java基础-内部类

在这里插入图片描述
内部类拥有外围类所有元素的访问权限。仍然是独立的类,编译后会有单独的.class文件,命名是:外部类类名$内部类类名.class。
内部类是外部类的成员,外部类可以直接类名访问,其他类访问内部类要加外部类的名称。内部类和外部类不能重名。
如果把内部类声明成静态的,那么内部类不能随便访问外部类的成员变量,只能访问外部类的静态成员变量。
外部类只有两种访问级别:public和默认,内部类则有四种。
内部类可以嵌套,最外层的成为顶层类。

public class DbApplicationTests {
    public static class InnerClass{
        public int getSum(int x, int y) {
            System.out.println(a);
            //System.out.println(b); b不是静态变量,所以无法访问的。
            return x+y;
        }
    }
    public int b = 20;
    public static final int a = 10;
    @Test
    public void contextLoads() {
           // 测试本类的内部类,直接访问即可
        InnerClass i = new InnerClass(); // 10
        System.out.println(i.getSum(1, 2)); // 3
                 // 另一个
        Show s = new Show(3, 4); 
        s.testFather(); // Show.testFather: 3*4
        // Square.FatherInClass: 3*4   
    }
}

由于Shape里width和height是protected,所以Shape的子类Square、Square的子类Show都可以直接使用width和height而不需要加限定符。
在Square里添加一个内部类:

protected class FatherInClass {
        public void func() {
            System.out.println("Square.FatherInClass: "+width+"*"+height);
        }
    }
// Show继承了Square:
public class Show extends Square{
    public Show(int width, int height) {
        super(width, height);
    }
    public void testFather() {
               // 这里是外部访问Square的内部类,需要实例化
        Square.FatherInClass fi = new Square(width, height).new FatherInClass();
        System.out.println("Show.testFather: "+width+"*"+height);
        // 有FatherInClass的实例了
        fi.func();
    }
}

实例内部类

没有static修饰的内部类。

  1. 外部类的静态方法和外部类以外的类中,需要先创建外部类实例再创建内部类实例。在外部类的非静态方法和另一个内部类中,都不需要创建外部类实例,直接new内部类实例即可。
  2. 如果有多层嵌套,内部类是可以访问所有外部类的成员的。
  3. 外部类中不能直接访问内部类的成员,必须通过内部类的实例去访问。如果类A包含类B,类B包含类C,那么A访问C要通过B的实例。
  4. 在实例内部类中不能定义static成员,除非同时使用final和static修饰。

静态内部类

用static修饰的内部类。

  1. 创建静态内部类的实例时,不需要创建外部类的实例(创建内部类实例还是要加外部类的类名的)。
  2. 静态内部类中可以定义静态成员和实例成员。外部类外的其他类可以通过完整类名访问静态成员,实例成员则需要静态内部类的实例。
  3. 静态内部类可以访问外部类的静态成员,如果要访问外部类的实例成员,需要外部类的实例去访问。
    目录

局部内部类

在一个方法中定义的内部类。

  1. 不能使用访问控制修饰符和static修饰,只能写class XXX{}。它可以有内部类,但是也不能有这些修饰。
  2. 不能定义static成员。
  3. 在局部内部类中可以访问外部类的所有成员。
  4. 在局部内部类中只能访问当前方法中的final成员。如果方法中的成员与外部类的某成员同名,那么访问外部类中那个成员可以用 外部类名.this.成员名 。
public class Test {
    int a=0;
    int d=0;
    public void method() {
        int b=0;
        final int c=0; // final型才能在Inner中被访问
        final int d=10;
        class Inner {
            int a2=a;    //直接访问外部类中的成员
            //intb2=b;    //编译出错
            int c2=c;    //访问方法中的成员
            int d2=d;    //访问方法中的成员
            int d3=Test.this.d;    //访问外部类中的成员
        }
        Inner i=new Inner(); // 需要实例
        System.out.println(i.d2);    //输出10
        System.out.println(i.d3);    //输出0
    }
    public static void main(String[] args){
        Test t=new Test();
        t.method();
    }
}

利用内部类实现多重继承

内部类可以继承一个与外部类无关的类,所以才可以多重继承。
举例:

Father.java
public class Father {
    public int strong() {
        return 9;
    }
}
Mother.java
public class Mother {
    public int kind() {
        return 8;
    }
}
// 现在制造一个Son类去继承这两个类:
public class Son {
    class Father1 extends Father { // 此内部类继承了Father
        public int strong() {
            return super.strong() + 1;
        }
    }
    class Mother1 extends Mother { // 此内部类继承了Mother
        public int kind() {
            return super.kind() - 2;
        }
    }
    public int getStrong() {
        return new Father1().strong(); // 用一个实例去调用成员函数
    }
    public int getKind() {
        return new Mother1().kind();
    }
}
// 测试:
Son s = new Son();
System.out.println(s.getStrong()); // 10
System.out.println(s.getKind()); // 6

匿名类

没有类名的内部类,它的任务是继承一个类,重写它的方法;或者实现一个或多个接口。既然是内部类,就可以放在类中也可以放在方法中了。注意各种访问控制。匿名类中允许使用非静态代码块初始化成员。

public class DbApplicationTests {
    private void show() { // 这是一个方法
        Out ac = new Out() { // 这个匿名类要继承类Out
            int i;
            { // 非静态代码块
                i = 10; // 成员初始化
            }
            void show() { // 重写了Out.show()
                System.out.println("annoymous.show()");
            } // 只能访问DbApplicationTests.show()中的final变量
        }; // 这个分号不要漏了
        System.out.println("show()");
        ac.show(); // 前面只是匿名类的定义,这里还需要调用一下
    }
    @Test
    public void contextLoads() {
        show();      
    }
}
// 匿名类继承的Out类:
public class Out {
    void show() {
        System.out.println("Out.show()");
    }
}
// 所以最后输出是:
show()
annoymous.show()
// 实现了重写。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值