Java程序设计—面向对象_内部类和枚举

Posted on 2018-01-28 12:36  Jonathan_C  阅读(176)  评论(0)    收藏  举报
  • 内部类:类的内部定义的类。
  1. 为什么使用内部类:
    • 增强封装,防止其他类访问这个类
    • 内部类可以提高代码的可维护性。
    • 内部类可以直接访问外部类的成员(字段)

  2. 内部类可以分为四种:

    • 实例内部类:没有使用static修饰,必须通过实例调用
    • 静态内部类:用static修饰
    • 局部内部类:在方法中定义的内部类
    • 匿名内部类:属于局部内部类的特殊情况

    内部类相当于外部类的一个成员,所以可以用public, static,protected,private修饰

    一般外部类是用public或者缺省修饰

  • 实例内部类
  1. 特点:编译器会产生内部类的字节码文件;内部类可以访问外部类成员(通过内部类的方法);外部类只能通过内部类的实例来访问内部类的成员;实例内部类,不能定义静态成员(因为实例内部类没有static修饰);如果内外部类具有同名字段(方法),则按照就近原则访问,或者通过this关键字指定访问
 1 class Outer{
 2     String name="outter";
 3     int i=100;
 4     public int getInner() {
 5         return new Inner().i;//通过new一个内部类实例来调用内部类的字段i 
 6     }
 7     
 8     class Inner{//没有static修饰,实例内部类
 9         public String getName() {//通过内部类方法访问外部类的name
10             return name;
11         }
12         int i=10;
13         String name="inner";
14         public int getI() {
15             int i=1;
16             return i;
17         }
18     }
19 }
20 
21 public class J7_Interior_Class {
22     public static void main(String[] args) {
23         //创建内部类对象
24         Outer o=new Outer();//先创建内部类对象
25         Outer.Inner i=o.new Inner();//再通过外部类对象,创建内部类对象
26         System.out.println(i);
27         System.out.println(i.getName());//通过内部类的方法访问外部类的成员。
28         //外部类访问内部类
29         System.out.println(o.getInner());//10
30         //重名的字段调用结果
31         System.out.println(i.getI());//1 就近原则访问。若要访问inner的i,则return this.i,
32         //若访问外部的i,return outer.this.i
33 
34         
35     }
36 }
  • 静态内部类
  1. 特点:在创建内部类时候,不必通过创建外部类对象来创建内部类;静态内部类可以直接访问外部的静态成员(通过静态内部类的方法),若要访问非静态的成员,需要先创建对象再访问。
 1 class Outer_2{
 2     String name="non-static name";
 3     static String name2="Outer_2";
 4     static class Inner{
 5         static int i=9;
 6         public String getName2() {
 7             return name2;
 8         }
 9         public String getName() {
10             return new Outer_2().name;
11         }
12     }
13 }
14 //main...
15         //static inner class
16         System.out.println(new Outer_2.Inner().i);
17         //创建内部类对象
18         Outer_2.Inner inn=new Outer_2.Inner();
19         System.out.println(inn.getName2());//outer_2,静态内部类可以访问外部类的静态对象
20         System.out.println(new Outer_2.Inner().getName());//non-static name 非静态外部类成员,需要先创建对象再访问
  • 局部内部类
  1. 不能使用private,public,static, protected修饰
  2. 只能在当前方法中使用
  3. 不包含静态成员
  4. 可访问外部类所有成员
  5. 局部内部类访问的局部变量用final修饰
 1 public class J7_Interior_Class_2 {
 2     static String name="xxx";//外部类的字段
 3     public static void main(String[] args) {
 4         final int age=10;//局部变量,用final修饰
 5         class localClass{//局部类
 6             String info="YYY";
 7             public void test() {
 8                 System.out.println(name);//可直接访问外部类的字段
 9                 System.out.println(age);//可直接访问方法内的变量
10                 System.out.println(info);//可访问自身的字段 
11             }
12         }
13         new localClass().test();
14         
15     }
16 }

  当test()方法在栈桢中被销毁后,堆中还存在着localClass的对象,其引用依然指向栈桢。所以用final修饰age,使其变成常量,就不会被销毁了。引用仍然有效。

  • 匿名内部类
  1. 没有名称的局部内部类,适合只使用一次的类
  2. 没有自身的构造器,调用父类构造器或者接口。接口形式用的比较多。只能继承一个父类或一个接口。
 1 class OuterClass {
 2     String name="AAA";
 3     public String getName() {
 4         return name;
 5     }
 6 }
 7 public class J7_Interior_Class_3 {
 8     public static void main(String[] args) {
 9         System.out.println(new OuterClass() {
10             //匿名内部类体
11         });
12     }
13 }
  • 枚举
  1. 枚举的直接父类是java.lang.Enum,但是不能显示继承Enum
  2. 枚举就相当于一个类,可以定义普通方法,成员变量,构造方法,抽象方法。
  3. 枚举类的数量是固定的,实例个数有限,不能用new来创建实例。
  4. 枚举中都是全局公共的静态变量,可以直接使用枚举类名来调用
1 Weekdays day=Weekdays.Friday
  1. 枚举对象可以使用父类Enum的方法
        String someday=Weekdays.MONDAY.name();
        int ordinal=Weekdays.TUESDAY.ordinal();
        System.out.println(ordinal);
  1. switch只支持int和枚举类型,之所以支持枚举类型,是因为枚举底层使用的是ordinal的类型为int
  2. 建议用枚举做单例设计模式
 1 enum Weekdays{//在底层,这里相当于class Weekdays extends Enum
 2     MONDAY,TUESDAY,WENEDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY;
 3 }
 4 enum ArrUtil{
 5     INSTANCE;
 6     public void sort(int[] arr) {
 7         System.out.println("SORT");
 8     }
 9 }
10 class Employee{
11     private Weekdays restday;
12     public Weekdays getRestday() {
13         return this.restday;
14     }
15     public void setRestday(Weekdays ele) {
16         this.restday=ele;
17     }
18 }
19 
20 public class J8_Enumerate {
21     public static void main(String[] args) {
22         Employee e=new Employee();
23         e.setRestday(Weekdays.FRIDAY);
24         Weekdays restday=e.getRestday();
25         System.out.println(restday);
26         if(restday==Weekdays.FRIDAY||restday==Weekdays.SATURDAY) {
27             System.out.println("Weekend Rest");
28         }
29         else {
30             System.out.println("Business Day");
31         }
32         //枚举对象可调用Enum中的方法
33         String someday=Weekdays.MONDAY.name();
34         int ordinal=Weekdays.TUESDAY.ordinal();
35         System.out.println(ordinal);
36         
37         Weekdays[] ws=Weekdays.values();
38         for(Weekdays i:ws) {
39             System.out.println(i);//返回数组中所有的常量
40         }
41         //把字符串转换成枚举类中的同名常量
42         Weekdays day=Weekdays.valueOf("MONDAY");
43         System.out.println(day);
44         //单例设计模式
45         ArrUtil.INSTANCE.sort(null);
46     }
47 }