内部类应用场景
描述事物A时,发现需要在事物A内部,封装一个能访问A属性等数据的事物B来只服务于事物A。
即如果一个类附属于另一个类且只应用于这个类,则可以用内部类,比如Android的Adapter里的ViewHolder。
使用内部类的优势
-
可以把内部类隐藏在外部类内,不允许同一个包中的其他类访问该类。
-
内部类定义于外部类的成员变量位置,因此内部类可以使用任意访问控制符,如 public 、 protected 、 private 等,同时也可以访问外部类任意数据。
-
内部类隐式的持有了一个外部类的引用,所能用外部类全部属性,要想打破引用就要用静态内部类。
-
可以实现多重继承。
成员内部类
public static void main(String[] args) {
Outer.Inner inner = new Outer().new Inner();
inner.test();
}
class Outer {
public int i = 1;
class Inner {
public int i = 2;
public void test() {
System.out.println("避免就近原则,调用外部类同名变量" + Outer.this.i);
}
}
}
静态内部类
public static void main(String[] args) {
Outer.Inner inner = new Outer.Inner();//注意调用方式
inner.test();
}
class Outer {
public static int i = 1;
static class Inner {
public void test() {
System.out.println("静态内部类只能引用外部类的静态成员" + i);
}
}
}
局部内部类
class Outer {
public void test() {
class Inner {
public void innerTest() {
System.out.println("InnerTest" );
}
}
Inner inner = new Inner();
inner.innerTest();
}
}
//调用内部类方式
Outer outer = new Outer();
outer.test();
局部内部类访问局部变量问题
class Outer {
int num = 3;
public void test() {
//JDK低于1.8
//final int x = 9;
//JDK1.8
int x = 9;
class Inner {
public void show() {
System.out.println("Inner...." + x);
}
}
Inner inner = new Inner();
inner.show();
}
}
如果你的JDK为1.8以下,想访问就要把局部变量声明成final,而1.8后的JDK不需要(JDK1.8帮你隐藏了,实际还是存在final)。
至于为什么访问就要把局部变量声明成fianl?
因为局部变量的生命周期是一旦出作用域就马上被释放,然而这时new Inner这个对象还在等待Java垃圾回收机制来回收并没有马上释放消失,相应的它内部访问局部变量也没有消失。
如此给人的感觉就是这个局部变量的生命周期延长了,这就违背Java的设计原则了。
所以Sun想了解决方案,如果一个局部内部类访问一个局部变量的时候,那就让该局部内部类访问该局部变量的复制品。
如此什么复制品?
完全一样的才是复制品。
为了保证值完全一样不能随意变换,所以这个变量要声明成final。
匿名内部类
-
没有类名的类就称作匿名内部类,只是没有类名,类的其他成员都具备。
-
匿名内部类的好处
简化书写,能尽快的释放空间(作为实参传值,出作用域就释放)。
继承方式的匿名内部类
abstract class Demo {
public abstract void read();
}
public class Run {
public static void main(String[] args) {
//注意这里创建的是继承Demo类的子类对象
new Demo() {
@Override
public void read() {
System.out.println("Read");
}
}.read();
}
}
如果想通过匿名内部类实现调用多个方法,需要将返回值设为基类
abstract class Demo {
public abstract Demo read();
public abstract Demo write();
}
public class Run {
public static void main(String[] args) {
// 注意这里是继承Demo类的对象
new Demo() {
@Override
public Demo read() {
System.out.println("Read");
return this;
}
@Override
public Demo write() {
System.out.println("Write");
return this;
}
}.read().write();
}
}
如果匿名内部类中定义了其特有的方法,想都不要想调用,不明白的去看我写的多态篇找原因。
实现方式的匿名内部类
//接口
interface Demo {
void read();
}
//测试类
class Test {
public void test() {
//注意:这是匿名的接口实现类对象,不是接口new。
new Demo() {
@Override
public void read() {
System.out.println("read");
}
}.read();
}
}
public class Run {
public static void main(String[] args) {
Test test = new Test();
test.test();
}
}
在实际开发中匿名内部类一般用于实参
-
假设有一个函数的形参需要传一个接口类的实参,这个实参仅在用时调用。
-
如果专门去写一个实现类是不是太low,那么这时候就可以用上匿名内部类。
interface Demo {
void read();
}
public class Run {
public static void main(String[] args) {
test(new Demo() {
@Override
public void read() {
System.out.println("Read");
}
});
}
public static void test(Demo demo) {
demo.read();
}
}
网友评论