Java内部类使用总结

一、内部类的定义和作用

将一个类定义在另一个类里面或者方法里面的类成为内部类。
作用和优点:每个内部类都能独立的继承一个接口的实现,所以无论外部类是否继承了某个接口的实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整。弥补了单继承的缺点

二、内部类的用法

1.成员内部类

成员内部类即为外部类的成员,非静态的。可以直接访问外部类的所有成员和方法,当有和内部类重名时需要用外部类.this.属性或方法。外部类访问内部类需要创建一个内部类的对象才可以访问。PS:成员内部类不能含有static的修饰符。因为内部类属于非静态的,先要创建外部类,才能创建它自己。成员内部类的修饰符可以是private,默认的,protected,public或者是静态的。和外部类(public和default)不同

public class Outer {

    public static void main(String[] args){
        Outer outer = new Outer();
        Outer.Inner inner = outer.getInner();
        inner.print("成员内部类第一次打印");
        inner = outer.new Inner();
        inner.print("这是一成员内部类");
    }

    public Inner getInner(){
        return new Inner();
    }

    public static void printOuter(){
        System.out.println("这是一个外部类");
    }

    public class Inner{
        public void print(String str){
            getInner();
            Outer.this.printOuter();
            System.out.println(str);
        }
    }
}

2.局部内部类

局部内部类定义在方法或作用域内部。

public class Part {

    public Destination print(String str){
        class a implements Destination{

            private String label;
            private a(String label){
                this.label = label;
            }
            public String read() {
                return label;
            }
        }
        return new a(str);
    }

    public static void main(String[] args){
        System.out.println(new Part().print("这是一局部内部类的事例").read());
    }
}

3.静态内部类

静态内部类可以让外部类随意访问,无需创建内部类的对象。静态内部类不能访问外部类的非静态成员,因为非静态成员必须是对象存在的时候,所以有矛盾。

public class Singleton2 {
    // 提供一私有构造函数
    private Singleton2(){};
    public Integer i;
    public static Singleton2 getInstance(){
        return SingletonHolder.instance;
    }

    private static class SingletonHolder{
        private static final Singleton2 instance = new Singleton2();
    }
}

4.匿名内部类

匿名内部类也可以进行实例初始化,虽然没有构造函数

public class Outer {

    public static void main(String[] args){
        Outer outer = new Outer();
        Outer.Inner inner = outer.getInner("Inner", "gz");
        System.out.println(inner.getName());
        System.out.println(inner.getProvince());
    }

    public Inner getInner(final String name, final String city){
        // 匿名内部类中使用
        return new Inner() {
            private String namString = name;
            private String province;
            // 实例初始化
            {
                if(city.equals("gz")){
                    province = "gd";
                }else {
                    province = "";
                }
            }

            public String getName() {
                return namString;
            }

            public String getProvince() {
                return province;
            }
        };
    }

    interface Inner{
        String getName();
        String getProvince();
    }
}

5.内部类的继承

注意的是继承内部类的类的构造函数默认传递外部类参数,并调用super方法,不然会有编译错误。

class InheritInner extends Outer.Inner {

    public InheritInner(Outer outer){
        outer.super();
    }

    public static void main(String[] args){
        new InheritInner(new Outer()).print("这是内部类继承");
    }
}

三、注意的问题

1.为什么成员内部类可以无条件的访问外部类成员:

首先要明确一点的是内部类和外部类是两份字节码,即Outer.class, Outer$Inner.class.
通过反编译字节码可以看出,内部类的构造器是无参构造函数,编译器会默认添加一个参数,改参数的类型为指向外部类对象的一个引用,所以成员内部类中的Outter this&0 指针便指向了外部类对象,因此可以在成员内部类中随意访问外部类的成员。

2.为什么匿名内部类和局部内部类只能访问局部的final。

public class Test {
    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();
    }
}

如上面的代码,因为是当test方法执行完毕之后,变量a的生命周期就结束了,而此时Thread对象的生命周期很可能还没有结束,那么在Thread的run方法中继续访问变量a就变成不可能了,但是又要实现这样的效果,怎么办呢?Java采用了 复制,也就说如果局部变量的值在编译期间就可以确定,则直接在匿名内部里面创建一个拷贝。如果局部变量的值无法在编译期间确定,则通过构造器传参的方式来对拷贝进行初始化赋值。 的手段来解决这个问题。复制的手段会带来一个问题,会导致数据不一致,所以采用final为不可变

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值