Java内部类解析
Inner Class
Four Type:
-
Regular inner class 常规内部类
-
Static inner class 静态内部类
-
Method-local inner class 局部内部类
-
Anonymous inner class 匿名内部类
标在最前面 参考此博客+个人总结
总刚要:
Regular Inner Class 常规内部类
概念: inner类被声明在outer类里, 像outer类的一个成员。
创建内部类
//两种方法
outer obj=new outer();
outer.inner iobj= obj.new inner ();
//第二种方法
outer.inner in = new outer().new inner();
关于访问
成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。而外部类想访问成员内部类的成员却不是这么随心所欲了。在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问
一段资料解释 为什么成员内部类依赖外部类
for example:
不同访问修饰词:
如果内部class :
用private修饰 只有外部class可以访问。
用public修饰 任何地方都可以。
用protected修饰 同一个包或者继承外部类可以访问。
默认 则只有同一个package可以访问。
Static Inner Class 静态内部类
概念: 静态内部类声明在另一个类里的类, 只不过在类前多了一个关键字Static
静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。
声明:
//无需先new外部类
outer.inner obj=new outer,inner();
Method-Local InnerClass 局部内部类
概念: 定义在方法或者一个作用域里的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
实例这个类:
//例如在方法 display()内定义了一个类 print
void display() {
final String z = "local variable";
System.out.println(x); //x是外部类里的变量
class Inner {
public void print() {
System.out.println("Outer x: " + x);
System.out.println("Local variable z: " + z);
}
}
Inner obj = new Inner(); // 只能在方法内部访问
obj.print();
}
注意:
局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。但是可以被标记为abstract 或者 final。
Anonymous Inner Class 匿名内部类
概念:
匿名内部类没有名称,通常是另一个类的子类或接口的实现。匿名内部class是一个表达式
实现:
//例如抽象类的子类
abstract class person{
void print() {};
}
public class AnonymousClass {
public static void main(String[] args) {
person p=new person() { //匿名类 实现接口或者继承类
void print() {
System.out.println("AnonymousClass");
}
}; //有分号
p.print();
}
}
解释这段代码:
//此时匿名内部类是:
person p=new person() {
void print() {
System.out.println("AnonymousClass");
}
};
/*
1. 这个匿名类继承了person并提供了eat方法 名字由编译器决定。
2. 这个过程创建了匿名类对象 p。
*/
//这个匿名类由编译器生成为:
static class TestAnonymousInner$1 extends Person {
TestAnonymousInner$1(){}
void eat() {
System.out.println("nice fruits");
}
}
匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。
解释:为什么局部内部类和匿名内部类只能访问局部final变量?
例如如下代码:
public class AnonymousClass {
public static void main(String[] args) {
}
public void test(final int b) {
final int a = 10;
new Thread(){
public void run() {
System.out.println(a);
System.out.println(b);
};
}.start();
}
}
考虑两个问题( 如果a不是final型 ):
- 如果test类不存在 而Thread类以及存在 那么a是否存在?
- 如果Thread类中修改a的值 会出现什么情况?
解答:
- 为了解决两个类生命周期不一致的问题 而又要使得访问变量a不出现问题, java采用了复制的手段解决这个问题。也就说如果局部变量的值在编译期间就可以确定,则直接在匿名内部里面创建一个拷贝。如果局部变量的值无法在编译期间确定,则通过构造器传参的方式来对拷贝进行初始化赋值。 所以两个类中的a根本不是同一个变量
- 由1知 两个a不是同一个变量。如果修改一个地方的a 就会导致数据的不一致性。因此为了避免出现这样的情况 必须将a限制为final型,不允许对变量a进行更改(对于引用类型的变量,是不允许指向新的对象。这就解决了数据不一致的问题。
内部类使用的场景和好处
目前我还没体会到 先记下来
- 每个内部类都能独立的继承一个接口的实现 无论外部类是否继承过别的接口。所以内部类使得多继承的问题得以实现。
- 方便将有一定逻辑关系的类组织在一起 对外界隐藏
- 方便编写事件驱动程序
- 方便编写线程代码