内部类
一、访问某内部类中方法的两种方式
* 如果一个事物的内部包含另一个事物,那么这就是一个类内部包含另一个类。
* 例如:身体和心脏的关系。 又如:汽车和发动机的关系。
* 分类:
1. 成员内部类
2. 局部内部类(包含匿名内部类)
* 成员内部类的定义格式:
修饰符 class 外部类名称{
修饰符 class 内部类名称 {
...
}
...
}
* 注意:内用外,随意访问; 外用内,需要内部类对象。
=================================
* 如何使用成员内部类?有两种方式:
1. 间接方式:在外部类的方法当中,使用内部类,然后main只是调用外部类的方法。
2. 直接方式:公式:
类名称 对象名 = new 类名称();
外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();
package cn. itcast. day11. demo03;
public class Body {
public class Heart {
public void beat ( ) {
System. out. println ( "心脏跳动:蹦蹦蹦!" ) ;
System. out. println ( "我叫:" + name) ;
}
}
private String name;
public void methodBody ( ) {
System. out. println ( "在外部类的方法里调用外部类的内部类" ) ;
new Heart ( ) . beat ( ) ;
}
public String getName ( ) {
return name;
}
public void setName ( String name) {
this . name = name;
}
}
package cn. itcast. day11. demo03;
public class Demo01InnerClass {
public static void main ( String[ ] args) {
Body body = new Body ( ) ;
body. methodBody ( ) ;
System. out. println ( "=================" ) ;
Body. Heart heart = new Body ( ) . new Heart ( ) ;
heart. beat ( ) ;
}
}
二、访问重名的外部类成员变量
package cn. itcast. day11. demo03;
public class Outer {
int num = 10 ;
public class Inner {
int num = 20 ;
public void methInner ( ) {
int num = 30 ;
System. out. println ( num) ;
System. out. println ( this . num) ;
System. out. println ( Outer. this . num) ;
}
}
}
package cn. itcast. day11. demo03;
public class Demo02InnerClass {
public static void main ( String[ ] args) {
Outer. Inner obj = new Outer ( ) . new Inner ( ) ;
obj. methInner ( ) ;
}
}
三、局部内部类
* 如果一个类是定义在一个方法内部的,那么这就是一个局部内部类。
“局部”:只有当前所属的方法才能使用它,出了这个方法外面就不能用了
* 定义格式:
修饰符 class 外部类名称{
修饰符 返回值类型 外部类方法名称(参数列表){
class 局部内部类名称{
...
}
}
}
* 小结一下类的权限修饰符:
public > protected > (default) > private
定义一个类的时候,权限修饰符规则:
1. 外部类: public / (default)
2. 成员内部类: public / protected / default private
3. 局部内部类: 什么都不能写
package cn. itcast. day11. demo04;
public class Outer {
public void methodOuter ( ) {
class Inner {
int num = 10 ;
public void methodInner ( ) {
System. out. println ( "num" ) ;
}
}
Inner inner = new Inner ( ) ;
inner. methodInner ( ) ;
}
}
package cn. itcast. day11. demo04;
public class DemoMain {
public static void main ( String[ ] args) {
Outer obj = new Outer ( ) ;
obj. methodOuter ( ) ;
}
}
* 局部内部类,如果希望访问所在方法的局部变量,那么这个局部变量必须是【有效final】的。
* 备注:从Java 8+开始,只要局部变量事实不变,那么final关键字可以省略。
* 原因:
1. new出来的对象在堆内存当中。
2. 局部变量是跟着方法走的,在栈内存当中。
3. 方法运行结束之后,立刻出站,局部变量就会立刻消失。
4. new出来的对象会在堆内存当中持续存在,知道垃圾回收消失
package cn. itcast. day11. demo04;
public class MyOuter {
public void methodOuter ( ) {
final int num = 10 ;
class MyInner {
public void methodInner ( ) {
System. out. println ( num) ;
}
}
}
}
四、匿名内部类-接口的实现类
package cn. itcast. day11. demo05;
public interface MyInterface {
public abstract void method1 ( ) ;
public abstract void method2 ( ) ;
}
package cn. itcast. day11. demo05;
public class MyInterfaceImpl implements MyInterface {
@Override
public void method1 ( ) {
System. out. println ( "实现类覆盖重写了方法!111" ) ;
}
@Override
public void method2 ( ) {
System. out. println ( "实现类覆盖重写了方法!222" ) ;
}
}
* 如果接口的实现类(或者是父类的子类),只需要使用唯一一次。
那么这种情况下就可以省略掉该类的定义,而改为使用【匿名内部类】。
* 匿名内部类的定义格式:
接口名称 对象名 = new 接口名称(){
//覆盖重写所有抽象方法
};
* 对格式 “new 接口名称(){ ... }” 进行解析:
1. new代表创建对象的动作
2. 接口名称就是匿名内部类需要实现哪个接口
3. { ... }才是匿名内部类的内容
* 另外还要注意几点问题:
1. 匿名内部类在创建对象的时候,只能使用唯一一次。
2. 匿名对象,在【调用方法】的时候,只能调用唯一一次。
如果希望同一个对象,调用多次方法,那么必须给对象起一个名字。
3. 匿名内部类是省略了【实现类/子类名称】。但匿名对象是省略了【对象名称】
强调:匿名内部类和匿名对象不是一回事!!! 匿名内部类是大括号 { } 里的内容,但没有名称
package cn. itcast. day11. demo05;
public class DemoMain {
public static void main ( String[ ] args) {
MyInterface impl = new MyInterfaceImpl ( ) ;
MyInterface objA = new MyInterface ( ) {
@Override
public void method1 ( ) {
System. out. println ( "匿名内部类实现了方法!111-A" ) ;
}
@Override
public void method2 ( ) {
System. out. println ( "匿名内部类实现了方法!222-A" ) ;
}
} ;
objA. method1 ( ) ;
objA. method2 ( ) ;
System. out. println ( "==============" ) ;
new MyInterface ( ) {
@Override
public void method1 ( ) {
System. out. println ( "匿名内部类实现了方法!111-B" ) ;
}
@Override
public void method2 ( ) {
System. out. println ( "匿名内部类实现了方法!222-B" ) ;
}
} . method1 ( ) ;
new MyInterface ( ) {
@Override
public void method1 ( ) {
System. out. println ( "匿名内部类实现了方法!111-B" ) ;
}
@Override
public void method2 ( ) {
System. out. println ( "匿名内部类实现了方法!222-B" ) ;
}
} . method1 ( ) ;
}
}
五、类作为成员变量的类型
package cn. itcast. day11. demo06;
public class Hero {
private String name;
private int age;
private Weapon weapon;
public Hero ( ) {
}
public Hero ( String name, int age, Weapon weapon) {
this . name = name;
this . age = age;
this . weapon = weapon;
}
public void attack ( ) {
System. out. println ( "年龄为" + age + "的" + name + "用" + weapon. getCode ( ) + "攻击敌方" ) ;
}
public String getName ( ) {
return name;
}
public void setName ( String name) {
this . name = name;
}
public int getAge ( ) {
return age;
}
public void setAge ( int age) {
this . age = age;
}
public Weapon getWeapon ( ) {
return weapon;
}
public void setWeapon ( Weapon weapon) {
this . weapon = weapon;
}
}
package cn. itcast. day11. demo06;
public class Weapon {
private String code;
public Weapon ( ) {
}
public Weapon ( String code) {
this . code = code;
}
public String getCode ( ) {
return code;
}
public void setCode ( String code) {
this . code = code;
}
}
package cn. itcast. day11. demo06;
public class DemoMain {
public static void main ( String[ ] args) {
Hero hero = new Hero ( ) ;
hero. setName ( "盖伦" ) ;
hero. setAge ( 20 ) ;
Weapon weapon = new Weapon ( "多兰剑" ) ;
hero. setWeapon ( weapon) ;
hero. attack ( ) ;
}
}
六、接口作为成员变量类型
package cn. itcast. day11. Demo07;
public class DemoGame {
public static void main ( String[ ] args) {
Hero hero = new Hero ( ) ;
hero. setName ( "艾希" ) ;
hero. setSkill ( new Skill ( ) {
@Override
public void use ( ) {
System. out. println ( "Biu~Pia~Biu~Pia~" ) ;
}
} ) ;
hero. attack ( ) ;
}
}
package cn. itcast. day11. Demo07;
public class Hero {
private String name;
private Skill skill;
public Hero ( ) {
}
public Hero ( String name, Skill skill) {
this . name = name;
this . skill = skill;
}
public void attack ( ) {
System. out. println ( "我叫" + name + ",开始释放技能:" ) ;
skill. use ( ) ;
System. out. println ( "释放技能完成。" ) ;
}
public String getName ( ) {
return name;
}
public void setName ( String name) {
this . name = name;
}
public Skill getSkill ( ) {
return skill;
}
public void setSkill ( Skill skill) {
this . skill = skill;
}
}
package cn. itcast. day11. Demo07;
public interface Skill {
void use ( ) ;
}
package cn. itcast. day11. Demo07;
public class SkillImpl implements Skill {
@Override
public void use ( ) {
System. out. println ( "Biu~biu~biu~" ) ;
}
}
七、接口作为方法的参数和返回值
package cn. itcast. day11. Demo07;
import java. util. ArrayList;
import java. util. List;
public class DemoInterface {
public static void main ( String[ ] args) {
List< String> list = new ArrayList < > ( ) ;
List< String> result = addNames ( list) ;
for ( int i = 0 ; i < result. size ( ) ; i++ ) {
System. out. println ( "result.get(i)" ) ;
}
}
public static List< String> addNames ( List< String> list) {
list. add ( "迪丽热巴" ) ;
list. add ( "古尼娜扎" ) ;
list. add ( "马尔扎哈" ) ;
list. add ( "沙扬娜拉" ) ;
return list;
}
}