黑马程序员——Java基础——内部类

原创 2015年07月08日 08:53:22
------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------


什么是内部类,简单来说就是一个外部类的内部又定义了一个类,那为什么需要内部类呢?

因为内部类可以直接访问外部类中的成员,包括私有。用现实的例子描述就是一个人是由大脑、肢体、器官等身体结果组成,而内部类相当于其中的某个器官之一,例如心脏,它也有自己的属性和行为(血液、跳动),心脏可以直接访问身体的血液,而不是通过医生来抽血,这时不能用属性或者方法表示一个心脏,而是用一个类

内部类可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式 外部类名.this

外部类要访问内部类,必须建立内部类对象

内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。对于一个名为outer的外部类和其内部定义的名为inner的内部类。编译完成后出现outer.class和outer$inner.class两类。所以内部类的成员变量/方法名可以和外部类的相同。

1.成员内部类

就是将内部类定义在外部类的成员位置,而且非私有,可以在外部其他类直接建立内部类对象。格式:

外部类名.内部类名  变量名 = 外部类对象.内部类对象;
 Outer.Inner in = new Outer().new Inner();

开头的Outer是为了标明需要生成的内部类对象在哪个外部类当中。必须先有外部类的对象才能生成内部类的对象,因为内部类的作用就是为了访问外部类中的成员变量。

//定义外部类
class Outer
{
	//定义内部类
	class Inner
	{
		void show()
		{
			System.out.println("内部类运行...");
		}
	}
}


public class InnerClassDemo {

	public static void main(String[] args) {
		
		//在外部其他类建立内部类对象
		Outer.Inner in = new Outer().new Inner();
		in.show();
	}

}


当内部类在成员位置上,就可以被成员修饰符所修饰。
private:将内部类在外部类中进行封装。如同是,我的心脏只能由我的身体控制,其他人无法直接访问它

static:内部类就具备static的特性。当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问局限。

在外部其他类中,如何直接访问static内部类的非静态成员呢?
new Outer.Inner().function();

在外部其他类中,如何直接访问static内部类的静态成员呢?
Outer.Inner.function();

 注意:当内部类中定义了静态成员,该内部类必须是static的。
       当外部类中的静态方法访问内部类时,内部类也必须是static的。

//定义外部类
class Outer
{
	//内部类被static修饰后,只能直接访问外部类中的static成员
	private static int num = 2;
	static class Inner
	{
		static void show()
		{
			System.out.println("内部类运行..."+num);
		}
	}
}




public class InnerClassDemo {

	public static void main(String[] args) {
		Outer.Inner.show();
	}

}


2.局部内部类

内部类定义在外部类中的某个方法中,创建了这个类型的对象时,且仅使用了一次,那么可在这个方法中定义局部类。

不可以被成员修饰符修饰,如public、private、static等修饰符修饰。它的作用域被限定在了声明这个局部类的代码块中

可以直接访问外部类中的成员,因为还持有外部类中的引用。

但是不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量。为什么呢?

因为局部内部类对象和局部变量的生命周期不同,内部类需要复制局部变量为内部类的一个成员变量,为了保证局部变量和该副本的值的一致性,所以要将修饰符设为final。

//定义外部类
class Outer
{
	//局部内部类访问局部变量必须用final修饰
	void show(final int num)
	{	
		//内部类定义在外部类方法内
		class Inner
		{
			void show()
			{
				System.out.println("内部类运行..."+num);
			}
		}
		//访问语句必须在定义类局部内部类之后
		new Inner().show();
	}
}


public class InnerClassDemo {

	public static void main(String[] args) {
		
		Outer out = new Outer();
		out.show(3);//内部类运行...3
		out.show(4);//内部类运行...4

	}

}


3.匿名内部类

没有名字的内部类。就是内部类的简化形式。一般只用一次就可以用这种形式简化书写。

定义匿名内部类的前提:内部类必须是继承一个类或者实现接口。
匿名内部类的格式:  new 父类或者接口(){定义子类的内容}
其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。 可以理解为带内容的对象。
匿名内部类中定义的方法最好不要超过3个。

public class InnerClassDemo {

	public static void main(String[] args) {
		
		//编译通过,运行
		new Object(){
			void show(){
				System.out.println("show run");				
			}
		}.show();
		
		//编译失败,因为匿名内部类是一个子类对象,当用Object的obj引用指向时,
		//就被提升为了Object类型,而编译时检查Object类中是否有show方法

		Object obj = new Object(){
			void show(){
				System.out.println("show run");
			}
		};
		obj.show();
	}

}

从上面这个例子可以看出,匿名内部类就是参照多态的表达形式,用父类引用接收一个子类对象,编译运行参照多态的规则。

4.匿名内部类的扩展

可以通过匿名内部类的方式实现多重继承

//创建一个使用继承的类
abstract class Normal
{
	abstract void methodNomal();
}
//创建一个使用匿名内部类的类
abstract class Outer
{
	abstract void methodOuter();
}

//创建实现多重继承的类
class Multi extends Normal
{

	//复写父类的方法
	@Override
	void methodNomal() {
		System.out.println("normal method ...");
		
	}
	
	//创建返回匿名内部类对象的方法
	public Outer getOuter(){
		
		return new Outer(){

			@Override
			void methodOuter() {
				
				System.out.println("Outer method...");
			}
			
		};
	}
}

public class InnerClassDemo {

	public static void main(String[] args) {
		 
		//实现一个类的多重继承,调用方法
		Multi m = new Multi();
		m.methodNomal();
		m.getOuter().methodOuter();
	}
}


5.继承内部类

在学习了内部类的基础知识后,产生了一个疑问,既然内部类也是一个类,那它能不能被继承呢

//定义外部类
class Outer
{
	//定义内部类
	class Inner
	{
		Inner()
		{
			System.out.println("内部类运行...");
		}
	}
}
//继承时需要指定外部类名称
class ExtendsClass extends Outer.Inner
{
	//ExtendsClass();无法通过编译
	//构造函数需要传递外部类对象
	ExtendsClass(Outer out)
	{
		//调用内部类的构造函数
		out.super();
	}
}

public class InnerClassDemo {

	public static void main(String[] args) {
		 
		//创建外部类对象,并传入继承类的构造函数,完成初始化
		Outer out = new Outer();
		ExtendsClass ex = new ExtendsClass(out);
	}
}


上面就是继承内部类的代码,为什么要这样写?

继承内部类后,需要调用内部类的默认构造函数,但是加载内部类必须先加载外部类,所以要给继承类的构造函数传入外部类的对象,然后通过外部类.super()来调用内部类的默认构造函数完成初始化。










敢说你java基础很好吗?你能答对几个?(Java基础知识点整理)

1.熟悉IO相关接口和类,知道字符流和字节流的区别。 2.理解Java反射,并熟练使用反射解决问题。 3.理解泛型,并能熟练使用。知道的区别。 4.了解Collection、List、Map、Set之...
  • u014481156
  • u014481156
  • 2015年03月10日 21:40
  • 790

如何做到有扎实的 Java 基础

学习java的同学大部分估计都有这样的疑问,到底什么是java基础呢,我们总会去问一些高手,什么是基础,每个人都会有不同的答案告诉你,这时候的你将会接收很多知识,因为这也是基础,那也是基础,整的全都成...
  • marvel_java
  • marvel_java
  • 2016年11月21日 09:25
  • 2554

如何做到有扎实的Java基础

工作这么多年了,主要用的C语言,对Java语言只停留在看一些代码的层面,或者说是知道一些Java的语法。既然下定了决心学习Android App开发,而且也写了一些App代码, 但是发现对Java一些...
  • rex_nie
  • rex_nie
  • 2016年12月29日 00:34
  • 1729

JAVA学习需要什么基础

JAVA学习需要什么基础
  • javaniuniu
  • javaniuniu
  • 2017年02月04日 13:10
  • 2743

JAVA网络基础

1 网络基础简介1.1 两台计算机通信两台计算机需要通过网络进行通信,需要满足三个必备条件:IP地址(所处位置和身份)、协议(共同的语言)和端口号。1.1.1 TCP/IP协议 TCP/IP是目前世界...
  • DXZCZH
  • DXZCZH
  • 2016年07月03日 10:38
  • 372

四道Java基础题 你能对几道?

一、==符的使用 首先看一段比较有意思的代码 Integer a = 1000,b=1000; Integer c = 100,d=100;    public void mRun(final S...
  • soul_code
  • soul_code
  • 2015年12月21日 09:04
  • 7068

Java 基础内容简介

一.基本概念 类: 将一些具有相似属性和共同方法的事物抽象为一个类,以便于对事物进行描述.(足球,篮球,排球可以抽象为一个类 球 ) 对象:一个类的具体实例.(球的一个具体事物,足球) 继承: ...
  • mydream20130314
  • mydream20130314
  • 2015年04月05日 11:22
  • 394

零基础学习Java步骤

零基础学习Java步骤
  • javaniuniu
  • javaniuniu
  • 2017年02月06日 12:46
  • 2337

分享一道java基础题,测测你是不是基础扎实

这是在网上只看到的一道java关于多态继承的问题,看着很简单,结构出乎意料,也是研究了一天终于搞明白了一点 问题来自:http://blog.itpub.net/28562677/views...
  • wq343502916
  • wq343502916
  • 2015年03月21日 10:28
  • 937

java基础面试题:java笔记题收集(一)

1、面向对象的特征有哪些方面?  - 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。  - 继承:继...
  • chenpeng19910926
  • chenpeng19910926
  • 2016年08月02日 16:09
  • 571
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:黑马程序员——Java基础——内部类
举报原因:
原因补充:

(最多只允许输入30个字)