内部类方法调用
有如下类:
public class Body {
private String name;
public class Heart{
public void beat(){
System.out.println("heart beats");
}
}
//外部类调用内部类方法
public void bodyMethod(){
new Heart().beat();
}
}
则有两种方法调用内部类Heart:
public class InnerClassDemo01 {
public static void main(String[] args) {
//用外部类方法调用内部类方法
Body body = new Body();
body.bodyMethod();
System.out.println("------------------");
//直接创建内部类对象
Body.Heart heart = new Body().new Heart();
heart.beat();
}
}
内部类同名变量的访问
内部类同名变量访问方式如下:
public class Outer {
int num = 10;
public class Inner {
int num = 20;
public void innerMethod() {
int num = 30;
System.out.println(num); //方法内局部变量
System.out.println(this.num); //内部类成员变
System.out.println(Outer.this.num); //外部类成员变量
}
}
}
局部内部类
局部内部类和一般内部类的区别是:局部内部类是在方法里的。
public class Outer {
public static void main(String[] args) {
}
public void outerMethod() {
class Inner { //局部内部类
int num = 10;
public void innerMethod() {
System.out.println(num);
}
}
Inner inner = new Inner();
inner.innerMethod();
}
}
要想调用局部内部类,只能调用外部类方法:
public class DemoMain {
public static void main(String[] args) {
Outer obj = new Outer();
obj.outerMethod();
}
}
权限修饰符小结
- 外部类:public / (default)
- 成员内部类:public / protected / (default) / private
- 局部内部类:什么都不能写
局部内部类final问题
局部内部类访问方法的局部变量,该局部变量必须是有效final的。
/*
局部内部类,如果要访问所在方法的局部变量,该变量必须是“有效final的”
从Java 9开始,只要局部变量事实不变,那么final关键字可以省略
这与生命周期有关。
1.因为new生成的对象在堆内存中,而局部变量在栈内存中
2.方法运行结束之后出栈,局部变量消失
3.new出来的对象持续存在,直至垃圾回收
*/
public class MyOuter {
public void outerMethod() {
int num1 = 10;
final int num2 = 20;
int num3 = 30;
num3++;
class MyInner {
public void method() {
System.out.println(num1);
System.out.println(num2);
// System.out.println(num3); 报错
}
}
}
}
匿名内部类
在内部类中用得最多,也是最重要的,是Lambda表达式的基础。
有接口如下:
public interface MyInterface {
void method();
}
通常情况下,先在一个类中实现该接口,然后在该类调用接口的方法:
public class MyInterfaceImpl implements MyInterface{
@Override
public void method() {
System.out.println("实现类覆盖重写方法!");
}
}
匿名内部类的实现方法:
/*
如果接口的实现类,或父类的子类,只需要使用一次
这种情况下可以省略掉该类的定义,而改为匿名内部类,格式如下
接口/抽象类名称 对象名 = new 接口/抽象类名称(){
//覆盖重写所有抽象方法
};
*/
public class DemoMain {
public static void main(String[] args) {
MyInterface obj1 = new MyInterfaceImpl();
obj1.method();
System.out.println("-----------------");
//使用匿名内部类
MyInterface obj2 = new MyInterface() {
@Override
public void method() {
System.out.println("匿名内部类覆盖重写方法!");
}
};
obj2.method();
}
}
内部类使用示例
public interface Skill {
public void use();
}
//Clone是英雄的一种技能
public class Clone implements Skill{
@Override
public void use() {
System.out.println("Clone");
}
}
public interface Weapon {
public void use();
}
public class Hero {
private String name;
private Skill skill;
private Weapon weapon;
public Hero(String name) {
this.name = name;
}
public Skill getSkill() {
return skill;
}
public void setSkill(Skill skill) {
this.skill = skill;
}
public Weapon getWeapon() {
return weapon;
}
public void setWeapon(Weapon weapon) {
this.weapon = weapon;
}
public void attack(){
System.out.println(name + "attack with" + weapon);
}
public String getName() {
return name;
}
}
public class DemoGame {
public static void main(String[] args) {
Hero hero = new Hero("Ethan");
//使用了匿名对象,Clone对象没有名字
hero.setSkill(new Clone());
//使用了匿名内部类,实现Skill接口的类没有名字
Skill skill = new Skill() {
@Override
public void use() {
System.out.println("anonymous skill");
}
};
hero.setSkill(skill);
//同时使用匿名对象和匿名内部类
hero.setWeapon(new Weapon() {
private String weaponName = "sword";
@Override
public void use() {
System.out.println(hero.getName() + "use" + weaponName);
}
});
}
}