java之内部类


文章类容选自尚硅谷,jdk8,eclipse环境。

内部类的特性

内部类是创建在类内的类,它有类内成员和类的两方面的属性

内部类可以分为成员内部类和局部内部类

  • 成员内部类作为类的成员,就像类的属性一样,可用static关键字修饰
  • 局部内部类可以放在构造器,方法和代码块内,就像类的局部变量一样

从属性来讲,一方面,它作为类内的成员

  1. 可以被static关键字修饰,就像static关键字修饰属性一样
  2. 被static关键字修饰内部类,只能是成员内部类,不能是局部内部类。
  3. 可以调用外部类的方法和属性
  4. 可以使用4种权限修饰符

另一方面,它作为一个类

  1. 可以被abstract关键字修饰,意味着它不可以实例化
  2. 可以被final关键字修饰,意味着它不可以被继承
  3. 类内可以定义属性,方法,构造器
  4. 内部类内还可以嵌套内部类,只不过很少见

示例代码如下

package com.atguigu.java2;

public class InnerClassTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}

class Person{
	
	public void eat(){
		System.out.println("人吃饭");
	}
	//成员内部类,可被static关键字修饰,也可以被abstract关键字修饰
	static abstract class Dog{
		String name;
		int age;
		
		public void show(){
			System.out.println("dog shout");
		}
	}
	
	final class Bird{
		String name;
		
		public Bird(){
			
		}
		
		public void sing(){
			System.out.println("bird sing");
			eat();
		}
	}
	
	public void method(){
		//局部内部类,可以被abstract,final关键字修饰
		abstract class AA{
			
		}
		
		final class BB{
			
		}
	}
	//局部内部类可以放到代码块内部
	{
		class CC{
			
		}
	}
}

以上的写法是完全合法的。

内部类调用外部类

在Bird内部类的sing方法中,调用了外部类的eat方法,实际上该eat方法是省略掉了Person.this.的关键字的。

若只加上一个this关键字,编译器会默认在内部类中找eat方法,找不到则报错,加上Person.this.的关键字,编译器则会在外部类中找eat方法

		public void sing(){
			System.out.println("bird sing");
			eat();
			Person.this.eat();
		}

这两个eat方法是等价的,都调用的是外部类的eat()方法。

内部类的使用

首先分别去掉Dog类前的abstract关键字和Bird类前的final关键字,在main方法中写入测试语句。

	public static void main(String[] args) {
		Person.Dog dog = new Person.Dog();
		dog.show();
		Person p = new Person();
		Person.Bird bird = p.new Bird();
		bird.sing();

	}

运行结果为

dog shout
bird sing
人吃饭
人吃饭

分析代码
Dog类是静态的成员内部类,在创建Dog类的时候,由于Dog类被static关键字所修饰,所以使用的时候不用先创建Person类的对象,直接通过Person.Dog就可以创建对象了。

然而在创建Bird类的时候,由于Bird类没有加static关键字修饰,在创建对象的时候必须先创建外部类的对象,然后再创建内部类的对象,注意,在创建内部类的对象的时候

		Person.Bird bird = p.new Bird();

形式为 外部类对象名.new 内部类构造器 这样的形式。

外部类和内部内重名属性(方法)的调用

当外部类和内部类有重名属性的时候,可以通过关键字加以区分。

之前讲到的eat()方法,由于没有重名的情况出现,内部类在调用外部类eat()方法的时候,直接是省略掉了Person.this关键字,但是如果有重名的情况。
比如说给Person类赋上String name的属性并显式初始化为”Reiner“,给Bird类的name属性显式初始化为“dujuan”

class Person{
	String name = "Reiner";
	
	public void eat(){
		System.out.println("人吃饭");
	}
	//成员内部类,可被static关键字修饰,也可以被abstract关键字修饰
	static class Dog{
		String name;
		int age;
		
		public void show(){
			System.out.println("dog shout");
		}
	}
	
	class Bird{
		String name = "dujuan";
		
		public Bird(){
			
		}
		
		public void sing(){
			System.out.println("bird sing");
			eat();
			Person.this.eat();
		}
		
		public void displat(String name){
			System.out.println(name);//输出的是方法的形参
			System.out.println(this.name);//输出的是内部类的属性
			System.out.println(Person.this.name);//输出的是外部类的属性
		}
	}
}

再在main方法中进行测试

	public static void main(String[] args) {
		Person p = new Person();
		Person.Bird bird = p.new Bird();
		bird.displat("huangli");

	}

测试结果为

huangli
dujuan
Reiner

可见,通过this关键字和Person.this关键字,就区分出了内部类和外部类的属性
同类,也可以通过this关键字和外部类名.this 关键字区分出内部类和外部类的方法

用局部内部类实现接口

示例代码如下,用局部内部类实现接口

package com.atguigu.java2;

public class InnerClassTest1 {
	//返回一个实现了Comparable接口的非匿名实现类的匿名对象
	public Comparable getComparable(){
		class MyComparable implements Comparable{

			@Override
			public int compareTo(Object o) {
				// TODO Auto-generated method stub
				return 0;
			}
			
		}
		return new MyComparable();	
		//也可以返回一个匿名实现类的匿名对象
//		return new Comparable(){
//
//			@Override
//			public int compareTo(Object o) {
//				// TODO Auto-generated method stub
//				return 0;
//			}
//			
//		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值