`
王的篇章
  • 浏览: 2830 次
  • 性别: Icon_minigender_1
  • 来自: 江西玉山
最近访客 更多访客>>
社区版块
存档分类
最新评论

JavaSE:内部类

阅读更多

内部类是指在一个外部类的内部再定义一个类。
内部类的作用:

1). 内部类可以很好的实现隐藏,也就是封装性。一般的非内部类,是不允许有 private 与protected权限的,但内部类可以
2). 内部类可以直接访问外部类的所有属性和方法,即使是private修饰的

3). 可以实现多重继承
4). 可以不修改接口而实现同一个类中有两个同名方法

 

一、成员内部类(外部类的成员变量)

说明:编译之后,内部类字节码文件是:Outer$Inner.class

1)内部类可以直接访问外部类中的私有属性。实际上内部类已经破坏了一个类的基本结构,因为类是由属性及方法组成的,这是内部类的缺点;内部类可以直接访问外部类中的私有属性,这是其最大的优点

package com.wbf.test1;

class Outer{
	private String info = "hello world!!!";//外部类的私有属性
	class Inner{
		public void print(){
			System.out.println(info);//直接访问外部类的私有属性
		}
	};
	
	public void fun(){
		new Inner().print();//内部类的实例化对象调用自身的方法
	}
};

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

 

2)一个内部类除了可以通过外部类访问,也可以直接在其他类中进行调用

package com.wbf.test3;

class Outer{
	private String info = "hello world!!!";//外部类的私有属性
	class Inner{
		public void print(){
			System.out.println(info);//直接访问外部类的私有属性
		}
	};
};

public class InnerClassDemo03 {
	public static void main(String[] args) {
		/*
		Outer.Inner in = new Outer.Inner();//error, No enclosing instance of type Outer is accessible, 必须先有Outer类的实例
		in.print();
		*/
		Outer out = new Outer();
		Outer.Inner in = out.new Inner();
		in.print();
	}
}

一个内部类除了可以通过外部类访问,也可以直接在其他类中进行调用
格式:外部类.内部类 内部类对象 = 外部类实例.new 内部类();
以上的格式中,首先要找到外部类的实例化对象之后,才可以通过外部类的实例化对象去实例化内部类的对象
注意:此时的Inner类非static
如果Inner类用static修饰,那么在类加载的之后,对于Outer类来说,即使没有Outer类的实例化对象,Inner这个成员变量已经存在
反之,Inner类没有用static修饰,那么在没有Outer类实例化对象的情况下,对于Outer类来说,Inner这个成员变量根本就不存在,此时要直接实例化Inner,肯定是不行的
所以在一般情况下,当先有外部类的实例化对象之后,再通过外部类的对象去实例化内部类

 

三、静态内部类(用static声明内部类)

说明:静态内部类和普通的内部类一个区别:普通内部类不能有static方法和static属性,也不能包含静态内部类,但静态内部类可以。而静态内部类不能声明为private,一般声明为public,方便调用。编译之后,内部类字节码文件是:Outer$Inner.class

package com.wbf.test2;

class Outer{
	private static String info = "hello world!!!";//外部类的私有属性
	static class Inner{
		public void print(){
			System.out.println(info);//直接访问外部类的私有属性,同时这里info属性用static修饰
		}
	};
};

public class InnerClassDemo02 {
	public static void main(String[] args) {
		new Outer.Inner().print();//通过new Outer.Inner()来实例化内部类,同时调用内部类的方法
		/*
		Outer.Inner in = new Outer.Inner();
		in.print();
		*/
	}
}

 

static可以声明属性或方法,而是用static也可以声明内部类
用static声明的内部类成为外部类,但是用static声明的内部类不能访问外部类的非static属性

四、局部内部类(在方法中定义内部类)

说明:编译之后,内部类字节码文件是:Outer$1Inner.class

package com.wbf.test4;

class Outer{
	private String info = "hello world!!!";//外部类的私有属性
	public void fun(final int temp){
		class Inner{
			public void print(){
				System.out.println("方法中的参数: " + temp);//访问方法中的final参数
				System.out.println("类中的属性: " + info);//直接访问外部类的私有属性
			}
		};
		
		new Inner().print();
	}
};

public class InnerClassDemo04 {
	public static void main(String[] args) {
		Outer outer = new Outer();
		outer.fun(20);
	}
}

可以在一个方法中定义一个内部类,但是在方法中定义的内部类不能够直接访问方法中的参数;如果方法中的参数要想被内部类所访问,则参数前必须加上final关键字

 

五、匿名内部类

说明:编译之后,内部类字节码文件是:X$1.class

1)未使用匿名内部类

package com.wbf.test5;

interface A {
	public void printInfo();
}

class B implements A {
	public void printInfo(){
		System.out.println("hello world!!!");
	}
}

class X {
	public void fun1(){
		this.fun2(new B());
	}
	
	public void fun2(A a){
		a.printInfo();
	}
}

public class AnonymousInnerClassDemo {
	public static void main(String[] args) {
		new X().fun1();
	}
}

 

但是现在如果接口的实现类B只使用一次,那么还有必要单独定义一个子类B吗?很明显没有必要,所以此时就要使用匿名内部类完成

2)使用匿名内部类

package com.wbf.test6;

interface A {
	public void printInfo();
}

class X {
	public void fun1(){
		this.fun2(new A(){//匿名内部类
			public void printInfo(){//实现接口中的抽象方法
				System.out.println("hello world!!!");
			}
		});
	}
	
	public void fun2(A a){
		a.printInfo();
	}
}

public class AnonymousInnerClassDemo {
	public static void main(String[] args) {
		new X().fun1();
	}
}

 

六、Java通过内部类变相实现多重继承

package com.wbf.test7;

abstract class Father{
	public abstract void run();
};

abstract class Mother{
	public abstract void say();
};

class Son extends Father{
	public void run(){
		System.out.println("running...");
	}
	
	Mother getMother(){
		return new Mother(){
			public void say(){
				System.out.println("saying...");
			}
		};
	}
};

public class DuplicateExtendsDemo {
	public static void main(String[] args) {
		Son s = new Son();
		s.run();
		s.getMother().say();
	}
}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics