Java基础-内部类

前言

在java语言中,可以把一个类定义到另外一个类的内部,在类里面的这个类就叫内部类,外面的类就叫外部类。

成员内部类

顾名思义,成员内部类就是指一个类作为一个成员存在于另一个类的内部。这就成为成员内部类。如下:

public class ExterNal {
	class InsIde{	//内部类
		public void a () {
			System.out.println("a");
		}
	}
}

这样看起来InsIde类就像是ExterNal类的一个成员,ExterNal称为外部类。内部类可以访问外部类的所有成员属性和成员方法。包括private成员和静态成员。如下:

public class ExterNal {
	private int ExterNal_a = 1;
	private static int ExterNal_b = 2;

	private int a = 1;

	class InsIde { // 内部类

		private int a = 2;

		public void a() {
			System.out.println(ExterNal_a); // 外部类成员属性
			System.out.println(ExterNal_b); // 外部类静态成员属性
			
			// 但需要注意的是,当内部类和外部类存在同名属性或者方法时,内部类访问外部类同名属性或者方法需要按以下格式:
			System.out.println(ExterNal.this.a); // 访问外部类同名属性
		}
	}
}

虽然成员内部类可以无条件地访问外部类的成员,而外部类想访问成员内部类的成员却不是这么随心所欲了。在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问。包括私有化变量和方法也可以访问。

public class ExterNal {
	private int ExterNal_a = 1;
	private static int ExterNal_b = 2;

	private int a = 1;

	class InsIde { // 内部类

		private int a = 2;

		private void a() {
			System.out.println("a");
			System.out.println(ExterNal_a); // 外部类成员属性
			System.out.println(ExterNal_b); // 外部类静态成员属性

			// 但需要注意的是,当内部类和外部类存在同名属性或者方法时,内部类访问外部类同名属性或者方法需要按以下格式:
			System.out.println(ExterNal.this.a); // 访问外部类同名属性
		}
	}

	// 创建内部类对象
	public InsIde getInsIde() {
		return new InsIde();
	}

	
	public ExterNal() {
		//使用内部类对象访问内部类方法
		this.getInsIde().a();
		//使用内部类对象访问内部类属性
		System.out.println(this.getInsIde().a);
	}

}

成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。创建成员内部类对象的一般方式如下:

public static void main(String[] args) {
		
		/*创建内部类的两种方式*/
		// 第一种
		ExterNal exterNal = new ExterNal();
		ExterNal.InsIde insIde = exterNal.new InsIde();

		// 第二种
		ExterNal.InsIde insIde1 = exterNal.getInsIde();
	}

局部内部类

局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。

public class ExterNal {
	
	class b{
		
	}
	
	public void ExterNalFun() {
		//局部内部类
		class InsIde extends b{
			int a = 0;
		}
	}
}

需要注意的是局部内部类就像是方法里面的一个局部变量一样,是不能有 public、protected、private 以及 static 修饰符的。

匿名内部类

匿名内部类也就是没有名字的内部类,正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写。当然也仅能只继承一个父类或者实现一个接口。同时它也是没有class关键字,这是因为匿名内部类是直接使用new来生成一个对象的引用。当然这个引用是隐式的。

匿名内部类的基本实现。

public abstract class InsIde {
	public abstract void a () ;
}

public class ExterNal{
	
	public static void main(String[] args) {
		
		InsIde insIde = new InsIde() {
			@Override
			public void a() {
				// TODO Auto-generated method stub
				System.out.println("这是内部类中的方法---a");
			}
		};
		
		insIde.a();
	}
}

在接口上使用匿名内部类

public interfact class InsIde {
	public abstract void a () ;
}

public class ExterNal{
	
	public static void main(String[] args) {
		
		InsIde insIde = new InsIde() {
			@Override
			public void a() {
				// TODO Auto-generated method stub
				System.out.println("这是内部类中的方法---a");
			}
		};
		
		insIde.a();
	}
}

由上面的例子可以看出,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现。最常用的情况就是在多线程的实现上,因为要实现多线程必须j继承Thread类或是实现Runnable接口

Thread的匿名内部类实现

public class Demo {

	public static void main(String[] args) {
		Thread t = new Thread() {
			public void run() {
				for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
			}
		};
		
		t.run();
	}
}

Runnable的匿名内部类实现

public class Demo {

	public static void main(String[] args) {
		Runnable r = new Runnable () {
			public void run() {
				for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
			}
		};
		Thread t = new Thread(r);
		t.run();
	}
}

在使用匿名内部类时需要注意以下几点

  • 使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。
  • 匿名内部类中是不能定义构造函数的。
  • 匿名内部类中不能存在任何的静态成员变量和静态方法。
  • 匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。
  • 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。

静态内部类

静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法。相反,它可以使用外部类的所有静态方法和属性包括private修饰的方法和属性。

public class ExterNal{
	
	int a = 0;	//外部类属性
	private int private_a = 1;	//外部类私有属性
	static int static_a = 2;	//外部类静态属性
	private static int  private_static_a = 3;	//外部类私有静态属性
	
	//外部类私有方法
	private void function_a() {
		System.out.println("function_a");
	}
	
	//外部类私有静态方法
	private static void function_static_b() {
		System.out.println("function_static_b");
	}
	
	
	static class InsIde{
		public void test() {
			System.out.println(static_a);	//调用外部类静态属性
			System.out.println(private_static_a);	//调用外部类私有静态属性
			function_static_b();//调用外部类私有静态方法
		}
	}
}

总结

  • 静态内部类
    静态内部类是指被声明为static的内部类,他可以不依赖内部类而实例,而通常的内部类需要实例化外部类,从而实例化。静态内部类不可以有与外部类有相同的类名。不能访问外部类的普通成员变量,但是可以访问静态成员变量和静态方法(包括私有类型)
  • 成员内部类
    一个 静态内部类去掉static 就是成员内部类,他可以自由的引用外部类的属性和方法,无论是静态还是非静态。但是不可以有静态属性和方法
  • 局部内部类
    定义在一个代码块的内部类,他的作用范围是所在代码块,是内部类中最少使用的一类型。局部内部类跟局部变量一样,不能被public ,protected,private以及static修饰,只能访问方法中定义final类型的局部变量
  • 匿名内部类
    匿名内部类是一种没有类名的内部类,不使用class,extends,implements,没有构造函数,他必须继承其他类或实现其他接口。匿名内部类的好处是使代码更加简洁,紧凑,但是带来的问题是易读性下降。

文尾

文章均为学习阶段记录笔记,若有不妥请留言指正。谢谢!

你可能感兴趣的:(Java基础)