阿里云【名师课堂】Java面向对象开发51 ~ 53:内部类的定义及使用

阿里云【名师课堂】Java面向对象开发51 ~ 53:内部类的定义及使用


对于内部类的定义和使用暂时不作为我们的首要类设计原则。

51:内部类基本概念

概念

所谓的内部类指的就是在一个类中声明另一个类,被声明的类就是内部类,包含内部类的类称为内部类的外嵌类(外部类)。
理论上是可以在类中无限生命内部类,但是这样逻辑混乱操作复杂,所以基本上只声明一个内部类。

  • 外嵌类的成员变量在内部类中仍然有效,即内部类可以调用外嵌类中的属性和方法;
  • 内部类中不可以声明类变量和类方法,在外嵌类的类体中可以用内部类声明对象作为外嵌类的成员。
  • 范例:观察一个内部类
class OuterClass{  // 定义一个外嵌类
	private String msg = "Hello World!" ;  // 定义外嵌类的一个属性
	
	class InnerClass{  // 定义一个内部类
		public void print(){  // 定义一个普通方法
			System.out.println(msg) ;  // 引用外嵌类的变量
		}
	}
	
	// 在外嵌类中定义一个方法,这个方法负责产生内部类对象并且调用print()方法
	public void metd(){
		InnerClass in = new InnerClass() ;  // 内部类实例化一个内部类对象
		in.print() ;  // 内部类中提供的print()方法
	}
}

public class InnerDemo {
	public static void main(String args[]) {
		OuterClass out = new OuterClass() ;  // 实例化一个外嵌类对象
		out.metd() ;  // 调用了一个外嵌类中的方法
	}
}

在这里插入图片描述
代码虽然可以实现功能,但是可以看出程序的结构有些混乱。虽然内部类破坏了程序的结构,但是好处在于:

  • 外嵌类的私有访问:内部类只供它的外嵌类使用。

范例:将上述程序内部类挪到外部,实现相同功能,分析:

  1. InnerClassOuterClass是两个类,并且InnerClass需要访问到OuterClass中的msg属性,但是msg使用了private封装,外部访问它必须先在OuterClass中定义一个getter方法。
  2. InnerClass中的print()方法如果想要访问msg的内容,那么只能通过getMsg()方法来完成,而使用getMsg()方法必须要先使用OuterClass实例化一个对象,那么这个时候需要把在主方法中实例化的Outer对象传递到Inner中。
class OuterClass{
	private String msg = "Hello World!" ;
	
	public String getMsg(){
		return this.msg ; 
	}
	public void metd(){  // 3、Outer来调用metd方法
		InnerClass in = new InnerClass(this) ;  // 4、this表示当前,这里是当前正在调用metd的对象
		in.print() ;  // 7、调用方法
	}
}

class InnerClass{
	private OuterClass out ;
	
	public InnerClass(OuterClass out){  // 5、InnerClass.out = main.out
		this.out = out ;  // 6、引用传递
	}
	public void print(){  // 8、执行此方法
		System.out.println(this.out.getMsg()) ;
	}
}

public class InnerDemo {
	public static void main(String args[]) {
		OuterClass out = new OuterClass() ;  // 1、实例化一个Outer对象
		out.metd() ;  // 2、调用OuterClass中的metd方法
	}
}

在这里插入图片描述
实际上折腾这么久就是为了访问外部类中的私有属性(u1s1这过程太恶心了 ),没必要掌握。

具体使用

对于内部类的实际使用有以下几点:
1、通过以上代码可以发现,当前的内部类的访问必须通过外部类的方法才可以完成(比如第一段程序中,通过metd()方法访问InnerClass)。如果现在不想通过外部类方法进行调用,而是想在程序外部调用,就必须按照如下的形式进行内部类的实例化对象创建:

  • 外嵌类.内部类 内部类对象 = new 外部类().new 内部类() ;
class OuterClass{  // 定义一个外嵌类
	private String msg = "Hello World!" ;  // 定义外嵌类的一个属性
	
	class InnerClass{  // 定义一个内部类
		public void print(){  // 定义一个普通方法
			System.out.println(msg) ;  // 引用外嵌类的变量
		}
	}
}

public class InnerDemo {
	public static void main(String args[]) {
		// 声明内部类对象
		OuterClass.InnerClass in = new OuterClass().new InnerClass() ;
		in.print() ;
	}
}

在这里插入图片描述
注意这里的两个new:第一个是先在外嵌类实例化,第二个才是内部类的。

  • 之所以要先在外嵌类中进行实例化,主要问题在于此时外嵌类中存在有属性,这些属性只有在开辟实例化对象之后才能被访问。

2、如果现在一个内部类只想被外嵌类使用,即:不希望直接产生内部类的实例化对象,那么可以用private定义这个内部类。

class OuterClass{  // 定义一个外嵌类
	private String msg = "Hello World!" ;  // 定义外嵌类的一个属性
	
	private class InnerClass{  // 定义一个内部类,只能被外嵌类使用
		public void print(){  // 定义一个普通方法
			System.out.println(msg) ;  // 引用外嵌类的变量
		}
	}
	public void metd(){
		InnerClass in = new InnerClass() ;  // 内部类实例化一个内部类对象
		in.print() ;  // 内部类中提供的print()方法
	}
}

public class InnerDemo {
	public static void main(String args[]) {
		new OuterClass().metd() ;
	}
}

3、在进行属性访问时都需要习惯性的加上this,而如果想要在内部类中明确的使用this,那么语法为:外部类.this.属性,这代表在外嵌类中的当前的属性。如果只用this的话代表的是内部类中的属性。

52:static定义内部类

内部类定义时如果使用了static,代表这是一个外部类(功能上、结构上),这个外部类的名称为:外部类.内部类,同时该内部类只允许访问外部类中的static操作。语法:

  • 外嵌类.内部类 内部类对象 = new 外部类.内部类() ;

与程序外部实例化内部类对象做对比:

  • 外嵌类.内部类 内部类对象 = new 外部类().new 内部类() ;

范例:使用static定义内部类

class OuterClass{  // 定义一个外嵌类
	private static String msg = "Hello World!" ;  // msg如果是非static的外部类属性时无法被引用
	
	static class InnerClass{  // 定义一个 static内部类 = 外部类
		public void print(){
			// 此时只能使用外部类中的static操作
			System.out.println(msg) ;  // msg是非static的外部类属性
		}
	}
	public void metd(){
		InnerClass in = new InnerClass() ;  // 内部类实例化一个内部类对象
		in.print() ;  // 内部类中提供的print()方法
	}
}

public class InnerDemo {
	public static void main(String args[]) {
		OuterClass.InnerClass in = new OuterClass.InnerClass() ;
		in.print() ;
	}
}

在这里插入图片描述

53:在方法中定义内部类

理论上内部类可以定义在类中的任意位置上,这就包括:类中、方法中、代码块中。不过如果从实用的角度来讲,在方法中定义内部类的形式是最常见的。
范例:在方法中定义内部类

class OuterClass{
	private static String msg = "Hello World!" ;
	
	public void metd(int num){
		class InnerClass{
			public void print(){
				System.out.println("num = " + num) ;  // 内部类访问方法的参数num
				System.out.println("msg = " + msg) ;
			}
		}
		InnerClass in = new InnerClass() ;
		in.print() ;
	}
}

public class InnerDemo {
	public static void main(String args[]) {
		new OuterClass().metd(100) ;
	}
}

在这里插入图片描述
这段程序在JDK1.8之后是正确的,而在JDK1.8之前如果要想起到同样效果,需要给方法的参数加上final定义:第四行改为public void metd(final int num){
再次强调:内部类的使用暂时不该成为你的首选,但是至少应该知道内部类具备的特点:

  • 破坏了程序的结构;
  • 方便的进行私有属性的访问。
  • 以后如果发现类名称之前还有.,应该立即想到是内部类的概念。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值