一、内部类:
什么是内部类:
内部类就是: 在一个类的里边包含一个类, 被包含的类就叫做内部类(外边的类叫做外部类)
为什么要用内部类:
一个类只给另一个类调用,其他类不调用。 则可以将此类作为内部类写到调用它的类里边。
其他: 用内部类实现多继承(目前不用研究), 用内部类实现回调(目前不用研究)。
二、内部类分类:
- 成员内部类: 一个类体中(方法外边)书写的内部类,叫做成员内部类。
- 静态内部类:比成员内部类多一个static修饰符。
- 局部内部类:在方法内写的内部类。
- 匿名内部类:没有类名,通过实现一个接口,或继承一个父类来编写。(通常也写在方法内)
三、成员内部类:
一个外部类的类体中(方法外边)书写的内部类,叫做成员内部类。
1.成员内部类可以访问外部类的成员变量贺成员方法
2.外部类访问成员内部类的成员变量贺成员方法需要先创建成员内部类的对象(通过员内部类的对象访问)。
3.成员内部类创建对象: 需要先创建外部类对象, 再通过 "外部类对象.new 内部类名()" 的方式创建员内部类创建对象。
比如下边结构:
class OuterClass{ class InnerClass{ } }
案例:
package day0617; public class Stu { String stuName="刘凯"; class Book{ String name="java程序设计"; //setName: 将参数String n赋值给name public void setName(String n){ name=n;//将参数String n赋值给name } public void printStu(){ System.out.println(stuName);//内部类可以直接用外部成员语变量。打印外部类stuName } } } package day0617; public class TestStu { public static void main(String[] args) { //1.使用成员内部类(创建成员内部类对象) Stu s=new Stu();//1.外部类Stu对象 Stu.Book javaB=s.new Book();//2. System.out.println(javaB.name);//2.打印内部类成员变量name javaB.setName("java程序设计");//3.调用setName方法 javaB.printStu();//4.调用printStu方法 } }
解释:
1.成员内部类可以访问外部类的成员变量和成员方法
2.外部类访问成员内部类的成员变量和成员方法需要先创建成员内部类的对象(通过员内部类的对象访问)。
3.成员内部类创建对象: 需要先创建外部类对象, 再通过 "外部类对象.new 内部类名()" 的方式创建员内部类创建对象。
如下案例
四、静态内部类:
1.一个外部类的类体中(方法外边)书写的static修饰的内部类,叫做静态内部类。 (和成员内部类结构相比多了一个static修饰词)
2.静态内部类不依赖于外部类的实例,可以直接通过外部类名访问静态成员变量和静态成员方法(实例成员变量和实例方法还得创建静态内部类对象)。
3.静态内部类创建对象不需要依赖外部类对象(不需要创建外部类对象), 但是new后边得写外部类对象名。
4.静态内部类可以访问外部类的静态成员和方法,但不能访问外部类的非静态成员和方法。
解释:
注意: 可以将静态内部类理解成一个独立的类(和它对应的外部类是平级关系<不用理解成一个包含一个>, 只是书写位置被包含在外部类里边,逻辑上可以理解成没被包含)
五、匿名内部类:
1.匿名内部类没有名字,所以叫做匿名内部类。
2.定义了一个匿名内部类的同时还用new关键字创建出了匿名内部类的对象。
书写格式:
父类名或接口名 变量名=new 父类名或接口名(){ 成员变量; 成员方法或实现接口中的方法; };
书写格式举例:
案例1:
package day0617;
public class Human { public void sayHello() { System.out.println("Hello!"); } public static void main(String[] args) { //1.定义匿名内部类(Human不是下边内部类的名字<此内部类没有名字,所以叫做匿名内部类>) //2.下边定义了一个匿名内部类,同时还用new关键字创建出了匿名内部类的对象。 Human hello = new Human() { public void sayHello() { System.out.println("Hello, world!"); } }; hello.sayHello(); } }
案例2:
package day0617; public class Human { public static void main(String[] args) { //1.定义匿名内部类(Human不是下边内部类的名字<此内部类没有名字,所以叫做匿名内部类>) //2.下边定义了一个匿名内部类,同时还用new关键字创建出了匿名内部类的对象。 Hello h = new Hello() { public void sayHello() { System.out.println("Hello, world!"); } }; h.sayHello(); } } interface Hello { void sayHello(); }
注意: 局部内部类课后自己找资料了解
六、枚举:
枚举类本质上也是一种java类,只不过是这个类的对象是有限的(只有固定的几个对象),用户不能随意创建对象。
比如表示一个类只能有固定的几个对象时可以用枚举类表示。
一个数据如果只有几个固定的数值,则可以用枚举类表示(和上一行一个意思)
jdk1.5之前的写法: 构造器私有化(为了不让在此类之外创建对象)、 在类中创建对象并用public static final修饰。 成员变量用private final修饰。
举例:
下边jdk1.5及之前的写法了解即可(看懂即可,以便更好的理解jdk1.5以后的写法)
package day0617; public class Season { private final String seasonName; private Season(String name) { this.seasonName = name; } public static final Season SPRING = new Season("春天"); public static final Season SUMMER = new Season("夏天"); public static final Season AUTUMN = new Season("秋天"); public static final Season WINTER = new Season("冬天"); public String toString() { return "Season{" + "seasonName='" + seasonName + '\'' + '}'; } }
package day0617; public class TestSeason { public static void main(String[] args){ Season spring = Season.SPRING; System.out.println(spring); } }
jdk1.5之后的用法:
书写要点:
- 枚举类的常量对象列表必须在枚举类的首行。 (因为是常量,所以建议大写) 默认会用public static final修饰。
- 枚举类的默认用private修饰
- 枚举类默认继承的是java.lang.Enum类,因此不能再继承其他的类型。
- JDK5.0 之后的switch结构,支持枚举类型,case后面可以写枚举常量名。
package day0617; public enum Season { SPRING ("春天"),SUMMER ("夏天"),AUTUMN ("秋天"),WINTER("冬天"); private final String seasonName; //可以省略private(因为java中枚举类的构造方法默认用private修饰) private Season(String name) { this.seasonName = name; } }
案例1:
package day0617; public enum Season {
//枚举类的常量对象列表必须在枚举类的首行。 (因为是常量,所以建议大写) SPRING ("春天"),SUMMER ("夏天"),AUTUMN ("秋天"),WINTER("冬天"); private final String seasonName; //可以省略private(因为java中枚举类的构造方法默认用private修饰) private Season(String name) { this.seasonName = name; } public String getSeasonName() { return seasonName; } }
package day0617; public class TestSeason { public static void main(String[] args){ Season season = Season.SPRING; System.out.println(season);//默认会调用toString()方法 System.out.println(season.toString());//toString()方法内默认会返回对象的名字SPRING switch (season){ case SPRING: System.out.println("春天");break; case SUMMER: System.out.println("夏天");break; case AUTUMN: System.out.println("秋天");break; case WINTER: System.out.println("冬天");break; } } }
案例2:
package day0617; //枚举类Gender public enum Gender { WOMAN, MAN; }
package day0617; public class TestG { public static void main(String[] args) { System.out.println(Gender.WOMAN); Gender gender=Gender.MAN; switch (gender){ case MAN: System.out.println("您是帅哥");break; case WOMAN: System.out.println("您是美女");break; } } }
案例3:
package day0617; public enum Week { MONDAY("星期一"), TUESDAY("星期二"), WEDNESDAY("星期三"), THURSDAY("星期四"), FRIDAY("星期五"), SATURDAY("星期六"), SUNDAY("星期日"); private final String description; private Week(String description){ this.description = description; } public String toString() { return super.toString() +":"+ description; } }
package day0617; public class TestWeek { public static void main(String[] args){ Week week = Week.SUNDAY; System.out.println(week);//默认会调用toString()方法 System.out.println(week.toString());//toString()方法内默认会返回对象的名字SPRING switch (week){ case MONDAY: System.out.println("怀念周末,困意很浓");break; case TUESDAY: System.out.println("进入学习状态");break; case WEDNESDAY: System.out.println("死撑");break; case THURSDAY: System.out.println("死撑2");break; case FRIDAY: System.out.println("开始盼周末,无心学习");break; case SATURDAY: System.out.println("一觉到下午1");break; case SUNDAY: System.out.println("一觉到下午2");break; } } }