1 抽象
abstract class 类名{
//方法(实现的,抽象方法)
//属性
}
1.1抽象类的细节
1).抽象类不能被实例化
2).可以有不是抽象的方法
3).一旦包含了abstract方法,则这个类必须声明为abstract
4).只能修饰类和方法
5).抽象方法不能有主体({})
6.一个类继承了抽象类必须实现抽象类的所有方法
7.不能和private、final、static一起用
1.2抽象模板设计模式
多个类实现同一个功能,设置一个抽象父类,将方法的代码提为一个方法A,不同的代码部分用抽象方法B表示,把该抽象方法B插入A方法,子类在继承该抽象类时,只用重写B方法即可,动态绑定机制,调用方法A就可以
//eg:设计一个抽象类Template:
//1).编写方法calculateTime(),可以计算某段代码的耗时
//2).编写抽象方法code
//3).编写一个子类Sub,继承抽象类Template,并实现code方法
abstract class ChouMoBan{ public abstract void code();//抽象方法 public void calTime(){ long start=System.currentTimeMillis(); code(); long end= System.currentTimeMillis(); System.out.println("耗时:"+(end-start)); } }
2 接口
2.1接口
给出一些没有实现的方法,封装到一起,到某个类要使用的时候,再根据具体的情况把这些方法写出来
interface 接口名{//属性
//方法(抽象、static、default)
}
class 类名 extends 类名 implements 接口,接口{
//自己的属性;
//自己方法;
//必须实现的接口的抽象方法
}
JDK8.0后,接口类中可以有抽象、静态方法、默认方法,接口可以有方法的具体实现(抽象[可以不写abstract]、static、default)
2.2接口的细节
1).接口不能被实例化
2).接口中的所有方法都是public方法,接口中的抽象方法可以不用abstract修饰
3).一个普通类实现接口,必须实现接口的所有方法
4).抽象类实现接口可以不用实现接口的方法
5).一个类可以同时实现多个接口
6).接口中的属性只能是public static final
7).接口中属性的访问形式:接口名.属性名
8).一个接口不能继承其他的类,但是可以继承多个别的接口,接口和接口的关系是继承,类与接口的关系是实现
9).接口的修饰符只能是public和默认,和类的修饰符一样
2.3接口的多态
形参是接口类型,可以接受实现接口的类的对象实例;接口类型的变量,可以指向实现了该接口的类的对象实例(类比对象的多态)
eg:
IF if=new Car();
interface IF{}
class Car implements IF{}
2.4接口类型的数组
类比继承的多态数组
2.5接口的多态传递
interface IH{}
interface IG extends IH{}
class Teacher implements IG{}
IH ih=new Teacher();
2.6接口VS继承
1).继承是当子类继承父类,自动拥有父类的功能,如果子类要扩展功能,通过实现接口的方式扩展
2).实现接口是对Java单继承机制的一种补充
3).接口一定程度上实现代码解耦[即:接口规范性+动态绑定]
3 内部类
3.1概念
一个类的内部又完整的嵌套了另一个类结构。被嵌套的类叫做内部类,外层的叫外部类,类的第五大成员【构造器,属性,方法,代码块,内部类】。可以直接访问私有属性,并且可以体现类与类之间的包含关系。
基本语法:
class Outer{//外部类 class Inner{//内部类 } } class Other{//外部其他类 }
3.2内部类的分类
定义在外部类局部位置上(方法体中):1.局部内部类(有类名)2.匿名内部类(没有类名)定义在外部类的成员位置上:1.成员内部类(没有static修饰)2.静态内部类(使用static修饰)
3.3局部内部类
定义在外部类的局部位置,通常在方法代码块中,本质任然是一个类
基本语法:
public void print(){ class 类名{ 类体} }
1).可以直接访问外部类的所有成员,包括私有的
2).不能添加访问修饰符,因为它的地位就是一个局部变量,不可以使用修饰符,但是可以使用final,因为局部变量也可以使用final,局部内部类可以被局部内部类继承
3).作用域:仅仅在定义它的方法或代码块中
4).外部类可以在方法中new内部类的对象,然后调用即可,因为局部内部类的作用域只是局部的,无法在方法外创建
5).如果外部类和局部内部类的成员重名时,在局部内部类中使用默认遵循就近原则,如果想访问外部类的成员,可以使用(外部类名.this.成员)去访问
3.4匿名内部类
定义在外部类的局部位置,比如方法中,并且没有类名,本质是类,内部类,该类没有名字,同时还是一个对象,new 接口一般为了简化开发,只用一次的,底层是implenments extends;new 类若写了方法会覆盖原来的方法,底层是extends
基本语法:
new 类或接口(参数列表){ 类体}; eg. Ia ia=new Ia() {//编译类型是接口Ia,运行类型是匿名内部类(底层会分配一个类名一般含$,getClass()可以查看到运行类型) @Override public void print() { //实现方法体; } }; interface Ia{ public void print(); }
1).两种调用匿名内部类的方法:ia.方法名();new Ia(){
}.方法名();
2).作用域:仅仅在定义它的方法或代码块中,相当于局部变量
3).可以直接访问外部类的所有成员,包括私有的
4).如果外部类和局部内部类的成员重名时,在局部内部类中使用默认遵循就近原则,如果想访问外部类的成员,可以使用(外部类名.this.成员)去访问
5).可以当作实参直接传递,简洁高效
3.5成员内部类
定义在外部类的成员位置,并且没有static修饰
1).可以直接访问外部类的所有成员,包含私有的
2).可以添加任意访问修饰符(public,protected,默认,private)
3).作用域相当于普通成员
4).使用成员内部类,在外部类中添加方法,new成员内部类;
Innerclass02.Inner inner=new Innerclass02().new Inner();
Innerclass02.Inner inner01=new Innerclass02().getInner();
外部类类名.内部类类名 对象名=new 外部类类名.内部类类名 /方法名();
5).如果外部类和局部内部类的成员重名时,在局部内部类中使用默认遵循就近原则,如果想访问外部类的成员,可以使用(外部类名.this.成员)去访问
3.6静态内部类
定义在外部类的成员位置,有static修饰
1).可以直接访问外部类的所有静态成员,包含私有的静态,不可以访问非静态的
2).可以添加任意访问修饰符(public,protected,默认,private)
3).作用域相当于普通成员,整个类体
4).使用成员内部类,在外部类中添加方法,new成员内部类;
或者:外部类类名.内部类类名 对象名=new 外部类类名.内部类类名 /方法名();
5).如果外部类和局部内部类的成员重名时,在局部内部类中使用默认遵循就近原则,如果想访问外部类的成员,可以使用(外部类名.成员)去访问
class Innerclass02{ private int a=0; private static int astatic=0; public class Inner{//成员内部类 public void print(){ System.out.println("成员内部类被调用"); } } public static class Inner02{//静态内部类 public void print02(){ // 只能访问静态的变量 System.out.println("静态内部类被调用"+a); System.out.println("静态内部类被调用"+astatic); } } public void newinner(){ Inner inner = new Inner(); inner.print(); } public Inner getInner(){ return new Inner(); } }
4 枚举
枚举:一种特殊的类,里面只包含一组有限的特定的对象,不可以继承其他类,因为已经隐式继承了Enum,可以implements
4.1自定义枚举
1).将构造器私有化,防止直接new,可以get,不要setXXX方法,防止被修改
2).在内部new,对枚举对象/属性使用final+static共同修饰,实现底层的优化
3).枚举对象名通常使用全部大写,常量的命名规范
4).根据需要,定义属性
4.2使用关键字enum实现枚举类
1).使用enum代替class
2).不用new,直接使用常量名(实参列表)
3).如果有多个常量对象,使用,间隔即可
4).如果有enum来使用枚举,将定义常量对象写在最前面
5).默认继承了java.lang.enum,底层还是枚举对象
enum Season2{//关键字实现枚举,将定义常量对象放在最前面用,间隔 SPRING ("春天","温暖"),SUMMER("夏天","炎热"),WHAT(); private String name; private String desc; // public static Season SPRING = new Season("春天","温暖"); // public static Season SUMMER= new Season("夏天","炎热"); Season2() { } private Season2(String name, String desc) { this.name = name; this.desc = desc; } public String getName() { return name; } public String getDesc() { return desc; } }
4.3Enum的成员方法
1).name():输出枚举对象的名字
2).ordinal():输出枚举对象的次序/编号,从0开始编号的
3).values():返回一个Enum类型的数组,包含所有的枚举对象
4).valueOf(“字符串”):将字符串转换成枚举对象,要求字符串为已有的对象,找到了就返回该枚举对象
5).compareTo(枚举对象):将两个枚举对象相比较,比较的是编号,返回两个编号的差
增强for循环:
for(数组类型 变量名:数组名){}:依次取出数组中的一个给变量,数组中取完了则退出循环