14、内部类

内部类

从开发角度来说,尽量不要使用内部类

内部类基本概念

1.内部类是指在一个类的内部定义其他的类。
范例:内部类

class Outer { // 外部类
    private String msg = "Hello World";

    class Inner { // 内部类
        public void print() {
            System.out.println(msg);
        }
    }

    public void fun() {
        // 实例化内部类对象,调用print()方法
        new Inner().print();
    }
}

public class Demo {
    public static void main(String[] args) {
        // 实例化外部类对象
        Outer out = new Outer();
        out.fun(); // 调用外部类方法,Hello World
    }
}

上述代码牺牲了程序的结构,实现了一个重要功能。
2.为说明内部类特点,现将内部类取出,作为一个单独的类,并要求实现与之前一样的功能。
范例:取出内部类

class Outer { 
    private String msg = "Hello World";

    public void fun() {
        new Inner().print();
    }
}

class Inner { 
    public void print() {
        System.out.println(msg);
    }
}

public class Demo {
    public static void main(String[] args) {
        Outer out = new Outer();
        out.fun(); // 报错,msg属于Outer,Inner无法调用
    }
}

(1)要想使得Inner调用msg,就需在Outer中写一个getMsg()

public String getMsg(){
    return this.msg;
}

(2)Inner要调用OutergetMsg()方法,必须实例化一个Outer对象

class Outer { 
    private String msg = "Hello World";

    public String getMsg(){
        return this.msg;
    }

    public void fun() {
        new Inner().print();
    }
}

class Inner {
    public void print() {
        System.out.println(new Outer().getMsg());
    }
}

public class Demo {
    public static void main(String[] args) {
        Outer out = new Outer();
        out.fun();
    }
}

上述的做法不合理,最好是将主方法中的Outer对象传递给Inner对象。

class Outer { 
    private String msg = "Hello World";

    public String getMsg() {
        return this.msg;
    }

    public void fun() {
        new Inner(this).print();
    }
}

class Inner {
    private Outer out;

    public Inner(Outer out) {
        this.out = out;
    }

    public void print() {
        System.out.println(this.out.getMsg());
    }
}

public class Demo {
    public static void main(String[] args) {
        Outer out = new Outer();
        out.fun();
    }
}

由此可得内部类的特点:

内部类可以直接访问外部类的私有属性和方法,外部类也可以通过内部类对象访问内部类的私有属性。

范例:访问内部类私有属性

class Outer { // 外部类
    private String msg = "Hello World";

    class Inner { // 内部类
        private  String info = "世界你好";
        public void print() {
            System.out.println(msg);
        }
    }

    public void fun() {
        // 实例化内部类对象
        Inner in = new Inner();
        // 使用内部类对象访问内部类私有属性
        System.out.println(in.info);
    }
}

public class Demo {
    public static void main(String[] args) {
        Outer out = new Outer();
        out.fun();
    }
}

3.观察代码

class Outer { // 外部类
    private String msg = "Hello World";

    class Inner { // 内部类
        private  String info = "世界你好";
        public void print() {
            System.out.println(this.msg); // 报错,找不到msg
        }
    }

    public void fun() {
        new Inner().print();
    }
}

报错原因this.msg指向的是Inner类,而Inner类中没有msg属性。因此要访问Outermsg属性,需要使用Outer.this.msg.

class Outer { // 外部类
    private String msg = "Hello World";

    class Inner { // 内部类
        public void print() {
            // 外部类.this = 外部类的当前对象
            System.out.println(Outer.this.msg); 
        }
    }

    public void fun() {
        new Inner().print();
    }
}

4.内部类的class文件名: Outer$Inner.class
直接实例化内部类对象语法:外部类.内部类 对象名 = new 外部类().new 内部类();
范例:实例化内部类对象

public class Demo {
    public static void main(String[] args) {
        Outer.Inner in = new Outer().new Inner();
        in.print();
    }
}

上述代码说明:

要想使用内部类对象,必须先实例化外部类对象。开发中一般是通过外部类访问内部类,不用创建内部类对象。

5.内部类只想被外部类使用,不能被外部调用,应使用private定义

class Outer { // 外部类
    private String msg = "Hello World";

    private class Inner { // 内部类
        public void print() {
            // 外部类.this = 外部类的当前对象
            System.out.println(Outer.this.msg);
       }
    }
}

static定义内部类

使用static定义的属性或方法不受实例化对象控制,因此使用static定义的内部类也不受外部类实例化对象控制。
1.static定义的内部类只能访问外部类中static定义的属性或方法

class Outer { // 外部类
    private String msg = "Hello World";

    static class Inner { // 内部类
        public void print() {
            System.out.println(msg); // 报错,无法引用非静态变量msg
        }
    }
}

2.static定义的内部类,相当于外部类
取得static定义的内部类对象语法:外部类.内部类 对象 = new 外部类.内部类();由该语法可知,static定义的内部类,不需要先实例化外部类对象,再实例化内部类对象,相当于内部类成了一个外部类。

class Outer { // 外部类
    private static String msg = "Hello World";

    static class Inner { // 内部类
        public void print() {
            System.out.println(msg);
        }
    }
}

public class Demo {
    public static void main(String[] args) {
        Outer.Inner in = new Outer.Inner();
        in.print();
    }
}

方法中定义内部类

1.内部类可定义在外部类中的任意位置。在方法中定义内部类是最常见的形式。

class Outer { // 外部类
    private String msg = "Hello World";

    public void fun() {
        class Inner { // 定义在方法中的内部类
            public void print() {
                System.out.println(msg);
            }
        }
        new Inner().print();
    }
}

public class Demo {
    public static void main(String[] args) {
        new Outer().fun();
    }
}

2.方法可以接收参数,也可以定义变量
范例:访问方法中定义的参数或变量

class Outer { // 外部类
    private String msg = "Hello World";

    public void fun(int num) { // 方法参数
        double score = 99.9; // 方法变量
        class Inner { // 定义在方法中的内部类
            public void print() {
                System.out.println("属性:" + msg);
                System.out.println("方法参数:" + num);
                System.out.println("方法变量:" + score);
            }
        }
        new Inner().print();
    }
}

public class Demo {
    public static void main(String[] args) {
        new Outer().fun(100);
    }
}

方法中的内部类可以访问方法中未用关键字修饰的参数或变量,该操作仅限于JDK1.8后!在JDK1.8之前的版本严格要求:方法中的内部类只能访问final标记的参数或变量,所以上述代码在JDK1.7前应该改为如下形式:

class Outer { // 外部类
    private String msg = "Hello World";

    public void fun(final int num) { // 方法参数
       final double score = 99.9; // 方法变量
        class Inner { // 定义在方法中的内部类
            public void print() {
                System.out.println("属性:" + msg);
                System.out.println("方法参数:" + num);
                System.out.println("方法变量:" + score);
            }
        }
        new Inner().print();
    }
}

匿名内部类

interface Message {
    public void print();
}

class Messagelmpl implements Message {
    public void print() {
        System.out.println("Hello");
    }
}

public class Demo {
    public static void main(String[] args) {
        fun(new Messagelmpl());
    }

    public static void fun(Message msg) {
        msg.print();
    }
}

假如Messagelmpl只使用一次,那么就可以利用匿名内部类。
范例:使用匿名内部类

interface Message {
    public void print();
}

public class Demo {
    public static void main(String[] args) {
        fun(new Message() {
            // 匿名内部类
            public void print() {
                System.out.println("Hello");
            }
        });
    }

    public static void fun(Message msg) {
        msg.print();
    }
}

使用匿名内部类的前提:必须基于接口或抽象类的应用。
匿名内部类定义在方法中,方法的参数或是变量要被匿名内部类访问,必须加上final关键字。匿名内部类的优点在于减少了类的定义。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值