局部内部类的final问题与匿名内部类
局部内部类的final问题
package demo02; /* 局部内部类,如果希望访问所在方法的局部变量,那么这个局部变量必须是【有效final的】。 备注:从Java 8+开始,只要局部变量事实不变,那么final关键字可以省略。 原因: 1. new出来的对象在堆内存当中。 2. 局部变量是跟着方法走的,在栈内存当中。 3. 方法运行结束之后,立刻出栈,局部变量就会立刻消失。 4. 但是new出来的对象会在堆当中持续存在,直到垃圾回收消失。 */ public class MyOuter { public void methodOuter() { int num = 10; // 所在方法的局部变量 class MyInner { public void methodInner() { System.out.println(num); } } } }
匿名内部类
匿名内部类 :是内部类的简化写法。它的本质是一个 带具体实现的 父类或者父接口的 匿名的 子类对象。
开发中,最常用到的内部类就是匿名内部类了。以接口举例,当你使用一个接口时,似乎得做如下几步操作,
1. 定义子类
2. 重写接口中的方法
3. 创建子类对象
4. 调用重写后的方法
我们的目的,最终只是为了调用方法,那么能不能简化一下,把以上四步合成一步呢?匿名内部类就是做这样的快
捷方式
前提
匿名内部类必须继承一个父类或者实现一个父接口
格式
new 父类名或者接口名(){ // 方法重写 @Override public void method() { // 执行语句 } };
使用方式
以接口为例,匿名内部类的使用,代码如下:
定义接口:
public abstract class FlyAble{ public abstract void fly(); }
创建匿名内部类,并调用:
public class InnerDemo { public static void main(String[] args) { /* 1.等号右边:是匿名内部类,定义并创建该接口的子类对象 2.等号左边:是多态赋值,接口类型引用指向子类对象 */ FlyAble f = new FlyAble(){ public void fly() { System.out.println("我飞了~~~"); } }; //调用 fly方法,执行重写后的方法 f.fly(); } }
通常在方法的形式参数是接口或者抽象类时,也可以将匿名内部类作为参数传递。代码如下:
public class InnerDemo2 { public static void main(String[] args) { /* 1.等号右边:定义并创建该接口的子类对象 2.等号左边:是多态,接口类型引用指向子类对象 */ FlyAble f = new FlyAble(){ public void fly() { System.out.println("我飞了~~~"); } }; // 将f传递给showFly方法中 showFly(f); } public static void showFly(FlyAble f) { f.fly(); } }
以上两步,也可以简化为一步,代码如下:
public class InnerDemo3 { public static void main(String[] args) { /* 创建匿名内部类,直接传递给showFly(FlyAble f) */ showFly( new FlyAble(){ public void fly() { System.out.println("我飞了~~~"); } }); } public static void showFly(FlyAble f) { f.fly(); } }
定义一个接口
package demo03; public interface MyInterface { void method1(); // 抽象方法 void method2(); }
package demo03; public class MyInterfaceImpl implements MyInterface { @Override public void method1() { System.out.println("实现类覆盖重写了方法!111"); } @Override public void method2() { System.out.println("实现类覆盖重写了方法!222"); } }
package demo03; /* 如果接口的实现类(或者是父类的子类)只需要使用唯一的一次, 那么这种情况下就可以省略掉该类的定义,而改为使用【匿名内部类】。 匿名内部类的定义格式: 接口名称 对象名 = new 接口名称() { // 覆盖重写所有抽象方法 }; */ public class DemoMain { public static void main(String[] args) { // MyInterface obj = new MyInterfaceImpl(); // obj.method(); // MyInterface some = new MyInterface(); // 错误写法! // 使用匿名内部类,但不是匿名对象,对象名称就叫objA MyInterface objA = new MyInterface() { @Override public void method1() { System.out.println("匿名内部类实现了方法!111-A"); } @Override public void method2() { System.out.println("匿名内部类实现了方法!222-A"); } }; objA.method1(); objA.method2();