java基础知识---内部类

内部类是指在一个外部类内定义的类(可以在方法中定义),按照是否有类名分为有名内部类和匿名内部类。

有名内部类:

package com.test.csdn;

import com.test.csdn.Body.Heart;

//前面不能加public,因为一个java文件中不能有俩个public类
class Body{
	
	//有名内部类
	public class Heart{
		
		public void beat() {
			System.out.println("心脏在跳动");
		}
	}
	
	//此方法也可以创建,其中this可以省略
	{
		Heart heart = this.new Heart();
		heart.beat();
	}
}

public class Test{
	
	public static void main(String[] args) {
		//先创建外部内对象
		Body body = new Body();
		//创建内部类
		Heart heart = body.new Heart();
		heart.beat();
	}
}

匿名内部类

package com.test.csdn;

class Mammal{
	
	public void move() {
		System.out.println("动物在移动");
	}
	
	public Mammal() {
		
	}
}

public class Sea{
	
		//调用父类无参构造方法
		Mammal whale = new Mammal() {
			public void move() {
				System.out.println("鲸鱼游动");
			}
		};
		
		public static void main(String[] args) {
			
		}
}

抽象类:抽象类匿名内部类实质为抽象类的子类

package com.test.csdn;

abstract class Mammal{
	
	abstract void move();
	
	
	public Mammal(String name) {
		System.out.println(name);
		
	}
}

public class Sea{
	
		//调用父类有参构造方法
		Mammal whale = new Mammal("鲸鱼") {
			@Override
			public void move() {
				System.out.println("鲸鱼游动");
			}
		};
		
		public static void main(String[] args) {
			
		}
}

 接口:接口匿名内部类实质为接口的实现类。

package com.test.csdn;

interface Mammal{
	
	abstract void move();
	
}

public class Sea{
	
		Mammal whale = new Mammal() {
			
			public void move() {
				System.out.println("鲸鱼游动");
			}
		};
		
		public static void main(String[] args) {
			
		}
}

匿名内部类特点:

1.匿名内部类一定是接口的实现类(该实现类仅能实现一个接口)或类(普通类或抽象类)的子类;

2.匿名内部类不能有构造方法,但是可以通过非静态代码块初始化成员变量;

3.匿名内部类一定不能是抽象类;

4.可以在匿名内部类中添加新的属性和方法,但是这些属性和方法不能被上转型对象所调用,只能被非上转型对象方式创建的匿名内部类对象所调用,例如:

public class Test {

	public static void main(String[] args) {

		IMammal whale = new IMammal() {
			public void breath() {
				System.out.println("鲸鱼正在呼吸......");
			}

			@Override
			public void move() {
				System.out.println("鲸鱼靠鳍游动......");
			}
		};//此时匿名内部类对象为上转型对象
		whale.breath();// 上转型对象无法调用新增的breath方法
	}
}

interface IMammal {
	void move();
}
public class Test {

	public static void main(String[] args) {

		new IMammal() {
			public void breath() {
				System.out.println("鲸鱼正在呼吸......");
			}

			@Override
			public void move() {
				System.out.println("鲸鱼靠鳍游动......");
			}
		}.breath();// 调用新增的breath方法
	}
}

interface IMammal {
	void move();
}

同一个匿名内部类对象只能调用一个新增的属性或方法,无法再调用实现的抽象方法、重写的方法或继承的方法,也无法调用继承的属性

按照是否有static修饰分为静态内部类和非静态内部类,有static修饰的为静态内部类,没有static修饰的为非静态内部类,上面所举例都是非静态内部类,下面来说说静态内部类

静态有名内部类:

下方代码为跨类使用,若是本类使用,则不需要new Body。

package com.test.csdn;

import com.test.csdn.Body.Heart;

class Body{
	
	public static class Heart{
		
		public void beat() {
			System.out.println("心脏在跳动");
		}
	}
}

public class Test{
	
	public static void main(String[] args) {
		//仔细区别和非静态内部类创建对象的区别,这里采用类名
		Heart heart = new Body.Heart();
		heart.beat();
	}
}

静态匿名内部类:

class Father {

	public void eat() {
		System.out.println("筷子吃饭....");
	}
}

/**
 * 外部类
 */
public class OutClass {

	/**
	 * 匿名内部类
	 */
	static Father son = new Father(){
		
		@Override
		public void eat() {
			System.out.println("筷子吃饭....");
		}
	};
}

如果为static内部类只能直接定义在外部类中,非static的内部类可以定义在main方法内,如下

package com.test.csdn;

public class OutClass {

	public static void main(String[] args) {
		
		
	}
	static class InClass {
		
		public void printInfo() {
			System.out.println("有名内部类");
		}
	}
}

在非外部类中定义的内部类和局部变量一样,其使用范围从定义的位置开始到其所在直接语句块结束。

public class OutClass {
	public static void main(String[] args) {
		if(args!=null) {
			class InClass{
				
			}
		}
		InClass inClass = new InClass();//无法创建对象,因为内部类作用范围无法作用到这里
	}
}

只有有名静态内部类中才允许有静态成员(静态属性、静态代码块和静态方法)。

内部类是一个独立的类编译之后内部类会被编译成独立的.class文件,如果该内部类为有名内部类,则有名内部类字节码文件名为外部类的类名+$+内部类类名;如果为匿名内部类,则匿名内部类字节码文件名为外部类的类名+$+数字;

普通外部类、抽象类和接口可以有内部类(匿名的或有名的);

内部类可以直接定义在类中,也可以定义在方法或代码块中;其中直接定义在外部类中的内部类可以有public、protected、默认的和private四种访问权限修饰(普通外部类、接口和抽象类只能使用public和default修饰),也可以使用static修饰( static不能修饰普通外部类、接口和抽象类);但是定义在方法或代码块中的内部类不能有访问修饰符修饰,也不能有static修饰。

public class OutClass {
	
	private String name;

	class InClass{

		{
			System.out.println(name);
		}
	}
}

内部类可以访问外部类的所有访问权限的成员变量,如上图;

内部类暂时就到这里了,说实话,我自己都觉得有点难。。。。。。

猜你喜欢

转载自blog.csdn.net/LanQiLi/article/details/81262916