JAVA面向对象学习——java面向对象概念———内部类

                                                      内部类

 

Java从JDK 1.1开始引入内部类,内部类主要有如下作用:

 

➢ 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。

 

➢ 内部类成员可以直接访问外部类的私有数据,因为内部类被当成其外部类成员,同一个类的成员之间可以互相访问。

     但外部类不能访问内部类的实现细节,例如内部类的成员变量。

 

➢ 匿名内部类适合用于创建那些仅需要一次使用的类。

 

 

 

 

从语法角度来看,定义内部类与定义外部类的语法大致相同,内部类除需要定义在其他类里面之外,还存在如下两点区别:

 

➢ 内部类比外部类可以多使用三个修饰符:private、protected、static—外部类不可以使用这三个修饰符。

 

➢ 非静态内部类不能拥有静态成员。

 

 

 实例变量就是每个实例都有自己的一份拷贝,实例之间没有影响。类变量就是这个类的所有实例都共享一个变量,一改都改了。

 

 

6.7.1 非静态内部类


内部类都被作为成员内部类定义,而不是作为局部内部类。成员内部类是一种与成员变量、方法、构造器和初始化块相似的类成员;局部内部类和匿名内部类则不是类成员。

 

成员内部类分为两种:静态内部类和非静态内部类,使用static修饰的成员内部类是静态内部类,没有使用static修饰的成员内部类是非静态内部类。

 

成员内部类(包括静态内部类、非静态内部类)的class文件总是这种形式:OuterClass$InnerClass.class。

 

当在非静态内部类的方法内访问某个变量时,系统优先在该方法内查找是否存在该名字的局部变量,如果存在就使用该变量;

如果不存在,则到该方法所在的内部类中查找是否存在该名字的成员变量,如果存在则使用该成员变量;

如果不存在,则到该内部类所在的外部类中查找是否存在该名字的成员变量,如果存在则使用该成员变量;

如果依然不存在,系统将出现编译错误:提示找不到该变量。

 

因此,如果外部类成员变量、内部类成员变量与内部类里方法的局部变量同名,则可通过使用this、外部类类名.this作为限定来区分。

 

 

 

非静态内部类的成员可以访问外部类的实例成员,但反过来就不成立了。如果外部类需要访问非静态内部类的实例成员,则必须显式创建非静态内部类对象来调用访问其实例成员。

 

根据静态成员不能访问非静态成员的规则,外部类的静态方法、静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例等。

 

总之不允许在外部类的静态成员中直接使用非静态内部类

 

Java不允许在非静态内部类里定义静态成员,非静态内部类里不能有静态方法、静态成员变量、静态初始化块。

 

-----------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
public class Cow
{
    private double weight;
     
    public Cow()                  // 外部类的两个重载的构造器
    {
         
    }
     
    public Cow(double weight)
    {
        this.weight = weight;
    }
     
     
    private class CowLeg                 // 定义一个非静态内部类
    {
         
        private double length;               // 非静态内部类的两个实例变量
        private String color;
         
        public CowLeg()                   // 非静态内部类的两个重载的构造器
        {
             
        }
         
        public CowLeg(double length, String color)
        {
            this.length = length;
            this.color = color;
        }
         
        public void setLength(double length)    // 下面省略length、color的setter和getter方法
        {
            this.length = length;
        }
         
        public double getLength()
        {
            return this.length;
        }
         
        public void setColor(String color)
        {
            this.color = color;
        }
         
        public String getColor()
        {
            return this.color;
        }
         
        public void info()   // 非静态内部类的实例方法
        {
            System.out.println("当前牛腿颜色是:" + color + ", 高:" + length);
             
            System.out.println("本牛腿所在奶牛重:" + weight);    // 直接访问外部类的private修饰的成员变量
        }
    }
     
    public void test()
    {
        CowLeg cl = new CowLeg(1.12, "黑白相间");
        cl.info();
    }
     
    public static void main(String[] args)
    {
        Cow cow = new Cow(378.9);
        cow.test();
    }
}

  

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
public class Cow
{
    private double weight;
 
    public Cow()
    {
 
    }
 
    public Cow(double weight)
    {
        this.weight = weight;
    }
 
 
    private class CowLeg
    {
 
        private double length;
        private String color;
 
        public CowLeg()
        {
 
        }
 
        public CowLeg(double length, String color)
        {
            this.length = length;
            this.color = color;
        }
 
        public void setLength(double length)
        {
            this.length = length;
        }
 
        public double getLength()
       {
        return this.length;
        }
 
        public void setColor(String color)
        {
            this.color = color;
        }
 
        public String getColor()
        {
            return this.color;
        }
 
        public void info()
        {
            System.out.println(color + "----------" + length);
 
            System.out.println(weight);
        }
    }
 
    public void test()
    {
        CowLeg cl = new CowLeg(1.12, "黑白相间");
        cl.info();
    }
 
    public static void main(String[] args)
    {
        Cow cow = new Cow(378.9);
        cow.test();
    }
}

  

 

 

 

 

------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------

 

当在非静态内部类的方法内访问某个变量时,系统优先在该方法内查找是否存在该名字的局部变量,如果存在就使用该变量;


如果不存在,则到该方法所在的内部类中查找是否存在该名字的成员变量,如果存在则使用该成员变量;


如果不存在,则到该内部类所在的外部类中查找是否存在该名字的成员变量,如果存在则使用该成员变量;


如果依然不存在,系统将出现编译错误:提示找不到该变量。


因此,如果外部类成员变量、内部类成员变量与内部类里方法的局部变量同名,则可通过使用 this、外部类类名.this 作为限定来区分。

 

 

如下程序所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class DiscernVariable
{
    private String prop = "外部类的实例变量";
     
    private class InClass
    {
        private String prop = "内部类的实例变量";
        public void info()
        {
            var prop = "局部变量";
             
            System.out.println("外部类的实例变量值:" + DiscernVariable.this.prop);   // 通过 外部类类名.this.varName 访问外部类实例变量
             
            System.out.println("内部类的实例变量值:" + this.prop);  // 通过 this.varName 访问内部类实例的变量
             
            System.out.println("局部变量的值:" + prop);    // 直接访问局部变量
        }
    }
     
    public void test()
    {
        InClass in = new InClass();
        in.info();
    }
     
    public static void main(String[] args)
    {
        new DiscernVariable().test();
    }
}

  

 

 

 

 

 

 

 

执行结果:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------

 

非静态内部类的成员,可以访问外部类的实例成员。反过来就不成立。

 

如果外部类需要访问非静态内部类的实例成员,则必须显式创建非静态内部类对象来调用访问其实例成员

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Outer
{
    private int outProp = 9;
    class Inner
    {
        private int inProp = 5;
        public void accessOuterProp()
        {
            // 非静态内部类可以直接访问外部类的private实例变量
 
            System.out.println("外部类的outProp值:" + outProp);
        }
    }
    public void accessInnerProp()
    {
        // 外部类不能直接访问非静态内部类的实例变量,
        // 下面代码出现编译错误
        // System.out.println("内部类的inProp值:" + inProp);
        // 如需访问内部类的实例变量,必须显式创建内部类对象
 
        System.out.println("内部类的inProp值:" + new Inner().inProp);
    }
    public static void main(String[] args)
    {
        // 执行下面代码,只创建了外部类对象,还未创建内部类对象
 
        var out = new Outer();      // ①
        out.accessInnerProp();
    }
}

  

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Outer
{
    private int outProp = 9;
     
    class Inner
    {
        private int inProp = 5;
        public void accessOuterProp()
        {
            System.out.println("outProp:" + outProp);
        }
    }
    public void accessInnerProp()
    {
 
        System.out.println("inProp:" + new Inner().inProp);
    }
    public static void main(String[] args)
    {
 
        Outer out = new Outer();
        out.accessInnerProp();
    }
}

 

 

 

 

 

 

根据静态成员不能访问非静态成员的规则,外部类的静态方法、静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例等。

 

总之,不允许在外部类的静态成员中直接使用非静态内部类。

 

 

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

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

 

6.7.2 静态内部类

 

 

 

如果使用static来修饰一个内部类,则这个内部类就属于外部类本身,而不属于外部类的某个对象

 

因此使用static修饰的类为类内部类,有的地方也称之为静态内部类。

 

 

 

 

static 关键字的作用是把类的成员变成类相关,而不是实例相关,即 statice修饰的成员属于整个类,而不属于单个对象。

 

外部类的上一级程序单元是包,所以不可使用 static修饰:而内部类的上一级程序单元是外部类,使用 statice 修饰可以将内部类变成外部类相关,而不是外部类实例相关。

 

因此 static 关键宇不可修饰外部类,但可修饰内部类。

 

 

 

 

静态内部类可以包含静态成员,也可以包含非静态成员。

 

根据静态成员不能访问非静态成员的规则,静态内部类不能访问外部类的实例成员,只能访问外部类的类成员

 

即使是静态内部类的实例方法也不能访问外部类的实例成员,只能访问外部类的静态成员。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class StaticInnerClassTest
{
    private int prop1 = 5;<br>
    private static int prop2 = 9;<br>
    static class StaticInnerClass
    {
        // 静态内部类里可以包含静态成员
        private static int age;<br>
        public void accessOuterProp()           //这是一个实例方法
        {
            // 下面代码出现错误:
            // 静态内部类无法访问外部类的实例变量
//          System.out.println(prop1);<br>
            // 下面代码正常
            System.out.println(prop2);
        }
    }

  

 

 

 

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class AccessStaticInnerClass
{
    static class StaticInnerClass
    {
        private static int prop1 = 5;
         
        private int prop2 = 9;
    }
    public void accessInnerProp()
    {
//      System.out.println(prop1);
 
        // 上面代码出现错误,应改为如下形式:
         
        // 通过类名访问静态内部类的类成员
        System.out.println(StaticInnerClass.prop1);
         
//      System.out.println(prop2);
        // 上面代码出现错误,应改为如下形式:
         
        // 通过实例访问静态内部类的实例成员
        System.out.println(new StaticInnerClass().prop2);
    }
}

  

 

 

 

如果用static修饰一个内部类,称为静态内部类。

静态内部类可以包含静态成员,也可以包含非静态成员。

所以静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。

静态内部类的对象寄存在外部类里,非静态内部类的对象寄存在外部类实例里

 

 

 

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

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

 

 

 

6.7.3 使用内部类

 

 

1.在外部类内部使用内部类

 

从前面程序中可以看出,在外部类内部使用内部类时,与平常使用普通类没有太大的区别。

 

一样可以直接通过内部类类名来定义变量,通过new调用内部类构造器来创建实例。

 

唯一存在的一个区别是:不要在外部类的静态成员(包括静态方法和静态初始化块)中使用非静态内部类,因为静态成员不能访问非静态成员。

 

在外部类内部定义内部类的子类与平常定义子类也没有太大的区别。

 

 

 

2.在外部类以外使用非静态内部类

如果希望在外部类以外的地方访问内部类(包括静态和非静态两种),则内部类不能使用private访问控制权限,private修饰的内部类只能在外部类内部使用。

 

对于使用其他访问控制符修饰的内部类,则能在访问控制符对应的访问权限内使用:

 

➢ 省略访问控制符的内部类,只能被与外部类处于同一个包中的其他类所访问。

➢ 使用protected修饰的内部类,可被与外部类处于同一个包中的其他类和外部类的子类所访问。

➢ 使用public修饰的内部类,可以在任何地方被访问。

 

在外部类以外的地方定义内部类(包括静态和非静态两种)变量的语法格式如下:

 

由于非静态内部类的对象必须寄生在外部类的对象里,因此创建非静态内部类对象之前,必须先创建其外部类对象。

 

在外部类以外的地方创建非静态内部类实例的语法如下:

 

 

 

 

3.在外部类以外使用静态内部类

因为静态内部类是外部类类相关的,因此创建静态内部类对象时无须创建外部类对象。在外部类以外的地方创建静态内部类实例的语法如下:

 

 

 

 

 

1.在外部类内部使用内部类-不要在外部类的静态成员中使用非静态内部类,国为静态成员不能访问非静态成员。

 

2.在外部类以外使用非静态内部类。

 

 

private 修饰的内部类只能在外部类内部使用。

 

 

 

在外部类以外的地方使用内部类,内部类完整的类名应该OuterClass.InnerClass.

 

在外部类以外的地方使用非静态内部类创建对象的语法如下:OuterInstance.new InnerConstructor()

 

在外部类以外的地方使用静态内部类创建对象的语法如下:new OuterClass.InnerConstructer();

 

 

 

 

 实例:如何在外部类以外的地方创建非静态内部类对象,并把它赋给非静态内部类类型的变量。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Out
{
    // 定义一个内部类,不使用访问控制符,
    // 即只有同一个包中其他类可访问该内部类
    class In
    {
        public In(String msg)
        {
            System.out.println(msg);
        }
    }
}
public class CreateInnerInstance
{
    public static void main(String[] args)
    {
        Out.In in = new Out().new In("测试信息");<br>
        /*
        上面代码可改为如下三行代码:<br>
        使用OuterClass.InnerClass的形式定义内部类变量
        Out.In in;<br>
        创建外部类实例,非静态内部类实例将寄存在该实例中
        Out out = new Out();<br>
        通过外部类实例和new来调用内部类构造器创建非静态内部类实例
        in = out.new In("测试信息");
        */
    }
}

  

上面程序中粗体代码行创建了一个非静态内部类的对象。

 

从上面代码可以看出,非静态内部类的构造器必须使用外部类对象来调用。

 

 

如果需要在外部类以外的地方创建非静态内部类的子类,则尤其要注意上面的规则:非静态内部类的构造器必须通过其外部类对象来调用。

 


当创建一个子类时,子类构造器总会调用父类的构造器,因此在创建非静态内部类的子类时,必须保证让子类构造器可以调用非静态内部类的构造器,调用非静态内部类的构造器时,必须存在一个外部类对象。

下面程序定义了一个子类继承了 Out 类的非静态内部类 In类。

1
2
3
4
5
6
7
8
9
10
11
public class SubClass extends Out.In
{
    //显示定义SubClass的构造器
     
    public SubClass(Out out)
    {
        //通过传入的Out对象显式调用In的构造器
         
        out.super("hello");
    }
}

  

 

 

 

 

 

 

 

 在外部类以外使用静态内部类

 

因为静态内部类是外部类类相关的,因此创建静态内部类对象时,无需创建外部类对象。

 

在外部类以外的地方创建静态内部类的语法如下:new OuterClass.InnerConstructer();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class StaticOut
{
    // 定义一个静态内部类,不使用访问控制符,
    // 即同一个包中其他类可访问该内部类
     
    static class StaticIn
    {
        public StaticIn()
        {
            System.out.println("静态内部类的构造器");
        }
    }
}
public class CreateStaticInnerInstance
{
    public static void main(String[] args)
    {
        StaticOut.StaticIn in = new StaticOut.StaticIn();
         
        /*
        上面代码可改为如下两行代码:
        使用OuterClass.InnerClass的形式定义内部类变量
         
        StaticOut.StaticIn in;
         
        通过new来调用内部类构造器创建静态内部类实例
        in = new StaticOut.StaticIn();
        */
    }
}

  

 

 

 

 

 

 

 

 

 

 

 

 

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

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

 

 

 

6.7.4 局部内部类


如果把一个内部类放在方法里定义,则这个内部类就是一个局部内部类,局部内部类仅在该方法里有效。

 

由于局部内部类不能在外部类的方法以外的地方使用,因此局部内部类也不能使用访问控制符和static修饰符修饰。

 

 

 

 

 

 

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

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

 

 

 

 

6.7.5 匿名内部类


匿名内部类适合创建那种只需要一次使用的类,定义匿名内部类的格式如下:

 

 

 

匿名内部类必须继承一个父类,或者实现一个接口,但是最多只能继承一个父类或者实现一个接口。

 

关于匿名内部类还有如下两条规则:

➢ 匿名内部类不能是抽象类,因为系统在创建匿名内部类时,会立即创建匿名内部类的对象。因此不允许将匿名内部类定义成抽象类。

➢ 匿名内部类不能定义构造器。由于匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义初始化块,可以通过实例初始化块来完成构造器需要完成的事情。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
interface Product
{
    double getPrice();
    String getName();
}
public class AnonymousTest
{
    public void test(Product p)
    {
        System.out.println("购买了一个" + p.getName()
            + ",花掉了" + p.getPrice());
    }
    public static void main(String[] args)
    {
        var ta = new AnonymousTest();
         
        // 调用test()方法时,需要传入一个Product参数,
        // 此处传入其匿名实现类的实例
         
        ta.test(new Product()
        {
            public double getPrice()
            {
                return 567.8;
            }
            public String getName()
            {
                return "AGP显卡";
            }
        });
    }
}

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
interface Product
{
    double getPrice();
    String getName();
}
 
public class AnonymousTest
{
    public void test(Product p)
    {
        System.out.println(p.getName() + "      " + p.getPrice());
    }
    public static void main(String[] args)
    {
        AnonymousTest ta = new AnonymousTest();
 
        ta.test(new Product()
        {
            public double getPrice()
            {
                return 567.8;
            }
            public String getName()
            {
                return "AGP";
            }
        });
    }
}

 

 

 

 

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

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

 

匿名类继承一个父类

 

以下实例中,创建了 Polygon 类,该类只有一个方法 display(),AnonymousDemo 类继承了 Polygon 类并重写了 Polygon 类的 display() 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Polygon {
   public void display() {
      System.out.println("在 Polygon 类内部");
   }
}
 
class AnonymousDemo {
   public void createClass() {
 
      // 创建的匿名类继承了 Polygon 类
      Polygon p1 = new Polygon() {
         public void display() {
            System.out.println("在匿名类内部。");
         }
      };
      p1.display();
   }
}
 
class Main {
   public static void main(String[] args) {
       AnonymousDemo an = new AnonymousDemo();
       an.createClass();
   }
}

  

 

执行以上代码,匿名类的对象 p1 会被创建,该对象会调用匿名类的 display() 方法,输出结果为:

在匿名类内部。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Polygon
{
    public void display()
    {
        System.out.println("111111111111111111111111");
    }
}
 
class AnonymousDemo
{
    public void createClass()
    {
 
        Polygon p1 = new Polygon()
        {
            public void display()
            {
                System.out.println("222222222222222222");
            }
        };
        p1.display();
    }
}
 
class Main
{
    public static void main(String[] args)
    {
        AnonymousDemo an = new AnonymousDemo();
        an.createClass();
    }
}

  

 

 

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

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

 

匿名类实现一个接口

以下实例创建的匿名类实现了 Polygon 接口:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
interface Polygon {
   public void display();
}
 
class AnonymousDemo {
   public void createClass() {
 
      // 匿名类实现一个接口
      Polygon p1 = new Polygon() {
         public void display() {
            System.out.println("在匿名类内部。");
         }
      };
      p1.display();
   }
}
 
class Main {
   public static void main(String[] args) {
      AnonymousDemo an = new AnonymousDemo();
      an.createClass();
   }
}

  

输出结果为:

在匿名类内部。

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
interface Polygon
{
    public void display();
}
 
class AnonymousDemo
{
    public void createClass()
    {
        Polygon p1 = new Polygon()
        {
            public void display()
            {
                System.out.println("66666666666666666666666");
            }
        };
        p1.display();
    }
}
 
class Main
{
    public static void main(String[] args)
    {
        AnonymousDemo an = new AnonymousDemo();
        an.createClass();
    }
}

  

 

 

 

 

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

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

 

 

复制代码
abstract class Device
{
    private String name;
    public abstract double getPrice();
    public Device(){}
    public Device(String name)
    {
        this.name = name;
    }
    
    // 此处省略了name的setter和getter方法
    public void setName(String name)
    {
        this.name = name;
    }
    public String getName()
    {
        return this.name;
    }
}
public class AnonymousInner
{
    public void test(Device d)
    {
        System.out.println("购买了一个" + d.getName() + ",花掉了" + d.getPrice());
    }
    public static void main(String[] args)
    {
        var ai = new AnonymousInner();
        
        // 调用有参数的构造器创建Device匿名实现类的对象
        ai.test(new Device("电子示波器")
        {
            public double getPrice()
            {
                return 67.8;
            }
        });
        
        
        // 调用无参数的构造器创建Device匿名实现类的对象
        var d = new Device()
        {
            // 初始化块
            {
                System.out.println("匿名内部类的初始化块...");
            }
            
            // 实现抽象方法
            public double getPrice()
            {
                return 56.2;
            }
            
            // 重写父类的实例方法
            public String getName()
            {
                return "键盘";
            }
        };
        
        ai.test(d);
    }
}
复制代码

 

 

 

 

 

 

 

 

 

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

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

 

 

 

 

 

接下来便开始说正题吧,匿名内部类,通过名字,想必大家就知道什么是匿名内部类了吧,


1、定义:就是没有名字的内部类(内部类之前介绍过了哦)。


2、使用内部类有什么好处呢,一句话就概括了:简化书写,至于是怎么简化的,哪里简化了等下再说。


3、先说一下什么时候使用匿名内部类,即使用前提和条件:

 

       必须存在继承和实现关系的时候才可以使用,其实这也很好理解,首先,匿名内部类没有名字,那该如何描述以及new个对象呢?

 

       对,没错,要通过继承它的父类或者实现一个接口来达成这一目的。

 

下面举个例子:

 

 

 

 输出结果:

 

 

 

 

看到这几行代码,应该就不用我来解释为什么说匿名内部类可以简化书写了吧。

 

如何调用匿名内部类中的方法这个应该也是大家好奇的吧,毕竟匿名内部类没有类名该如何调用方法就成为了一个问题。

 

1、匿名内部类中只有一个方法的情况

 

 

 

 

2、匿名内部类有一个方法调用起来很容易,那如果有多个方法呢,大家不会想这样吧?

 

 

 

输出结果试一下:

 

 

 

那么该如何调用匿名内部类中的多方法呢?
Endeavor有两种方法,如果大家还有更好的方法多多赐教哦!
1、利用多态的思想(匿名内部类的前提是存在继承或实现关系的)

 

 

输出结果:

 

 

 

 

2、改变方法类型,返回this

 

 

输出结果:

 

 

 

 


不知道看完之后大家有没有什么疑问,如果想调用匿名内部类自己特有的方法的时候呢?该如何调用呢?

 

 

输出结果:

 

 

 

显然是不行的,所以Endeavor觉得内名内部类可以有自己特有的方法,但是前提条件是这个匿名内部类只有这一个方法。

 

如果有多个方法的时候,他只能继承父类的方法以及重写这个方法或实现接口,绝不可能在在多个方法的情况下,调用自身特有的方法,但是这个特有的方法可以存在,但无法调用,不知道大家认同与否。

举例:

 

 

 

输出结果:

 

 

 


补充三点:


1、匿名内部类 :匿名内部类只是没有类名,其他的一概成员都是具备的。


2、之前说过匿名内部类存在的前提是要有继承或者实现关系的,但是并没有看到extends和implements关键字,这是怎么回事呢?


   答:很简单,匿名内部类没有连类名都没有,使用关键字就更无从说起了。这些由jvm搞定了。


2、匿名内部类是实现接口

 

 


3、接下来和大家分享一下匿名内部类中使用最普遍的一种情况,即以实参的形式使用

 

 

输出结果:

 

 

 

 

 

 

 

 

 

 

 

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

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

 

 

java匿名内部类:

1:匿名内部类,匿名内部类也就是没有名字的内部类。

2:匿名内部类的作用

正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写。

3:匿名内部类的实现

匿名内部类的两种实现方式:第一种,继承一个类,重写其方法;第二种,实现一个接口(可以是多个),实现其方法。

4:匿名内部类的创建

匿名类是不能有名称的类,所以没办法引用它们。必须在创建时,作为new语句的一部分来声明它们。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.mianshi.test;
/**
 * 类名称:AnonymousInnerClassTest
 * 描述: 匿名内部类测试
 * 创建人:王秋林
 * 创建时间:2017-2-12
 */
public class AnonymousInnerClassTest {
  public static void main(String args[]){  
    AnonymousInnerClassTest test = new AnonymousInnerClassTest();  
    test.show();  
  }  
  //在这个方法中构造了一个匿名内部类  
  private void show(){  
    Out anonyInter = new Out(){//获取匿名内部类实例  
      void show(){//重写父类的方法  
        System.out.println("this is Anonymous InnerClass showing.");
      }  
    };  
    anonyInter.show();//调用其方法  
  }
}
//这是一个已经存在的类,匿名内部类通过重写其方法,将会获得另外的实现  
class Out{  
  void show(){  
    System.out.println("this is Out showing.");  
  }  
}

5:匿名内部类的基本实现

(1)抽象方法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
abstract class Person {
  public abstract void eat();
}
public class Demo {
  public static void main(String[] args) {
    Person p = new Person() {
      public void eat() {
        System.out.println("eat something");
      }
    };
    p.eat();
  }
}

运行结果:eat something

(2)接口实现

1
2
3
4
5
6
7
8
9
10
11
12
13
interface Person {
  public void eat();
}
public class Demo {
  public static void main(String[] args) {
    Person p = new Person() {
      public void eat() {
        System.out.println("eat something");
      }
    };
    p.eat();
  }
}

运行结果:eat something

由上面的例子可以看出,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现。最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口

(3)Thread类的匿名内部类实现

1
2
3
4
5
6
7
8
9
10
11
12
public class Demo {
  public static void main(String[] args) {
    Thread t = new Thread() {
      public void run() {
        for (int i = 1; i <= 5; i++) {
          System.out.print(i + " ");
        }
      }
    };
    t.start();
  }
}

运行结果:1 2 3 4 5

(4)Runnable接口的匿名内部类实现

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Demo {
  public static void main(String[] args) {
    Runnable r = new Runnable() {
      public void run() {
        for (int i = 1; i <= 5; i++) {
          System.out.print(i + " ");
        }
      }
    };
    Thread t = new Thread(r);
    t.start();
  }
}

运行结果:1 2 3 4 5

二、匿名内部类的注意事项

(1)匿名内部类不能有构造方法。

(2)匿名内部类不能定义任何静态成员、方法和类。

(3)匿名内部类不能是public,protected,private,static。

(4)只能创建匿名内部类的一个实例。

(5)一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。

(6)因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。

(7)匿名类和内部类中的中的this:有时候,我们会用到一些内部类和匿名类。当在匿名类中用this时,这个this则指的是匿名类或内部类本身。这时如果我们要使用外部类的方法和变量的话,则应该加上外部类的类名。

 

posted @   小白龙白龙马  阅读(46)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示