内部类
内部类意义:
更好的封装:比如cow类,内部定义一个cowleg类,cowleg类只有在cow类里才有意义,不允许其他类访问cowleg类
内部类成员可以直接访问外部类的私有数据,但外部类不能访问内部类细节,如成员变量
匿名内部类适合创建仅需要使用一次的类
内部类比外部类多三个修饰符,private,protected,static,外部类不能使用这三个修饰符
非静态内部类不能拥有静态成员
通过OuterClass.this.var 访问外部类成员
通过this.var 访问内部类成员
静态内部类:
可以包含静态成员和非静态成员,根据静态成员不能访问非静态成员规则,静态内部类不能访问外部类的实例成员,只能访问类成员。即使是静态内部类的实例方法,也不能访问外部类的实例成员,只能访问静态成员。
编译后class文件名称是:outerclass.class,outerclass$innerclass.class
局部内部类(鸡肋):
把内部类放在一个方法里定义,这个内部类就是一个局部内部类。局部内部类仅在该方法里有效,所以也不能使用访问控制符合static修饰符。
编译后class文件名称是:outerclass.class,outerclass$1innerclass.class 多了个数字,用于区分不同方法中同名的局部内部类
java8改进的匿名内部类:
创建一个匿名内部类会立即创建一个该类的实例,这个类定义会立即消失,匿名内部类不能重复使用,格式:
new 实现接口 | 父类构造器(实参列表){匿名内部类实体部分}
匿名内部类必须实现一个接口或者继承一个父类,但两只只能取其一
匿名内部类两个规则:
匿名内部类不能是抽象类,因为系统在创建匿名内部类是,会立即创建匿名内部类的对象,因此不允许将匿名内部类定义成抽象类
匿名内部类不能定义构造器,因为匿名内部类没有类名,所以无法定义构造器,但可以定义初始化块,可以通过实例初始化块来完成构造器需要完成的事
最常用的创建匿名内部类的方式是需要创建某个接口类型的对象:
写法:
interface A{publice Double get();}
class B{
public void test(A a){a.get();}
publice static void main(String[] args){
B b = new B();
b.test(new A(){public Double get(){...}});
}
}
等同于
class C implements A{public Double get(){...}}
b.test(new C());
通过实现接口来创建匿名内部类时,匿名内部类不能显式的创建构造器,因此匿名内部类只有一个隐式的无参构造器,所以new 接口名后面的括号里不能有参数 w
通过继承父类来创建匿名内部类时,匿名内部类有和父类相似的构造器,这里的相似指拥有相同的形参列表
abstruct class A{public A(){} public A(String str){}}
class B{
public void test(A a){a.get();}
public static void main(String[] args){
B b = new B();
b.test(new A("asd"){...});
java8改进点:
java8前,要求局部内部类,匿名内部类访问的局部变量必须用final修饰,java8这个限制取消了,但是被访问的局部变量自动使用了final修饰,即别匿名内部类访问后,相当于final变量,不能再赋值
}
}