• Java

Java基础--内部类

普通内部类

如果一个类只需要在另一个类内部使用,可以考虑将它写成内部类。

内部类拥有其外部类所有成员的访问权,因为内部类中隐含了一个外部类的引用,可通过 OuterClass.this 获得。

普通内部类中不可定义static的字段,除非它是final的。

利用内部类可以实现类似“多继承”,因为内部类继承哪个父类或实现哪些接口都与外部类无关。

若内部类为private,外界将完全不可见,只有外部类可见。

若内部类为public,可通过外部类对象.new关键字获得。

interface ForInner1 {
    void printSomething();
}
class OutClass {
    private int id;
    private String name;

    public OutClass() {
    }

    public OutClass(int id, String name) {
        this.id = id;
        this.name = name;
    }

    private class Inner1 implements ForInner1 {
        private String info; // 自己的成员

        @Override
        public void printSomething() {
            info = "hello";
            System.out.println(id + "-" + name + "-" + info);
            // 通过Outer.this返回其外部类引用
            System.out.println(OutClass.this);
        }
    }

    public class Inner2 {
        public void printMe() {
            System.out.println(this);
        }
    }

    public Inner1 getInner1() {
        return new Inner1();
    }
}
public class NormalNestedClassTest {
    public static void main(String[] args) {
        OutClass outClass = new OutClass(10, "boy");
        // 错误 Inner1不可见
        // OutClass.Inner1 in1 = outClass.getInner1();
        // 错误 Inner1不可见
        // outClass.getInner1().printSomething();
        // 可通过接口访问
        ForInner1 inner1 = outClass.getInner1();
        inner1.printSomething();

        OutClass.Inner2 inner2 = outClass.new Inner2();
        inner2.printMe();
    }
}

输出:

10-boy-hello
demos.innerClass.OutClass@7852e922
demos.innerClass.OutClass$Inner2@4e25154f

静态内部类

如果不需要内部类与外部类的对象有关联,可以使用静态内部类

静态内部类与普通内部类非常不同,若为public的,则与普通的静态类无异。

静态内部类不能访问外部类的非静态成员,不隐含外部类对象的引用。

class OuterClass {
    private static String name="OuterClass";
    //在外部类中使用静态内部类
    private Nest1 nest1 = new Nest1();

    public void printNest1(){
        nest1.print();
    }
    private static class Nest1 {
        public void print() {
            // 只能访问外部类的静态成员
            System.out.println(this +" name:"+ name);
        }
    }
    public static class Nest2 {
        Nest2(){
            System.out.println(this);
        }
    }
}
public class StaticNestedClassTest {
    public static void main(String[] args) {
        OuterClass out1 = new OuterClass();
        OuterClass out2 = new OuterClass();
        out1.printNest1();
        out2.printNest1();
        // public静态内部类 无需外部类即可创建
        OuterClass.Nest2 nest2 = new OuterClass.Nest2();
    }
}

匿名内部类

这种方式将类的声明和实现放在了一起,并且省略了类名。

但是需要一个接口或父类来描述。

//内部类 接口
interface Iinner {
    void printSomething();
}
// 匿名内部类 父类
class Finner {
    String name;
    Finner() {
    }
    Finner(String name) {
        this.name = name;
    }
    public void printSomething() {
        System.out.println(this + " name:" + name);
    }
}
class Outer {

    // 匿名内部类1 实现接口,然后返回
    public Iinner getInner1() {
        return new Iinner() {
            @Override
            public void printSomething() {
                System.out.println("同一接口的第一种实现");
            }
        };
    }

    //或者 实现接口而后调用
    //等同于父类不实现,交由匿名内部类实现,这样可限制父类的类型
    //另一个意义 可实现同一个接口的不同实现
    public void printThing(){
        new Iinner(){
            @Override
            public void printSomething() {
                System.out.println("同一接口的第二种实现");
            }
        }.printSomething();
    }

    // 匿名内部类2  继承一个父类
    // 可通过父类构造函数传递参数到匿名内部类内部
    public Finner getInner2(String name) {
        Finner a= new Finner(name) {
            //隐秘的复写了父类的方法
            @Override
            public void printSomething() {
                System.out.println("I am "+name);
            }
            public void say(){
                //无法被调用
            }
        };
        return a;
    }

    // 匿名内部类3 直接传参到匿名内部类内部 参数为final
    public Finner getInner3(String str) {
        return new Finner() {
            private String s = str;
            public void printSomething() {
                System.out.println(s);
            }
        };
    }
}
public class InnerTest {
    public static void main(String[] args) {
        Outer out = new Outer();
        out.getInner1().printSomething();
        out.printThing();

        out.getInner2("tom").printSomething();
        out.getInner3("hehe").printSomething();
    }
}

输出:

同一接口的第一种实现

同一接口的第二种实现

I am tom

hehe

多继承

class Pen {
    protected String name = "pen";
    {System.out.println("I have a pen");}
}

class Apple {
    protected String name = "apple";
    {System.out.println("I have an apple");}
}

public class ApplePen {

    private class C1 extends Pen {}
    private class C2 extends Apple {}

    public void haha() {
        C1 c1 = new C1();
        C2 c2 = new C2();
        System.out.println("en " + c2.name +"-"+ c1.name);
    }

    public static void main(String[] args) {
        ApplePen ap = new ApplePen();
        ap.haha();
    }
}

内部类产生 Outer$Inner.class

匿名内部类产生 Outer$1.class


相关

最新