Java内部类

内部类

通常情况

一个 Java 文件中只有一个主类,也就意味着下面这样是错误的:

// 编译器会报错,一个 java 文件中只能有一个被 public 修饰的类,并且该类的类名与 java 文件名一致(Outer.java)
public class Outer{
}
public class Other{
}

将第二个类的 public 权限修饰符删除,就可以在 java 文件中定义多个类
并且每个类都可以被访问到

内部类的结构

内部类,顾名思义,就是 java 一个类中定义另一个类,如下所示:

public class Outer{
	class Inter{
	}
}

创建内部类

内部类在实例化的时候偷偷保留了指向外部类的引用。因此在创建内部类对象的同时,必须先创建外部类对象(静态内部类除外)

  • 通过外部类中的方法得到内部类
public class Outer{
	public Inter inter() {
		return new Inter();
	}
	class Inter{
	}
	public static void main(String[] args) {
		Outer outer = new Outer();
		Inter inter = outer.inter();
	}
}
  • 内部类对象通过 外部类对象的 .new 方法创建
public class Outer{
	class Inter{
	}
	public static void main(String[] args) {
		// 通俗易懂的创建方式
		Outer outer = new Outer();
		Outer.Inter inter0 = outer.new Inter();
		// 一次创建完毕
		Inter inter1 = new Outer().new Inter();
		Outer.Inter inter2 = new Outer().new Inter();
	}
}

内部类对象通过 外部类.this 方法得到父类

public class Outer{
	class Inter{
		Outer getOuter() {
			return Outer.this;
		}
	}
	public static void main(String[] args) {
		Outer outer1 = new Outer();
		Outer.Inter inter = outer1.new Inter();
		Outer outer2 = inter.getOuter();
		// 两个对象是同一个
		System.out.println(outer1 == outer2);	// true
	}
}

内部类的特点

内部类默认可以访问外部类中所有的成员

public class Outer{
	Object[] items = new Object[2];
	private int index = 0;
	class Inter{
		public void add(String s) {
			// 在Inter类中,可以访问到外部的private成员变量
			if (index<items.length) items[index++]=s;; 
		}
	}
	public static void main(String[] args) {
		Outer outer = new Outer();
		Outer.Inter inter = outer.new Inter();
		inter.add("元素一");
		inter.add("元素二");
		System.out.println(outer.items[1]);	// print:元素二
	}
}

内部类与向上转型

将内部类声明为private或者protected。同时,在创建内部类实例对象的时候,通过内部类的父接口来声明对象变量,这样一来,客户端程序员就只能访问接口中定义的公共方法。因而实现了对接口实现过程代码的隐藏。

public class Outer{
	public Inter inter() {
		return new Inter();
	}
	interface People{
		void speak();
	}
	class Inter implements People{
		public void speak() {
			System.out.println("这是接口中的一个方法");
		}
		public void sleep(){
		}
	}
	public static void main(String[] args) {
		// 程序员无法访问到内部类实现的接口以外的方法
		Outer outer = new Outer();
		People inter = outer.inter();
		inter.speak();
		// inter.sleep()	访问不到
	}
}

在方法中和作用域内的内部类

内部类可以在方法里面或者在任意的作用域中定义内部类。

匿名内部类

看起来就像创建类对象的时候,同时在这里插入该类的定义。

用的比较多的: new 接口(){ 接口的实现 },这样就不用再定义具体的一个实现类了

public class Outer{
    // 接口
	interface Inter{
		void speak();
	}
	public Inter inter() {
        // 返回的时候,将接口实现
		return new Inter(){
			public void speak() {
				System.out.println("hello");
			}
		};
	}
}

嵌套类(静态内部类)

使用 static 修饰的内部类就是嵌套类了。内部类不依赖于外部类对象,没有 .this方法,普通内部类中不能有static方法或成员和嵌套类。而嵌套类里边可以有static方法和成员,也可以继续嵌套一个类

public class Outer{
	static class Inter{
		static String des = "静态成员变量";
		static void speak() {
			System.out.println("静态方法");
		}
		static class InterInter{
			static {
				String des = "嵌套类中的嵌套类";
			}
		}
	}
	public static void main(String[] args) {
		Inter.speak();
	}
}
  • 接口内部的嵌套类
    接口中的类都会被声明为public,static。可以通过在接口内部写一个嵌套类,并且在这个嵌套类中创建公共代码

每个类中测试的时候都需要主方法,但是你可以在一个嵌套类中定义一个main方法,这样外部类在解析这个嵌套类的时候会执行其中的静态main方法,从而外部类不用特意写个主方法了

  • 无论嵌套多少层都没事,嵌套类总能访问外部类的成员(无论其访问修饰符是什么),最里层的嵌套类可以访问外层的所有成员

为什么使用内部类

每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否及经济成了某个(接口的)实现,对于内部类都没有影响

  • 可以解决多重继承问题
  • (闭包与回调)通过内部类提供闭包的功能是优良的解决方案,他比指针更灵活、更安全。

闭包(closure)是一个可调用的对象,他记录了一些信息,这些信息来自创建它的作用域。

  • 内部类和控制框架
    每个内部类都可以独立地实现一个action
    内部类可以很容易访问外围类的任意成员
原文地址:https://www.cnblogs.com/llf7/p/12996847.html