java内部类

本文详细介绍了Java内部类的概念、特点及其四种类型:成员内部类、静态内部类、匿名内部类和局部内部类。每种类型的内部类都有其独特的应用场景和访问特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内部类概念

定义在另一个类内部的类

内部类主要特点:

内部类可以很好的实现隐藏,可以使用public(默认)、protect、private修饰符。以前声明类的时候都是public,或者不写。外部类不能使用protect、private修饰符。

内部类可以访问外部类所有的成员,包括私有的成员。

外部类不能访问内部类的成员和方法。必须建立内部类的对象才能访问。

内部类可以解决一些问题,比如间接的去实现多继承。

内部类可以避免修改接口,而实现同一个类中两种同名方法的调用。

内部类分类:

成员内部类

1、成员内部类属于外部类的实例成员,成员内部类可以有public、private、default、protected权限修饰符。在成员内部类中访问外部类的成员方法和属性,要使用“外部类名.this.成员方法”和“外部类名.this.成员属性”的形式。

2、创建成员内部类的实例使用“外部类名.内部类名 实例名=外部类实例名.new 内部类构造方法(参数)”的形式。

3、成员内部类不能与外部类重名。

4、不能再成员内部类中定义static属性、方法、类(static final形式的常量定义除外)。因为一个成员内部类的实例必然与一个外部类的实例相关联。static成员完全可以移到其外部类中去。

public class Main {

	public static void main(String[] args) {
		// OuterClass outerClass = new OuterClass();
		// InnerClass innerClass = outerClass.new InnerClass();
		Outer1 outer1 = new Outer1();
		Outer1.Inner1 inner1 = outer1.new Inner1();
		outer1.outerShow();
		inner1.innerShow();
	}
}

// 产生三个自己码文件 Main.class Outer1.class Outer1$Inner1.class
class Outer1 {
	private String name = "zhangsan";
	private int num1 = 10;

	public void outerShow() {
		System.out.println(name);
		System.out.println(num1);
		//外部类不能直接访问内部类的成员和方法
//		System.out.println(num2);
		//外部类要想访问内部类的属性和方法,必须先产生内部类对象
		Inner1 inner1 = new Inner1();
		inner1.innerShow();
	}
//private class Inner1 私有的时候其他类不能创建内部类对象
	public class Inner1 {// 是否对外公开
		private String name = "lisi";
		private int num2 = 20;
		//静态的常量是可以的
		private static final int num3 = 20;
		// 在成员内部类中不能声明静态的成员,包括属性和方法
		// private static int num3=30;

		public void innerShow() {
			System.out.println("----------");
			System.out.println(name);
			System.out.println(num2);
			

			// 成员内部类可以直接访问外部类的属性和方法,包括私有的
			System.out.println(num1);
			outerShow();
			//Outer1.this外部类对象的引用,没有同名方法可以不加
			System.out.println(Outer1.this.name);
			Outer1.this.outerShow();
		}
	}
}


//内部类可以避免修改接口,而实现同一个类中两种同名方法的调用。
//具体的实用意义不大,只是为了演示学习内部类
public class Main3 {

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

}

abstract class Parent {
	public abstract void show();
}

interface IShow {
	public abstract void show();
}

// class Son extends Parent implements IShow{
//
// @Override
// public void show() {
// }
// }

class Son extends Parent {

	@Override
	public void show() {
		System.out.println("抽象类中show");
	}

	private class Inner2 implements IShow {

		@Override
		public void show() {
			System.out.println("Inner2中show");
		}
	}

	public void show2() {
		new Inner2().show();
	}
}


静态内部类

1、使用static修饰的成员内部类叫静态内部类。

2、静态内部类和外部类没有任何关系,只是在生成类名和类定义的时候有影响。静态内部类可以看做是与外部类平级的类。使用方式与外部类平级的类完全相同。

3、创建静态内部类的实例:外部类名.内部类名 实例名 = new 外部类名.内部类名(参数);

4、静态内部类不能与外部类重名

5、静态内部类不能访问外部类的非静态的属性和方法。外部类不能访问内部类的非静态的属性和方法。

(把静态内部类当做外部类的静态方法来看)

public class StaticMain {
	public static void main(String[] args) {
		// 构造静态内部类对象
		Outer2.Inner2 inner2 = new Outer2.Inner2();
		inner2.innerShow();
		Outer2 outer2 = new Outer2();
		outer2.outerShow();
	}
}

class Outer2 {
	private String name = "zhangsan";
	private int num1 = 10;
	private static int num3 = 100;

	public void outerShow() {
		System.out.println(name);
		System.out.println(num1);
		// 不能访问
		// System.out.println(Inner2.name);
		// 可以通过内部类对象进行访问
		Inner2 inner2 = new Inner2();
		System.out.println(inner2.name);
		// 可以访问内部类中的静态属性
		System.out.println(Inner2.num3);
	}

	public static class Inner2 {
		private String name = "lisi";
		private int num2 = 20;
		private static int num3 = 30;
		public void innerShow() {
			// 静态内部类不能访问外部类中非静态成员
			// System.out.println(Outer2.this.name);
			// 可以访问自己内部的
			System.out.println(num2);
			// 通过类名访问
			System.out.println(Outer2.num3);
		}
	}
}


匿名内部类

1、匿名内部类是没有名称的内部类,没有办法引用它们。必须在创建的时候作为new语句的一部分来声明并创建它们的实例。

2、匿名内部类必须继承一个类(抽象的、非抽象的都可以)或者实现一个接口。如果父类(或者父接口)是抽象类,则匿名内部类必须实现其所有的抽象方法。

3、匿名内部类中可以定义代码块{},用于实例的初始化(代码块优先构造方法先执行),但是不能定义静态代码块。

4、new interface/superclass{ }

这种形式的new语句声明一个新的匿名类,它对一个给定的类进行扩展,或者实现一个给定的接口,并同时创建该匿名类的一个新实例。new 出来的是接口/抽象类的实现类对象。

5、接口/抽象类绝对不能实例化。

public class AnonymousInnerClass {

	public static void main(String[] args) {
		Person person = new Person();
		Animal dog = new Dog();
		person.feed(dog);
		person.feed(new Animal() {
			@Override
			public void eat() {
				System.out.println("吃鱼");
			}
		});
		new Animal() {
			// 匿名内部类中可以有自己的属性
			private String name = "dog";
			// static不能有静态代码块
			{
				name = "haha";
			}
			@Override
			public void eat() {
				System.out.println("吃鱼");
			}
			// 匿名内部类中可以有自己的方法
			public void show() {
				System.out.println("show " + name);
			}
		}.show();// 调用自己的方法,只能通过这个方法
	}
}

class Person {
	// 多态
	public void feed(Animal animal) {
		animal.eat();
	}
}

abstract class Animal {
	public abstract void eat();
}

class Dog extends Animal {
	@Override
	public void eat() {
		System.out.println("啃骨头");
	}
}



局部内部类

1、局部内部类使用最少。

2、定义在代码块{},方法体内的类叫局部内部类。

3、局部内部类访问外部类的属性和方法使用“外部类名.this.属性名”和“外部类名.this.方法名(参数)”的形式。

4、对外部世界完全隐藏,只能在其作用域内生成对象。只能在方法体,代码块中构造。

5、局部类不能加访问修饰符,因为它们不是类成员。可以看做是局部变量。只有属性或者说是类的成员才能加访问修饰符。

6、成员内部类不能与外部类重名。

7、局部内部类访问作用域内的局部变量,该局部变量需要使用final修饰。也就是说局部内部类只能访问方法或者语句块中声明的常量。

public class LocalInnerClass {

	public static void main(String[] args) {
		Outer3 outer3 = new Outer3();
		outer3.showOuter();
	}
}

class Outer3 {
	private String name = "zhangsan";
	private int num1 = 10;
	private static int num2 = 20;

	public void showOuter() {
		int num4 = 50;
		final int num5 = 60;
		// 局部内部类不能加访问修饰符
		//局部内部类的声明周期很短,只在方法的语句块中有效
		//方法运行完,局部内部类对象释放
		class Inner3 {
			private int num3 = 30;
			private int num1 = 20;
			
			public void showInner() {
				System.out.println(num3);
				//自己的num1
				System.out.println(num1);
				//可以访问到
				System.out.println(Outer3.this.num1);
				System.out.println(Outer3.num2);
				//局部内部类只能访问声明其方法中的常量final
//				System.out.println(num4);
				System.out.println(num5);
			}
		}
		// 方法从上向下执行,只能在class之后创建,外部能不能使用Inner3
		Inner3 inner3 = new Inner3();
		inner3.showInner();
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值