【JavaSE】内部类超详细解析

目录

访问外部类私有成员

成员内部类

当内部类为公有或默认访问时

当内部类是私有访问时

局部内部类

匿名内部类

继承父类

使用匿名内部类:

而不适用匿名内部类:

继承抽象类

匿名内部类是实现接口

以实参的形式使用

未使用匿名内部类

使用匿名内部类

当调用方法为多个时

向上转型法(多态法)

this方法

静态内部类


访问外部类私有成员

内部类可以访问外部类的私有成员

package Lab4;

public class s {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		s S = new s();
		s.A a= S.new A();
		a.show();
		
	}
	private int id=1;
	class A{
		void show () {
			System.out.println(id);
			System.out.println(price);
		}
	}
	private int price=10;
}

输出:

1
10

也就是说,内部类可以访问外部类任何位置的私有成员

成员内部类

在一个类(外部类)中将另一个类(内部类)当做其的私有成员

语法格式:

public class OuterClass{							//外部类
	private class InnerClass{						//内部类
		//...
	}
}

当内部类为公有或默认访问时

法一:

package innerclass;

public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		OuterClass out=new OuterClass();
		OuterClass.InnerClass in=out.new InnerClass();
		
	}

}

class OuterClass{
	OuterClass(){
		System.out.println("外部类!");
	}
	
//	public InnerClass in=new InnerClass();
	public class InnerClass{
		InnerClass(){
			System.out.println("内部类!");
		}
	}
}

输出:

外部类!
内部类!

法二:

package innerclass;

public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		OuterClass out=new OuterClass();
//		OuterClass.InnerClass in=out.new InnerClass();
		
		
	}

}

class OuterClass{
	OuterClass(){
		System.out.println("外部类!");
	}
	
	public InnerClass in=new InnerClass();
	public class InnerClass{
		InnerClass(){
			System.out.println("内部类!");
		}
	}
}

输出:

内部类!

外部类!

当内部类是私有访问时

上述法一会失效,法二可以输出,即下面的代码可以输出

package innerclass;

public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		OuterClass out=new OuterClass();
//		OuterClass.InnerClass in=out.new InnerClass();
		
		
	}

}

class OuterClass{
	OuterClass(){
		System.out.println("外部类!");
	}
	
	public InnerClass in=new InnerClass();
	private class InnerClass{
		InnerClass(){
			System.out.println("内部类!");
		}
	}
}

局部内部类

内部类位于外部类方法成员里面

package innerclass;

public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		OuterClass out=new OuterClass();
		out.CreateInnerClass();
		
		
	}

}

class OuterClass{
	OuterClass(){
		System.out.println("外部类!");
		
	}
	

	void CreateInnerClass() {

		class InnerClass{
			InnerClass(){
				System.out.println("内部类!");
			}
			
		}
		InnerClass in=new InnerClass();
		
	}
}

输出:

外部类!
内部类!

值得注意的是,当内部类位于方法体内时,是没有private或是public的访问权限的,所以如果有访问权限的关键字时,编译器会报错。

匿名内部类

使用对象名来替代一个类,匿名内部类的所有实现方法均在大括号里面

使用前提和条件:必须存在继承和实现关系的时候才可以使用,其实这也很好理解,首先,匿名内部类没有名字,那该如何描述以及new个对象呢?对,没错,要通过继承它的父类或者实现一个接口来达成这一目的。

补充:

  • 1、匿名内部类 :匿名内部类只是没有类名,其他的一概成员都是具备的。

之前说过匿名内部类存在的前提是要有继承或者实现关系的,但是并没有看到extends和implements关键字,这是怎么回事呢?

答:很简单,匿名内部类没有连类名都没有,使用关键字就更无从说起了。这些由jvm搞定了。

格式:

return new A() {
	...//内部类体
};
A:对象名

继承父类

使用匿名内部类:

package innerclass;

public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new ParentClass() {
			void show() {
				System.out.println("匿名内部类!");
			}
		}.show();
		
		
	}

}

class ParentClass{
	void show() {
		// TODO Auto-generated constructor stub
		System.out.println("继承父类!");
	}
}

输出:

匿名内部类!

而不适用匿名内部类:

package innerclass;

public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ChildClass childClass=new ChildClass();
		childClass.show();
		
	}

}

class ParentClass{
	void show() {
		// TODO Auto-generated constructor stub
		System.out.println("继承父类!");
	}
}
class ChildClass extends ParentClass{
	void show() {
		System.out.println("匿名内部类!");
	}
}

输出:

匿名内部类!

继承抽象类

当然既然能继承父类,那么自然就可以继承抽象类

package innerclass;

public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new ParentClass() {
			void show() {
				System.out.println("匿名内部类!");
			}
		}.show();
		
		
	}

}

abstract class ParentClass{
	abstract void show();
}

匿名内部类是实现接口

package innerclass;

public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new ParentClass() {//值得注意的是,这里是实现接口的类,而不是创建对象(因为接口不能创建对象)
			public void show() {
				System.out.println("匿名内部类!");
			}
		}.show();
		
		
	}

}

interface ParentClass{
	abstract void show();
}

以实参的形式使用

未使用匿名内部类

package innerclass;

public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Child child=new Child();//法一
		run(child);//法一
		
		
//		run(new Child());//法二
	
		
		
	}
	public static void run(ParentClass a)//使用static因为在main里没有test类的对象
	{
		a.show();
	}

}

interface ParentClass{
	abstract void show();
}
class Child implements ParentClass{
	@Override
	public void show() {
		// TODO Auto-generated method stub
		System.out.println("未使用匿名内部类");
	}
}

使用匿名内部类

package innerclass;

public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		run(new ParentClass() {
			
			
			public void show() {
				// TODO Auto-generated method stub
				System.out.println("匿名内部类");
				
			}
		});
		
		
	}
	public static void run(ParentClass a)//使用static因为在main里没有test类的对象
	{
		a.show();
	}

}

interface ParentClass{
	abstract void show();
}

当调用方法为多个时

我们知道匿名内部类中只有一个方法时,可以通过上面的方法实现

当调用多个方法时,我们可以通过向上转型的方法来调用

向上转型法(多态法)

package innerclass;

public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ParentClass aClass=new ParentClass() {
			
			@Override
			public void show() {
				// TODO Auto-generated method stub
				System.out.println("调用show");
			}
			
			@Override
			public void haha() {
				// TODO Auto-generated method stub
				System.out.println("调用haha");
				
			}
		};
		aClass.show();
		aClass.haha();
		
	}
	

}

interface ParentClass{
	abstract void show();
	abstract void haha();
}

this方法

package innerclass;

public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new ParentClass() {
			
			@Override
			public ParentClass show() {//返回类型
				// TODO Auto-generated method stub
				System.out.println("调用show");
				return this;
			}
			
			@Override
			public void haha() {
				// TODO Auto-generated method stub
				System.out.println("调用haha");
				
			}
		}.show().haha();//注意顺序是先调用show,而不是先调用haha
		
	}
	

}

interface ParentClass{
	abstract ParentClass show();//注意返回类型
	abstract void haha();
}

输出:

调用show
调用haha

静态内部类

在内部类前用static修饰,使其成为静态内部类,静态内部类中可以声明static成员,但是非静态内部类中不可以声明静态成员,这是他们的区别。

静态内部类不能使用外部类的非静态成员

可以这么认为,普通的内部类对象隐式地在外部保存了一个引用,指向创建它的外部类对象,但静态内部类有一下两个特点:

1. 创建静态内部类的对象,不需要其外部类的对象

2. 不能从静态内部类的对象中访问非静态内部类的对象

参考资料:

https://www.jb51.net/article/233479.htm

Java 内部类 | 菜鸟教程

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LenckCuak

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值