内部类

目录:

  •    有名内部类
  •     匿名内部类
  •     静态内部类

一、有名内部类

     (1)直接定义在外部类中

public class Body {
	
	//1.直接定义在外部类中
	class Heart{
		
		public void jump() {
			System.out.println("心脏跳动");
		}
	}
	
	public static void main(String[] args) {
		Body body = new Body();//先创建外部类对象
		Heart heart = body.new Heart();//由外部类对象创建内部类对象
		heart.jump();
	}
	
}

  直接定义在外部类中的有名内部类,①必须先创建外部类的对象,②由外部类对象创建内部类对象,然后调用方法

    (2)定义在外部类的方法中 

public class Body {

	public static void main(String[] args) {
		
		//2.定义在外部类的main方法中
		class Heart{
			public void jump() {
				System.out.println("心脏跳动");
			}
		}
		Heart heart = new Heart();
		heart.jump();
	}
	
}

   (3)在非静态代码块中

public class Body {

	public void print(){
		int a=0;
		if(a==0) {
			//3.在非静态代码块中定义内部类
			class Heart{
				public void beat() {
					System.out.println("正在跳动……");
				}
			}
			Heart heart = new Heart();
			heart.beat();
		}
	}
	
	public static void main(String[] args) {
		Body body = new Body();
		body.print();
	}
	
}

      ①内部类创建对象,调用方法;②外部类创建对象,调用装有内部类的方法 

二、匿名内部类

  匿名内部类由于没有类名不能单独存在,定义匿名内部类的同时须直接实例化该类

 new 父类构造器([参数列表])|接口(){   

       //匿名内部类类体

   };  //不要忘了这个分号

      (1)普通类匿名内部类

public class Teacher {
	
	public void homework(){
		System.out.println("两斤作业");
	}
}


public class Student {
	
	Teacher teacher = new Teacher() { //匿名内部类的开始
		public void homework() {
			System.out.println("四斤作业");
		}
	};//匿名内部类到此结束
	
	public static void main(String[] args) {
		Student student = new Student();
		student.techer.homework();

	}
}

   (2)抽象类匿名内部类

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

abstract class Teacher {
	
	public void homework( String name){
		System.out.println("两斤作业");
	}
	
	abstract void move();
}


public class Student {
	
	Teacher teacher = new Teacher() { //匿名内部类的开始
		
		public void homework(String name){
			System.out.println(name+"写了四斤作业");
		}
		
		@Override
		public void move() {
			System.out.println("移动");
		}
		
	};//匿名内部类到此结束
	
	public static void main(String[] args) {
		Student student = new Student();
		student.teacher.move();
		student.teacher.homework("Tom");
	}
}

  (3)接口匿名内部类

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

interface Teacher {
	
	abstract void move();
}


public class Student {
	
	Teacher teacher = new Teacher() { //匿名内部类的开始
	
		@Override
		public void move() {
			System.out.println("移动");
		}
		
	};//匿名内部类到此结束
	
	public static void main(String[] args) {
		Student student = new Student();
		student.teacher.move();
	}
}

   匿名内部类特点:

匿名内部类一定是接口的实现类(该实现类仅能实现一个接口)或类(普通类或抽象类)的子类,其中new 关键字后面的类名或接口名即是该匿名内部类继承的父类或实现的接口;

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

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

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

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方法,
		whale.move();//可以调用原来的方法  鲸鱼靠鳍游动......
	}
}

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();
}

三、静态内部类

1.静态有名内部类

//Body类:
package com.jd;

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

	/**
	 * 静态有名内部类
	 */
	public static class Heart{

		public void beat(){
			System.out.println("正在跳动...");
		}
	}
	
	public static void main(String[] args) {
		Heart heart = new Heart();
		//本类使用则无须使用外部类类名
		heart.beat();
}


----------


//Test类:
package com.jd;

import com.jd.Body.Heart;//引包

public class Test {

	public static void main(String[] args) {
		Heart heart = new Body.Heart();
		//跨类使用则须“外部类类名.内部类名”
		heart.beat();
	}
}

2.静态匿名内部类

class Father {

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


public class OutClass {

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

注意:

1.static内部类只能直接定义在外部类中

内部类_第1张图片

2.静态内部类仅能直接访问外部类的静态成员变量和方法,可以通过创建外部类的对象间接使用非静态的成员变量和方法。

public class OutClass {
	
	private double weight=72;
	
	public static void print(String name) {
		System.out.println(name);
	}
	
	static class InClass{
		{
			double weight = new OutClass().weight;
			//由于weight是非静态的,所以在静态内部类中使用时必须先创建外部类对象
			print("Tom");//由于print方法为静态方法,所以可以直接使用。
		}
	}
}

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

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

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

               内部类_第2张图片

             内部类_第3张图片

              内部类_第4张图片

特点:

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

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

3.内部类可以直接定义在类中,也可以定义在方法或代码块中;

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

4.内部类可以访问外部类的所有访问权限的成员变量

5.在局部变量作用的范围内,如果定义的内部类需要使用该局部变量,则该变量必须有final修饰。

6.从 Java 8开始,如果定义的内部类需要使用该局部变量,则该变量可以不使用final修饰。

代码1
public class OutClass {

	public void print(final String name) {//由于局部变量name要在InClass内部类中使用,所以需要加final;方法参数前面加final修饰表示只能在调用方法时为该参数指定值,不允许再在方法体中进行二次修改。
		final int weight = 9;//由于局部变量weight要在InClass内部类中使用,所以需要加final;
		class InClass{
			public void print() {
				System.out.println(name+","+weight);
			}
		}
		new InClass().print();
	}
	
	public static void main(String[] args) {
		new OutClass().print("Tom");
	}
}

代码2
public class OutClass {

	public static void main(String[] args) {
		final int i = 8;//由于局部变量i要在InClass内部类中使用,所以需要加final;
		class InClass {
			public void print() {
				System.out.println(i);
			}
		}
		InClass inClass = new InClass();
		inClass.print();
	}
}

 

你可能感兴趣的:(内部类)