Java学习(十六)成员内部类,静态内部类,匿名内部类,局部内部类

Posted 泊而至远

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java学习(十六)成员内部类,静态内部类,匿名内部类,局部内部类相关的知识,希望对你有一定的参考价值。

定义:将一个类定义在另一个类的内部。内部的类称为内部类;

public class Outer{

           class inner{

         //省略

}

}

 

特点

①   内部类可以很好的实现隐藏,可以使用protected,private修饰符;

②   内部类可以直接访问外部类的所有成员,包括私有成员;

③   外部类不能直接访问内部类的成员,必须首先要建立内部类的对象才能访问;

④   内部类可以解决一些问题,比如间接的去实现多继承。可以避免修改接口而实现同一个类中两种同名方法的调用;

 

成员内部类及应用

成员内部类特点

①   成员内部类属于外部类的实例成员,成员内部类都可以有public,private,default,protected权限修饰符。在成员内部类中访问外部类的成员方法和属性,要使用“外部类名.this.成员方法”和“外部类名.this.成员属性”的形式;

②   创建成员内部类的实例使用“外部类名.内部类名.实例名=外部类实例名. new 内部类构造方法(参数)”的形式;

成员内部类有以下限制

①   成员内部类不能与外部类重名;

②   不能在成员内部类中定义static属性、方法和类(static,final形式的常量定义除外)。因为一个成员内部类实例必然与一个外部类实例关联,static成员完全可移到其外部类中去;

技术分享
 1 public class MemberInnerClass{
 2     public static void main(String []args){
 3         //创建外部类对象
 4         Outer1 outer=new Outer1();
 5         //创建内部类对象
 6         Outer1.Inner1 inner=outer.new Inner1();
 7         inner.innerShow();
 8         
 9         System.out.println("--------------外部类访问内部类对象--------------");
10         outer.outerShow();
11     }
12 }
13 
14 class Outer1{
15     private String name="张三";
16     private int num1=10;
17     public void outerShow(){
18         System.out.println(name);
19         System.out.println(num1);
20         //System.out.println(num2);//外部类不能直接访问内部类的成员
21         
22         //外部类访问内部类对象
23         Inner1 inner =new Inner1();
24         inner.innerShow();
25     }
26     
27     //当内部类改成私有时private,仅能在外部类中访问
28     public class Inner1{
29         private String name="李四";
30         private int num2=20;
31         private static final int num3=30;//静态常量在内部类中是可以使用的
32         //private static int num3=30;//在成员内部类中不能声明静态成员和静态方法
33         public void innerShow(){
34             System.out.println(name);
35             System.out.println(num2);
36             
37             //成员内部类可以直接访问外部类的属性和方法,包括私有的
38             System.out.println("--------------");
39             //外部类访问内部类时注释outerShow(),避免死循环
40             //outerShow();
41             
42             //打印外部类中成员属性
43             System.out.println("--------------打印外部类中成员属性--------------");
44             System.out.println(Outer1.this.name);
45             System.out.println(Outer1.this.num1);
46         }
47     }
48 }
View Code

用内部类间接实现多继承

技术分享
 1 public class MultiExtendsDemo{
 2     public static void main(String []args){
 3         C c=new C();
 4         //间接实现多继承
 5         c.showA();
 6         c.showB();
 7     }
 8 }
 9 
10 class A{
11     public void showA(){
12         System.out.println("A");
13     }
14 }
15 
16 class B{
17     public void showB(){
18         System.out.println("B");
19     }
20 }
21 
22 class C{
23     private class A1 extends A{
24         public void showA(){
25             super.showA();
26         }
27     }
28     
29     private class B1 extends B{
30         public void showB(){
31             super.showB();
32         }
33     }
34     
35     public void showA(){
36         new A1().showA();
37     }
38     
39     public void showB(){
40         new B1().showB();
41     }
42 }
View Code

父类中和接口中的方法名相同

为了不更改其方法且要实现这个2个方法

采用内部类的方式来实现

技术分享
 1 public class Demo2{
 2     public static void main(String []args){
 3         Son son=new Son();
 4         son.show();
 5         son.show2();
 6     }
 7 }
 8 
 9 abstract class Parent{
10     public abstract void show();
11 }
12 
13 interface IShow{
14     public abstract void show();
15 }
16 
17 /*class Son extends Parent implements IShow{
18     public void show(){
19         
20     }
21     public void show1(){
22         
23     }
24 }*/
25 
26 //因为父类中和接口中的方法名相同
27 //为了不更改其方法且要实现这个2个方法
28 //采用内部类的方式来实现
29 //但最好的方式还是改方法
30 class Son extends Parent{
31     public void show(){
32         System.out.println("抽象类中的show方法");
33     }
34     
35     private class Inner2 implements IShow{
36         public void show(){
37             System.out.println("接口中的show方法");
38         }
39     }
40     
41     public void show2(){
42         Inner2 inner=new Inner2();
43         inner.show();
44     }
45 }
View Code

 

静态内部类及其应用

静态内部类特点

①   使用static修饰的成员内部类叫静态内部类;

②   静态内部类跟外部类没有任何关系,只是在生成类名和类定义时有影响。静态内部类可以看作是与外部类平级的类。使用方式与外部类平级的类完全相同;

③   创建静态内部类的实例使用  外部类名.内部类名. 实例名=new 外部类名.内部类名(参数);

静态内部类有以下限制

①   静态内部类的名字不能与外部相同;

②   静态内部类不能访问外部类的非静态的属性和方法,外部类不能访问内部类的非静态的属性和方法;

技术分享
 1 public class StaticInnerClass{
 2     public static void main(String []args){
 3         Outer2.Inner2 inner=new Outer2.Inner2();//构造一个静态内部类对象
 4         inner.innerShow();
 5         
 6         Outer2 outer=new Outer2();
 7         outer.outerShow();
 8     }
 9 }
10 
11 class Outer2{
12     private String name="张三";
13     private int num1=10;
14     private static int num3=100;
15     public void outerShow(){
16         System.out.println(name);
17         System.out.println(num1);
18         
19         //System.out.println(Inner2.name);
20         Inner2 inner =new Inner2();
21         System.out.println(inner.name);//访问非静态
22         
23         System.out.println(Inner2.num3);//访问静态
24     }
25     
26     public static class Inner2{
27         private String name="李四";
28         private int num2=20;
29         private static final int num3=30;
30         
31         public void innerShow(){
32             System.out.println(name);
33             System.out.println(num2);
34             
35             //System.out.println(Outer2.this.name);//静态内部类不能访问外部类的非静态成员
36             System.out.println(Outer2.num3);
37             System.out.println(num2);
38         }
39     }
40 }
View Code

 

匿名内部类及应用

匿名内部类特点

①   匿名内部类时没有名称的内部类,没办法引用它们。必须在创建时,作为new语句的一部分来声明并创建它们的实例;

②   匿名内部类必须继承一个类(抽象的,非抽象的都可以)或者实现一个接口。如果父类(或父接口)是抽象类,则匿名内部类必须实现其所有抽象方法;

③   匿名内部类中可以定义代码块,用于实例的初始化,但是不能定义静态代码块;

匿名内部类的语法:new interface/superclass(){//类体}

这种形式的new语句声明一个新的匿名类,它对一个给定的类进行扩展,或者实现一个给定的接口,并同时创建该匿名类的一个新实例;

不使用匿名内部类时

技术分享
 1 public class AnonymousInnerClass{
 2     public static void main(String []args){
 3         Person person=new Person();
 4         Animal dog=new Dog();
 5         person.feed(dog);
 6     }
 7 }
 8 
 9 abstract class Animal{
10     public abstract void eat();
11 }
12 
13 class Person{
14     public void feed(Animal animal){
15         animal.eat();
16     }
17 }
18 
19 class Dog extends Animal{
20     public void eat(){
21         System.out.println("啃骨头");
22     }
23 }
View Code

使用匿名内部类

技术分享
 1 public class AnonymousInnerClass{
 2     public static void main(String []args){
 3         Person person=new Person();
 4         //Animal dog=new Dog();
 5         //person.feed(dog);
 6         
 7         /*Animal dog=*/new IAnimal(){
 8             private String name="aa";
 9             
10             //代码块
11             {
12                 name="哈哈";
13             }
14             
15             //不能使用静态代码块
16             //static{}
17             public void eat(){
18                 System.out.println("啃骨头");
19             }
20             public void show(){
21                 System.out.println(name);
22             }
23         }.show();//调用内部的show();
24         
25         //person.feed(dog);
26         //dog.show();//这里不能调用定义的show();
27         //person.feed(dog);
28         person.feed(new IAnimal(){
29             public void eat(){
30                 System.out.println("吃鱼");
31             }
32         });
33     }
34 }
35 
36 //抽象类
37 //使用接口时先注释
38 //并修改Person类中的Animal为IAnimal
39 /*abstract class Animal{
40     public abstract void eat();
41 }*/
42 
43 //接口
44 interface IAnimal{
45     public abstract void eat();
46 }
47 
48 class Person{
49     public void feed(IAnimal animal){
50         animal.eat();
51     }
52 }
53 
54 /*class Dog extends Animal{
55     public void eat(){
56         System.out.println("啃骨头");
57     }
58 }*/
View Code

局部内部类及应用

局部内部类的特点

①   定义在代码块、方法体内的类叫局部内部类;

②   局部内部类访问外部类的属性和方法使用“外部类名.this.属性名”和“外部类名.this.方法名(参数)”的形式;

③   对外部世界完全隐藏,只能在其作用域内生成对象;

 

局部内部类有以下限制

①   局部内部类不能加访问修饰符,因为它们不能类成员;

②   成员内部类不能与外部类重名;

③   局部内部类访问作用域内的局部变量,该局部变量需要使用final修饰;

技术分享
 1 public class LocalInnerClass{
 2     public static void main(String []args){
 3         Outer3 outer=new Outer3();
 4         outer.showOuter();
 5     }
 6 }
 7 
 8 class Outer3{
 9     private String name="张三";
10     private int num1=10;
11     private static int num2=20;
12     public void showOuter(){
13         /*final*/ int num4=50;//这里加不加final都可以被内部类访问?希望看到的且知道的帮我解答下
14         //局部内部类不能加访问修饰符
15         class Inner3{
16             private int num3=30;
17             private int num1=20;
18             public void showInner(){
19                 System.out.println(num3);
20                 System.out.println(num1);
21                 
22                 System.out.println(Outer3.this.num1);
23                 System.out.println(Outer3.num2);
24                 
25                 System.out.println(num4);
26             }
27         }
28         Inner3 inner=new Inner3();
29         inner.showInner();
30     }
31 }
View Code

 

以上是关于Java学习(十六)成员内部类,静态内部类,匿名内部类,局部内部类的主要内容,如果未能解决你的问题,请参考以下文章

Java语言中四种内部类(成员内部类,局部内部类,静态内部类,匿名内部类)在实际使用中有啥好处?

Java——基础知识——内部类

JavaSE基础(十 三 )---<内部类>成员内部类,静态内部类,局部内部类,匿名内部类,内部类的意义

java-07 内部类匿名内部类局部内部类lambda

内部类

内部类和匿名内部类的用法