《疯狂Java讲义(第4版)》-----第6章【面向对象(下)】(内部类)

内部类

内部类就是定义在类内部的类,可以 是成员内部类(类的第五种成员,分为静态内部类和非静态内部类),也可以定义在方法内部(局部内部类)。宿主类不能访问内部类的成员。可以通过”静态内部类名.静态内部类静态成员“和”内部类对象.内部类成员“来访问

非静态内部类

没有static修饰的成员内部类就是非静态内部类。非静态内部类不有静态成员。

访问权限的思考?
类的上级是包,包的上级是工程,所以类的访问控制修饰符有默认不写和public两种。类的成员如内部类,上级是类,再上级是包,再再上级是工程,所以类的成员的访问控制权限有private,默认不写和protected(子类可访问)。

示例代码及内存情况

//注意下面示范了宿主类成员变量,内部类成员变量和内部类局部变量同名的情况

class OutClass{

	private String prop = "外部类成员变量";
	private class InClass{
		private String prop = "内部类成员变量";
		public void info(){
			String prop = "局部变量";
			System.out.println(prop);//输出局部变量
			System.out.println(this.prop);//输出内部类成员变量
			System.out.println(OutClass.this.prop);//输出外部类成员变量
		}
	}
	public void test(){
		InClass in = new InClass();
		in.info();
	}
}

class Hello{

	public static void main(String[] args){

		OutClass out = new OutClass();			
		out.test();
	}
}

编译后生成了这几个字节码文件:
《《疯狂Java讲义(第4版)》-----第6章【面向对象(下)】(内部类)》

《《疯狂Java讲义(第4版)》-----第6章【面向对象(下)】(内部类)》

静态内部类

有static修饰的成员内部类是静态内部类。静态内部类可包好静态成员和非静态成员。

接口里可以定义内部类,默认使用public static修饰。接口里也可以定义内部接口(几乎不用),系统默认使用public static修饰。

使用内部类示例代码


//在外部使用内部类
class OutClass{

	class InClass{
		public InClass(String msg){
			System.out.println(msg);
		}
	}
}

class Hello{

	public static void main(String[] args){

		new OutClass().new InClass("在宿主类的外部使用内部类");
	}
}

//继承宿主类的内部类。要使用非静态内部类,那首先得有宿主类的实例。

class OutClass{

	class InClass{
		public InClass(String msg){
			System.out.println(msg);
		}
	}
}

class Hello extends OutClass.InClass{

	public Hello(OutClass out){
		out.super("hello");//super代表的是OutClass类的内部类InClass类
	}

	public static void main(String[] args){

		new Hello(new OutClass());
	}
}

//使用静态内部类
class OutClass{

	static class InClass{
		public InClass(String msg){
			System.out.println(msg);
		}
	}
}

class Hello{

	public static void main(String[] args){

		new OutClass.InClass("hello");
	}
}

子类重写父类的内部类可以吗??
假设Father类的子类是Son类,Father类的内部类是In类,假设可以重写,那么重写后Son类的内部类为Father.Son.In而父类的内部类是Father.In,显然这里两个名字是不一样的,名字都不一样,显然不可能重写。

局部内部类

定义在方法内部的类是局部内部类。和局部变量同级别,只能在方法内部使用,显然不能用访问控制符和static修饰,因为没意义。

下面是示例代码,笔者故意把A的成员变量x设置成了private,在A外面访问x很随意啊!!

class Hello{

	public static void main(String[] args){

		class A{
			private int x = 1;
		}
		
		A a = new A();
		a.x = 666;
		System.out.println(a.x);
	}
}

匿名内部类

new 实现接口() | 父类构造器(实参列表){
	//匿名内部类的实体部分
}

匿名内部类是定义在类内部的没有名字的类。由上面的定义方式,我们就知道只能实现一个接口或继承一个父类。创建匿名内部类的时候就会立即创建一个实例,定义随即消失。由此也可知道匿名内部类绝不可是抽象类。另外,匿名内部类不能定义构造器,因为匿名内部类没有名字,自然不可能由构造器,但可以定义初始化块。

interface A{
	public abstract String getName(); 
}

class Hello{

	public void test(A a){

		System.out.println(a.getName());
	}

	public static void main(String[] args){
			new Hello().test(new A(){
			public String getName(){
				return "hello";
			}
		});
	}
}

上面代码是匿名内部类的实例,如果不使用匿名内部类的话,可以改写代码如下:

interface A{

	public abstract String getName(); 
}

class B implements A{

	public String getName(){
		return "hello";
	}
}

class Hello{

	public void test(A a){

		System.out.println(a.getName());
	}

	

	public static void main(String[] args){
		new Hello().test(new B());
	}
}
abstract class A{
	private String name;
	public abstract String getSex(); 
	public A(){}
	public A(String name){
		this.name = name;
	}
	public String getName(){
		return this.name;
	}
}

class Hello{

	public void test(A a){

		System.out.println(a.getName()+" "+a.getSex());
	}

	public static void main(String[] args){
		
		Hello h = new Hello();
		h.test(new A(){
			
			{
				
				System.out.println("我是匿名内部类的初始化块");
	
			}
			public String getSex(){
				return "female";
			}
			//重写父类的方法
			public String getName(){
				return "Marry";
			}
		});

		h.test(new A("Jack"){
			public String getSex(){
				return "male";
			}
		});
		
	}
}

局部内部类、匿名内部类访问的局部变量必须是final修饰的:

interface A{
	public abstract void test();
}

class Hello{

	public static void main(String[] args){
		
		int x = 2;
		A a = new A(){
			public void test(){
				//Java8开始,匿名内部类、局部内部类允许访问非final的局部变量,也就是说,
				//如果访问了,那么那个变量即使没有final修饰,也会自动变为是final修饰的变量
				//Java8之前这是不允许的,编译过不了
				System.out.println("x");
			}
		};
		a.test();
	}
}
    原文作者:ccnuacmhdu
    原文地址: https://blog.csdn.net/ccnuacmhdu/article/details/82916900
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞