内部类可以分为:
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类(比较重要)
成员内部类: 也叫做非静态内部类,就是一个普通的内部类,不用加其他修饰。
在成员内部类中,不能定义静态属性,原因:
- static类型的属性和方法,在类加载的时候就会存在于内存中;
- 要想使用某个类的static属性和方法,那么这个类必须要加载到虚拟机- 中;
- 非静态内部类并不随外部类一起加载,只有在实例化外部类之后才会加载
调用外部类属性:外部类.this.外部类属性
**静态内部类:**在外部类里面包含一个static修饰的内部类
-
静态内部类中不能使用外部类的成员属性(static修饰的可以)—加载时机问题
-
静态内部类方法的调用—首先要实例化内部类对象
Outter.Inner inner = new Outter.Inner(); inner.test(); 简化版的实例化方式 Inner inner2 = new Inner(); inner2.test();
局部内部类:在外部类的方法中定义一个类,该类限制了只能在该方法中使用,外部不能使用(了解)
class Outter{
String a = "凤姐";
public void test() {
//在局部内部类中使用局部变量会自动加final修饰,确保局部内部类中的值不会销毁
final String b = "刘亦菲";
//public int a = 3; //局部变量不能加public修饰
class Inner{ //同样,局部内部类也不能加public修饰
String a = "芙蓉";
public void show() {
System.out.println(a); //出现冲突,则作用域小的优先---芙蓉
System.out.println(this.a); //还是芙蓉
System.out.println(Outter.this.a); //凤姐
System.out.println(b); //刘亦菲
}
}
new Inner().show(); //局部内部类的使用,只能在所在的方法内
}
}
public class Test1 {
public static void main(String[] args) {
new Outter().test();
}
}
//匿名内部类:本质就是多态,没有名字的内部类,直接通过(接口或抽象类)引用去使用匿名内部类—重点
//案例:喷火娃具备喷火的能力
//匿名内部类与多态的应用场景
//1.当需要实例化多个对象时,推荐使用多态
//2.当只需要实例化一个对象,或在测试案例中,推荐使用匿名内部类
interface Fireable{
public void fire();
}
class Baby implements Fireable{
@Override
public void fire() {
System.out.println("喷火娃正在喷火...");
}
}
public class Test1 {
public static void main(String[] args) {
//----1.直接接口实现多态------
Fireable fireable = new Baby();
fireable.fire();
//----1.直接使用匿名内部类------
/*Fireable fireable2 = new Fireable() {
@Override
public void fire() {
System.out.println("无名英雄在喷火...");
}
};
fireable2.fire();*/
//更简化
new Fireable() {
@Override
public void fire() {
System.out.println("无名英雄在喷火...");
}
}.fire();
}
}
2.匿名内部类以传参方式出现===
interface Usb{
void run();
}
class Disk implements Usb{
@Override
public void run() {
System.out.println(“硬盘在运转…”);
}
}
class Computer{
public void connect(Usb usb) {
usb.run(); //接口回调
}
}
public class Test2 {
//以传参方式实现多态:
//案例:电脑连接usb的硬盘,鼠标…
public static void main(String[] args) {
//2.以传参方式实现多态
Computer computer = new Computer();
computer.connect(new Disk());
//2.匿名内部类以传参方式出现
computer.connect(new Usb() {
@Override
public void run() {
System.out.println("匿名设备在运转");
}
});
}
}
=匿名内部类的应用场景====
//案例2: 定义一个工具类,测试一段执行时间的代码,你只要将这段代码放进去,我就能测试来花了多长时间
//使用匿名内部类来完成
//作用:灵活性和可扩展性更强,复用性更强---后续过滤器,拦截器,springaop都是这种思想
//提示: 测试使用 System.currentTimeMillis()
//接口实现多态的改造: 测试的一段代码具备可运行的标准
//可运行的---接口 执行运行的类----实现类
interface IRunCode{
void runCode();
}
class RunClass implements IRunCode{
@Override
public void runCode() {
//将测试的代码放到此处即可:
String a = "";
for(int i=0;i<1000;i++) {
a += i;
}
}
}
class Tool{
public static long getTime(IRunCode run) {
long start = System.currentTimeMillis();
run.runCode(); //接口回调
long end = System.currentTimeMillis();
return end-start;
}
}
public class Test3 {
public static void main(String[] args) {
/*
long start = System.currentTimeMillis();
//执行循环操作...
long end = System.currentTimeMillis();
System.out.println(end-start);
*/
/*
// 通过匿名内部类完成
long time = Tool.getTime(new IRunCode() {
@Override
public void runCode() {
String a = "";
for(int i=0;i<1000;i++) {
a += i;
}
}
});
System.out.println("该代码的执行时间为:"+time);
*/
//使用接口实现多态:
long time = Tool.getTime(new RunClass());
System.out.println("该代码的执行时间为:"+time);
}
}