- 内部类:类的内部定义的类。
- 为什么使用内部类:
-
- 增强封装,防止其他类访问这个类
- 内部类可以提高代码的可维护性。
- 内部类可以直接访问外部类的成员(字段)
2. 内部类可以分为四种:
-
- 实例内部类:没有使用static修饰,必须通过实例调用
- 静态内部类:用static修饰
- 局部内部类:在方法中定义的内部类
- 匿名内部类:属于局部内部类的特殊情况
内部类相当于外部类的一个成员,所以可以用public, static,protected,private修饰
一般外部类是用public或者缺省修饰
- 实例内部类
- 特点:编译器会产生内部类的字节码文件;内部类可以访问外部类成员(通过内部类的方法);外部类只能通过内部类的实例来访问内部类的成员;实例内部类,不能定义静态成员(因为实例内部类没有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 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 非静态外部类成员,需要先创建对象再访问
- 局部内部类
- 不能使用private,public,static, protected修饰
- 只能在当前方法中使用
- 不包含静态成员
- 可访问外部类所有成员
- 局部内部类访问的局部变量用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 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 }
- 枚举
- 枚举的直接父类是java.lang.Enum,但是不能显示继承Enum
- 枚举就相当于一个类,可以定义普通方法,成员变量,构造方法,抽象方法。
- 枚举类的数量是固定的,实例个数有限,不能用new来创建实例。
- 枚举中都是全局公共的静态变量,可以直接使用枚举类名来调用
1 Weekdays day=Weekdays.Friday
- 枚举对象可以使用父类Enum的方法
String someday=Weekdays.MONDAY.name(); int ordinal=Weekdays.TUESDAY.ordinal(); System.out.println(ordinal);
- switch只支持int和枚举类型,之所以支持枚举类型,是因为枚举底层使用的是ordinal的类型为int
- 建议用枚举做单例设计模式
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 }
浙公网安备 33010602011771号