内部类的使用与概念!

  如果一个事物的内部包含另一个事物,那么这就是一个类内部包含另一个类。

例如; 身体和心脏的关系,又如:汽车和发动机的关系。

 

 

分类;

1,成员内部类。

2,局部内部类(包含匿名内部类)

 

成员内部类的定义格式:
 修饰符 class 外部类名称 {

       修饰符 class 内部类名称 { 

         ///。。。

        }

     ///。。。

}

 

演示外部类和内部类。

 1 public class Body {//外部类
 2 
 3     public class Heart {//成员内部类
 4 
 5         //内部类的方法
 6         public void beat() {
 7             System.out.println("心脏跳动,蹦蹦蹦!");
 8             System.out.println("我叫:" + name);//正确写法!
 9         }
10 
11     }
12 
13     //外部类的成员方法
14     private String name;
15 
16 
17     //外部类的方法
18     public void methodBody() {
19         System.out.println("外部类方法");
20     }
21 
22     public String getName() {
23         return name;
24     }
25 
26     public void setName(String name) {
27         this.name = name;
28     }
29 }
30  

 

 

注意:内用外,随意访问。   外用内,需要内部类对象。

=============================================

成员内部类的使用;

 如何使用成员内部类?有两种方法;

1,【间接方法】在外部类的方法当中,使用内部类,然后main只是调用外部类的方法。

2,【直接方法】  公式:

一般创建对象的常用公式;类名称 对象名 =  new  类名称();

直接调用内部类的公式; 【外部类名称  .  内部类的名称   对象名 = new 外部类名称()  .   new 内部类名称();】

记忆技巧:【外点内】

 1 public class lei {
 2     public static void main(String[] args) {
 3 
 4         //间接方法
 5         Body body = new Body();//外部类的对象
 6         //通过外部类的对象,调用外部类方法,里面间接在使用内部类Heart。
 7         body.methodBody();
 8 
 9         System.out.println("=========================");
10 
11         //直接方法
12         Body.Heart heart = new Body().new Heart();
13         heart.beat();
14 
15     }
16 
17 }

 

 

 

 

 

 

内部类的同名变量访问:

如果出现重名现象,那么格式是:【外部类名称 . this . 外部类成员变量名】

 

 1 public class Outer {
 2 
 3     int num = 10;//外部类的成员变量
 4 
 5     public class Inner/* extends Object*/ {
 6 
 7         int num = 20;//内部类的成员变量
 8 
 9         public void methodInner() {
10 
11             int num = 30;//内部类方法的局部变量
12 
13             System.out.println(num);//局部变量,就近原则
14             System.out.println(this.num);//内部类的成员变量
15             System.out.println(Outer.this.num);//外部类的成员变量
16         }
17 
18 
19     }
20 }

 

调取方法;

 1 Outer.Inner inner = new Outer().new Inner();

2 inner.methodInner(); 

 

 

 

 

 

 局部内部类定义;

如果一个类是定义在方法内部的,那么这就是一个局部内部类。

局部提点:只有当前所属的方法才能使用它,出来这个方法外面就不能用了。

 

 

小节一下类的权限修饰符:

public   >   protected   >   (default)   >   private

定义一个类的时候,权限修饰符规则:

1,外部类: Public /  (default)

2,成员内部类:public   /   protected   /   (default)   /   private

3,局部内部类:什么都不能写

 

 1 public class OuterA {
 2 
 3     public void methodOuterA(){
 4 
 5 
 6         class Inner{//局部内部类
 7             int num = 10;
 8             public void methodInner() {
 9 
10                 System.out.println(this .num); //调用局部内部变量。
11 
12             }
13         }
14         Inner inner = new Inner();
15         inner.methodInner();
16 
17     }
18 
19 
20 
21 }

 

 

 

  局部内部类的final问题:

 

局部内部类,如果希望访问所在方法的局部变量,那么这个局部变量必须是【有效final的】

备注;从Java 8+开始,只要局部变量事实不变,那么final关键字可以省略。

原因:

1,new出来的对象在堆内存当中。

2,局部变量是跟着方法走的,在栈内存当中。

3,方法运行结束之后,立刻出栈,局部变量就会立刻消失。

4,但是new出来的对象会在堆中持续存在,直到垃圾回收消失。

 1 public class OuterA {
 2 
 3     public void methodOuterA(){
 4 
 5 
 6         class Inner{//局部内部类
 7            final int num = 10;
 8             public void methodInner() {
 9 
10                 System.out.println(this .num); //调用局部内部变量。
11 
12             }
13         }
14         Inner inner = new Inner();
15         inner.methodInner();
16 
17     }
18 
19 }

 

 在第7行里 那个final 可以不写,但是 有一个重要的信息 就是和final一样的作用。

 

 

 

 

 

匿名内部类:

如果接口的实现类(或者是父类的子类)只需要使用唯一的一次,

那么这种情况下就可以省略掉该类的定义,而改为使用【匿名内部类】。

 

匿名内部类的定义格式:

接口名称 对象名 = new 接口名称 () {

                    //覆盖重写所有抽象方法

  };

 1 public class DemoMain {
 2     public static void main(String[] args) {
 3    /*     MyInterface obj = new MyInterfaceImpl();
 4         obj.method();
 5 */
 6 
 7         MyInterface obj = new MyInterface() {
 8             @Override
 9             public void method() {
10                 System.out.println("匿名内部类实现了方法!"
11                 );
12 
13             }
14         };
15         obj .method();
16 
17 
18     }
19 }

 

 

 

 

 

 

匿名内部类的注意事项;

 

对格式“ new 接口名称(){....} ”进行解释:
1,new代表创建对象的动作。

2,接口名称就是匿名内部类需要实现那个接口。
3,{。。。}这才是匿名内部类的内容。

 

另外还有注意几点问题;

1,匿名内部类,在【创建对象】的时候,只能使用唯一 一次。

如果希望多次创建对象,而且类的内容一样的话,那么就必须使用单独定义的实现类了。

2,匿名对象,在【调用方法】的时候,只能用唯一 一次。

如果希望同一个对象,调用多次方法,那么必须给对象起个名字。

3,匿名内部类是省略了【实现类/子类名称】,但是匿名对象是省略了【对象名称】

强调:匿名内部类和匿名对象不是一回事!!!

 

 

 1 public class DemoMain {
 2     public static void main(String[] args) {
 3    /*     MyInterface obj = new MyInterfaceImpl();
 4         obj.method();
 5 */
 6 
 7         MyInterface obj = new MyInterface() {
 8             @Override
 9             public void method1() {
10                 System.out.println("匿名内部类实现了方法! 111- A");
11 
12             }
13 
14             @Override
15             public void method2() {
16                 System.out.println("匿名内部类实现了方法! 222- A");
17 
18             }
19         };
20         obj.method1();
21         obj.method2();
22         System.out.println("-----------------------------------");
23 
24         //使用了匿名内部类,而且省略了对象名称,也是匿名对象。
25         new MyInterface() {
26             @Override
27             public void method1() {
28                 System.out.println("匿名内部类实现了方法! 111- B");
29 
30             }
31 
32             @Override
33             public void method2() {
34                 System.out.println("匿名内部类实现了方法! 222- B");
35 
36             }
37         }.method1();
38         //因为匿名对象无法调用第二次方法,所以需要再创建一个匿名内部类的匿名对象
39 
40         new MyInterface() {
41             @Override
42             public void method1() {
43                 System.out.println("匿名内部类实现了方法! 111- B");
44 
45             }
46 
47             @Override
48             public void method2() {
49                 System.out.println("匿名内部类实现了方法! 222- B");
50 
51             }
52         }.method2();
53         
54     }
55 }

     

 

 

类作为成员变量类型;

 

成员变量不但可以基本类型,还可以用任何一种类class。

 

本节内容主要讲了是 :在成员变量里,也可以用类来当变量类型。

如下图里的 "private Weapon wwapon"  也可以用来变量使用。

 

普通类;

 

 1 public class Hero {
 2 
 3     private String name;//英雄的名子
 4     private int age; //英雄的年龄
 5     private Weapon weapon;//武器
 6 
 7     public Hero() {
 8     }
 9 
10     public Hero(String name, int age, Weapon weapon) {
11         this.name = name;
12         this.age = age;
13         this.weapon = weapon;
14     }
15 
16     public void attack() {
17         System.out.println("年龄为" + age + "的" + name + " 用" + weapon.getCode() + "攻击敌方。");
18     }
19 
20     public String getName() {
21         return name;
22     }
23 
24     public void setName(String name) {
25         this.name = name;
26     }
27 
28     public int getAge() {
29         return age;
30     }
31 
32     public void setAge(int age) {
33         this.age = age;
34     }
35 
36     public Weapon getWeapon() {
37         return weapon;
38     }
39 
40     public void setWeapon(Weapon weapon) {
41         this.weapon = weapon;
42     }
43 }

 

类;

这个类是单独写出啦的,里面有构造方法和get/set方法。可以理解定义一个类。给Hero 用的。

 

 1 public class Weapon {
 2 
 3     private String code; //武器的代号
 4 
 5     public Weapon() {
 6 
 7     }
 8 
 9     public Weapon(String code) {
10         this.code = code;
11     }
12 
13     public String getCode() {
14         return code;
15     }
16 
17     public void setCode(String code) {
18         this.code = code;
19     }
20 }

 

 

输出:

 注意看  10/12行里的代码。

 1 public class DemoMain {
 2 
 3     public static void main(String[] args) {
 4         //创建一个英雄角色
 5         Hero hero = new Hero();
 6         //为英雄起一个名字,并且设置年龄
 7         hero.setName("盖伦");
 8         hero.setAge(20);
 9 
10         //创建一个武器对象
11         Weapon weapon = new Weapon("AK-47");
12         hero.setWeapon(weapon);
13 
14         hero.attack();
15 
16 
17     }
18 
19 }

 

 

 

 

 接口作为成员变量类型:

 利用skill做为成员变量类型

 

普通类:

 1 public class Hero {
 2 
 3     private String name;//英雄的名称
 4     private Skill skill;//英雄的技能
 5 
 6     public Hero() {
 7     }
 8 
 9     public Hero(String name, Skill skill) {
10         this.name = name;
11         this.skill = skill;
12     }
13 
14 
15     public void attack() {
16         System.out.println("我叫" + name + ", 开始施放技能:");
17         
18         skill.use();//调用接口中的抽象方法
19 
20         System.out.println("施放技能完成!");
21     }
22 
23     public String getName() {
24         return name;
25     }
26 
27     public void setName(String name) {
28         this.name = name;
29     }
30 
31     public Skill getSkill() {
32         return skill;
33     }
34 
35     public void setSkill(Skill skill) {
36         this.skill = skill;
37     }
38 
39     public void setSkill() {
40     }
41 }

 

 

 接口类;

1 public interface Skill {

2 public abstract void use();

3 } 

 

实现接口类 ;

1 public class SkillImpl implements Skill {
2     @Override
3     public void use() {
4         System.out.println("Biu~biu~biu");
5     }
6 }

 

 

 类:

有3种不同的实现方法

 1 public class DemoGame {
 2     public static void main(String[] args) {
 3         Hero hero = new Hero();
 4         hero.setName("盖伦");//设置英雄的名称
 5 
 6 
 7         //设置英雄技能
 8 /*
 9         hero.setSkill(new SkillImpl());//使用单独定义类的实现类  //方法 1
10 */
11 
12 
13 /*
14         //使用匿名内部类                      //方法2
15         Skill skill = new Skill() {
16             @Override
17             public void use() {
18                 System.out.println("Pia~pia~pia~");
19             }
20         };
21         hero.setSkill(skill);
22 */
23 
24 
25 
26         //进一步简化,同时使用匿名内部类和匿名对象 //方法3
27         hero.setSkill(new Skill() {
28             @Override
29             public void use() {
30                 System.out.println("Biu~pia~Biu~pia");
31             }
32         });
33 
34 
35         hero.attack();
36 
37 
38     }
39 }

 

 

方法1的

 

 

方法2的

 

 

方法3的

 

 

 

 

 

 

 

posted @ 2020-10-27 00:53  ZHU_FENG  阅读(177)  评论(0)    收藏  举报