详述有名内部类与匿名内部类

1.什么是内部类

  • 在一个外部类中定义的类称为内部类
  • 内部类可以直接在类中定义,也可以在方法中和代码块中定义;但是需要注意的是:syso代码块中或方法中才能用
  • 按照是否有类名分为有名内部类和匿名内部类

2.有名内部类

  • 说明:全局有名内部类的使用方式类似于全局变量;局部有名内部类的使用方式类似局部变量——它们都有固定的使用范围
Body类:
package com.jd;

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

	/**
	 * 有名内部类
	 */
	public class Heart{

		public void beat(){
			System.out.println("正在跳动...");
		}
	}
}

Test类:
package com.jd;

import com.jd.Body.Heart;

public class Test {

	public static void main(String[] args) {
		Body body = new Body();
		Heart heart = body.new Heart();
		heart.beat();
	}
}

3.匿名内部类

  • 匿名内部类:匿名内部类没有类名,但是创建对象需要类名,所以匿名内部类在定义的时候要和创建对象一起定义
Object object = new Object() {
};

需要注意的是,匿名内部类后要有一个分号

  • 匿名内部类的语法:

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

  匿名内部类类体     

};

  • 匿名内部类的特点:

1.普通类匿名内部类实质为普通类的子类

普通类:
class Mammal {

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

public class Sea {

	Mammal whale = new Mammal() {//调用Mammal中的无参构造方法

		@Override
		public void move() {
			System.out.println("鲸鱼靠鳍移动......");
		}
	};
}

2.匿名内部类是抽象类的子类

抽象类:
abstract class Mammal {

	public Mammal(String name) {
		System.out.println(name);
	}

	abstract void move();
}
public class Sea {

	Mammal mammal = new Mammal("鲸鱼") {// 调用Mammal中的有参构造方法

		@Override
		void move() {
			System.out.println("鲸鱼靠鳍移动......");
		}
	};
}

3.匿名内部类是接口的实现类

接口:
interface Mammal {
	abstract void move();
}

public class Sea {

	Mammal mammal = new Mammal() {

		@Override
		public void move() {
			System.out.println("鲸鱼靠鳍移动......");
		}
	};
}

需要注意的是,匿名内部类此时必须实现完接口中的所有抽象方法,若没有实现完,则此时的匿名内部类为一个抽象类,这时必须有一个子类完全实现其抽象方法;但是,匿名内部类没有类名,所以没有子类;此时也证明了匿名内部类不能是抽象类。

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

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

代码1:
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();
}
  • 总结:无论是匿名内部类还是有名内部类,javac都会产生一个独立的class文件:编译之后内部类会被编译成独立的.class文件,如果该内部类为有名内部类,则有名内部类字节码文件名为外部类的类名+$+内部类类名;如果为匿名内部类,则匿名内部类字节码文件名为外部类类名+$+数字

4.内部类的其他需要掌握的方面

  • 外部类或外部接口 public 默认的;但是直接在类中定义的内部类,可以有public ~private
package com.edu.zzu.test;

public  class Body {
    int age =12;
	private class Heart {
		void work() {
			System.out.println("正在跳动");
		}
	}
  • 如果在内部类中使用局部变量的值,则:JDK8.0及+可以不适用final修饰,8.0以前必须使用fianl
package com.edu.zzu.test;

public  class Body {
public void eat(final String name) {
		class Baby{
			{
				System.out.println(name);
			}
		}
	}
}

需要注意的是,上述代码不能写到main方法里面,原因很简单,方法不能套方法;

private修饰的成员变量可以在内部类中使用

package com.edu.zzu.test;

public  class Body {

    private int age =12;
	public class Heart {
		void work() {
			System.out.println("正在跳动"+age);
		}
	}
  • 局部变量不能使用访问权限,访问权限用于限制成员变量或方法能否在另一个类中被使用,但因为局部变量已经限定,所以局部变量不能使用访问权限
package com.edu.zzu.test;

public  class Body {

    private int age =12;
	//有名内部类
	public class Heart {
	  private int number=13;
		void work() {
			System.out.println("正在跳动"+age);
		}
	}

此处有一个疑问,这时在内部类中的变量为局部变量,为什么这时候在局部变量的前面加上访问控制符,却并没有报错?

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值