java局部内部类,匿名内部类

局部内部类


可以将内部类定义在一个方法或者一个代码块内

public class A1 {
    private int age = 123;
    public static void main(String[] args) {
        A1 aa = new A1();
    }
    public void pp() {
        Date birth = new Date();
        // B1 bb=new B1();语法错误,要求局部内部类必须先定义后使用
        class B1 { // 局部内部类,只能在所在的{}范围中使用,具备内部类的范围限定词和临时变量一                //致,只能添加final或者abstract
            public void ff() {
                System.out.println(age);
                A1.this.age = 555;// 可以直接访问外部类中的成员
                System.out.println(birth);
                // 语法报错,在局部内部类中使用外部的临时变量,则外部临时变量必须是final的,只是final可以省略
                // birth = new Date();针对引用类型修改地址是不允许,但是可以修改属性
                System.out.println("B1...ff()");
            }
        }
        B1 bb = new B1();
    }
}

 局部内部类的特点:

  • 和外部类一样,它只是定义在外部类的某个方法中的另一个完整的类结构
  • 可以继承自己的想要继承的父类,实现自己想要实现的父接口们,和外部类的父类和父接口无关
  • 可以在局部内部类中声明属性、方法、构造器等结构,但不包括静态成员,除非是从父类继承 的或静态常量
  • 可以使用abstract修饰,因此它也可以被同一个方法的在它后面的其他内部类继承
  • 可以使用final修饰,表示不能被继承
  • 编译后有自己的独立的字节码文件,只不过在内部类名前面冠以外部类名、$符号、编号。
  • 这里有编号是因为同一个外部类中,不同的方法中存在相同名称的局部内部类
  • 和成员内部类不同的是,它前面不能有权限修饰符等
  • 局部内部类如同局部变量一样,有作用域
  • 局部内部类中是否能访问外部类的静态还是非静态的成员,取决于所在的方法
  • 局部内部类中还可以使用所在方法的局部常量,即用final声明的局部变量

JDK1.8之后,如果某个局部变量在局部内部类中被使用了,自动加final

问题: 

public class A1 {
    private int age = 123;
    public static void main(String[] args) {
        A1 aa = new A1();
    }
    public void pp() {
        static class B1 {//局部内部类不能是static
            static int age = 999;//不允许包含静态成员
            static{}
            public static void ff(){}
        }
    }
}

 注意:局部内部类需要先定义后使用,不能是先使用后定义

匿名内部类


匿名内部类就是内部类的简写格式 

public class A1{
    public void pp(){
        class B1 extends C1{}
    }
}
//简化写法
public class A1{
    public void pp(){
        new C1(){};//原始命名类的写法class B1 extends C1{} new B1();
    }
}
public class A1 {
    public void pp(){
        new Object(){
            public void ff(){ //ff方法在父类中没有定义,则只能直接调用
                System.out.println("anon inner class ... ff");
            }
        }.ff();
    }
    public static void main(String[] args) {
        A1 a1=new A1();
        a1.pp();
    }
}

下面写法使用较多

public class A1 {
    public void pp(){
        Object obj=new Object(){
            @Override//覆盖父类中定义的方法
            public String toString() {
                return ("anon inner class ... ff");
            }
            public void dd(){} //无法调用
        };
        System.out.println(obj.toString());//调用匿名内部类中覆盖定义的方法
    }
}

 匿名内部类的前提是必须继承或者实现一个外部类或者接口

new interfacename(){......};
new superclassname(){......};
如果父类中没有无参构造器,则()中应该有对应的参数
public class A1 {
    public void pp(){
        new B1(20){ //因为B1类中没有无参构造器,必须直接传入参数
        };
    }
}
class B1{
    private int age;
    public B1(int age){
        this.age=age;
    }
}
  • 匿名内部类由于没有名字,所以它没有构造函数
  • 如果这个匿名内部类继承了一个只含有带参数构造函数的父类,创建它的时候必须带上这些参数
  • 不能定义静态成员

匿名内部类的使用场景

当方法参数是接口类型时,而且接口中的方法不超过三个,可以用匿名内部类作为实际参数进行传递

匿名内部类的使用限制

  • 匿名内部类不能是抽象的
  • 匿名内部类不能定义构造器,默认和父类相似的构造器
  • JDK1.8-要求给局部内部类、匿名内部类访问的局部变量必须使用final修饰,从JDK1.8开始这个现 实被取消了,但是默认是final的(不能修改) 
public void pp() {
    final Date birth = new Date();
    class C1 {
        public void ff() {
            System.out.println(birth);
            birth.setYear(2000);// 3900
            // birth=new Date(); 语法报错
            System.out.println("modify year:" + birth);
        }
    }
    new C1().ff();
}

 nt等8种简单类型/Integer8种简单类型的包装类/String的使用中应该注意

内部类的使用场景和好处

  • 每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现, 对于内部类都没有影响。内部类使得多继承的解决方案变得完整
  • 方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏
public class 牛{
    private class 牛腿{}
}
  •  方便编写事件驱动程序
btn.addActionListener(new ActionListener() { //添加按钮对应的事件处理
    public void actionPerformed(ActionEvent e) {
        showNewWindow(mainWin);
    }
});
  •  方便编写线程代码。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值