Java 内部类

目录

一、成员内部类

二、局部内部类

三、匿名内部类


        在类中定义的类称为内部类,内部类又可以分为成员内部类(实例内部类、静态内部类)、局部内部类、匿名内部类等。

一、成员内部类

        成员内部类:在一个类中,与类成员变量、方法同级别的类,可以称为成员内部类。

实例内部类

public class Main {
    public static void main(String[] args) {
        Outer outer = new Outer("Outer"); // 实例化一个Outer
        Outer.Inner inner = outer.new Inner(); // 实例化一个Inner
        inner.hello();
    }
}

class Outer { // 定义一个外部类
    private String name;

    Outer(String name) {
        this.name = name;
    }

    class Inner { // 定义一个内部类
        void hello() {
            System.out.println("Hello, " + Outer.this.name);
        }
    }
}

Outer是一个外部类,而Inner是一个内部,它与外部类有个最大的不同,就是内部类的实例不能单独存在,必须依附于一个外部类的实例。

静态内部类

public class Main {
	public static void main(String[] args) {
		Outer.StaticNested sn = new Outer.StaticNested();
		sn.hello();
	}
}

class Outer {
	
	private static String NAME = "OUTER";

	private String name;

	Outer(String name) {
		this.name = name;
	}

	static class StaticNested {
		void hello() {
			System.out.println("Hello, " + Outer.NAME);
		}
	}
}

         用static修饰的内部类不依附于外部的实例,而是一个完全独立的类,因此无法引用外部类.this,但它可以访问外部类的private静态字段和静态方法。

二、局部内部类

        局部字面意思范围,例如在方法范围的类,就是一个局部内部类。

public class Main {
	public static void main(String[] args) {
		Outer outer = new Outer("Outer");
		outer.outerMethod();
	}
}

class Outer {
	
	static String name; // 内部类可以访问,
	
	public Outer(String name){
		this.name = name;
	}
	
	void outerMethod() {
		class Inner {
			public void innerMethod() {
				System.out.println(name);
			}
			
		}
		Inner n = new Inner();
		n.innerMethod();
	}

	 
}

        局部内部类与局部变量一样,不能使用访问控制修饰符(public、private 和 protected)和 static 修饰符修饰。

        局部内部类只在当前方法中有效。

三、匿名内部类

        匿名内部类:可以理解为隐藏了名字的内部类。

public class Main {
	public static void main(String[] args) {
		Outer outer = new Outer("Outer"); // 实例化一个Outer
		outer.asyncHello();
	}
}

class Outer { // 定义一个外部类
	private String name;

	Outer(String name) {
		this.name = name;
	}

	void asyncHello() {
		Runnable r = new Runnable() {
			@Override
			public void run() {
				System.out.println("Hello, " + Outer.this.name);
			}
		};
		new Thread(r).start();
	}

}

        在asyncHello()方法中,方法内部实例化了一个RunnableRunnable本身是接口,接口是不能实例化的,所以这里实际上是定义了一个实现了Runnable接口的匿名类,并且通过new实例化该匿名类,然后转型为Runnable。在定义匿名类的时候就必须实例化它,定义匿名类的写法如下:

Runnable r = new Runnable() {
    // 实现必要的抽象方法...
};

匿名类也完全可以继承自普通类

public class Main {
	 public static void main(String[] args) {
	        HashMap<String, String> map1 = new HashMap<String, String> ();
	        HashMap<String, String> map2 = new HashMap<String, String> () {}; // 匿名类!
	        HashMap<String, String> map3 = new HashMap<String, String> () {
	            {
	                put("A", "1");
	                put("B", "2");
	            }
	        };
	        System.out.println(map3.get("A"));
	    }
}

   map1是一个普通的HashMap实例,但map2是一个匿名类实例,只是该匿名类继承自HashMapmap3也是一个继承自HashMap的匿名类实例,并且添加了static代码块来初始化数据。观察编译输出可发现Main$1.classMain$2.class两个匿名类文件。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

2014Team

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值