JAVA内部类介绍

原则:在拥有外部类对象之前是不可能创建内部类对象的。
因为内部类对象会暗暗地连接到创建它的外部类对象上。但是注意嵌套类(静态内部类)是不需要对外部类对象的引用。

内部类的使用1:(向上转型)

interface Destination{
    String readLabel();
}

interface Contents{
    int value();
}

class Parce{
    public class Testnew{
        public Parce outer(){
            return Parce.this;//外部类的.this用法
        }
    }
    
    protected class PDestination implements Destination{
        private String label;
        private PDestination(String str){
            label = str;
        }
        public String readLabel(){
            return label;
        }
    }
    
    //private 说明了在Parce类外部是无法访问内部类PContents
    private class PContents implements Contents{
        private int i = 5;
        public int value(){return i;}
    }
    
    public Destination getDestination(String str){
        return new PDestination(str);
    }
    
    public Contents getContents(){
        return new PContents();
    }
}

public class Test
{
    public static void main(String[] str){
        Parce p = new Parce();
        Contents c = p.getContents();
        Destination d= p.getDestination("test");
        
        //在外部访问public的内部类,必须有外部类实例
        Parce.Testnew t = p.new Testnew(); //OK
        //p.TestNew t = p.new TestNew();//ERROR
        //Parce.Testnew t = p.new Parce.Testnew();//ERROR  
    }
}

方法和作用域的内部类:(局部内部类)

interface Destination{
    String readLabel();
}

class Parce{
    //方法中的内部类
    /*
     PDestination类是getDestination方法中的一部分,而不是Parce类中的一部分。
     所以在getDestination之外是无法访问PDestination类的。
     都是这并不意味一旦getDestination方法执行完毕,PDestination就不可用了。
     */
    public Destination getDestination(String str){
        class PDestination implements Destination{
            private String label;
            private PDestination(String str){
                label = str;
            }
            public String readLabel(){
                return label;
            }
        }
        
        return new PDestination(str);
    }
    
    //作用域中的内部类
    private void intertest(boolean b){
        /* 
         IntertestA类嵌入if语句的作用域内,并不是说该类的创建时有条件的,它实际上和
         别的类一起编译过了
        */
        if (b){
            class IntertestA{
                private String id;
                IntertestA(String s){id = s;}
                String getID(){return id;}
            }
        
            IntertestA it = new  IntertestA("hello");
            String s = it.getID();
        }
        //IntertestA it = new  IntertestA("hello");//ERROR
        //超出了IntertestA类的作用范围
    }
    
    public void test() {intertest(true);}
}

public class Test{
    public static void main(String[] str){
        Parce p = new Parce();
        Destination d = p.getDestination("test");
        p.test();
    }
}

匿名内部类

interface Contents{
    int value();
}

class Parce{
    public Contents getContents(){
        return new Contents(){//匿名内部类:创建一个继承于Contents的匿名类的对象
            private int i = 5;
            public int value(){return i;}
        };
    }
}
public class Test{
    public static void main(String[] str){
        Parce p = new Parce();
        Contents c = p.getContents();
    }
}

实际上上面的匿名内部类结构等价于:

class Parce{
    class MyContents implements Contents{
        private int i = 5;
        public int value(){return i;}
    }

    public Contents getContents(){
        return new MyContents();
    }
}

匿名内部类初始化操作怎么处理
因为没有名字,所以不可能有构造器,所以我们利用实例初始化来做到和构造器相同的效果。

abstract class Base{
    public Base(int i){
        System.out.println("Base:i = " + i);
    }
    
    public abstract void f();
}

class Base1{
}

public class Test{
    //i只是传递给匿名内部类的基类的构造器,没有在匿名内部类中使用,所以i不用时final
    //如果在匿名内部类中使用参数就必须是final
    public static Base getBase(int i){
        return new Base(i){//匿名内部类
            {//内部类的实例初始化
                System.out.println("inside instance Base");
            }
            
            public void f(){
                System.out.println("Test f fun");
            }
        };        
    }
    
    //如果在匿名内部类中使用参数就必须是final来修饰传入的参数
    public Base1 testBase1(final int i){
        return new Base1(){
            private int j =i;
            public int getLabel(){return j;}
        };
    }
    public static void main(String[] str){
        Base b = getBase(47);
        b.f();
    }
}

//
输出:
Base:i = 47
inside instance Base
Test f fun

嵌套类(static内部类)和普通内部类区别
(1) 普通内部类隐式地保存了一个引用,指向创建它的外围对象(特殊的this引用),而嵌套类没有
(2) 要创建嵌套类的对象,并不需要其外围类的对象
(3) 不能从嵌套类的对象中访问非static的外围类对象
(4) 普通内部类不能有static数据和字段,但是嵌套类可以有。

内部类使用的必要性
1每个内部类都能独立继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。相对外围类继承接口,共享性好很多。
2接口解决了部分问题,而内部类有效的实现了”多重继承”

特性
1. 内部类可以有多个实例,每个实例都有自己的状态信息,并且与外围类对象的信息相互独立。
2. 在单个外围类中,可以让多个内部类以不同的方式实现同一个接口或继承同一个类
3. 创建内部类对象的时刻并不依赖外部类对象的创立。
4. 内部类没令人迷惑的”is-a”关系


使用局部内部类替代匿名内部类的情况
1.需要一个已命名的构造器或者需重载构造器,而匿名内部类只能实例初始化
2.需要不止一个该内部类的对象

内部类标示符:
一个类就会产生一个.class文件。
Test.class //Test类
Test$1.class //匿名内部类会产生一个简单的数字作为标示符
Parce$Pdestination.class //局部内部类直接在$后面加上类名就Ok了

原文地址:https://www.cnblogs.com/lijunamneg/p/2893161.html