学习了一定基础后,开始更加深入的学习面向对象,包含static,final两个关键字,面向对象编程三大特征之继承和多态。以及对于抽象类,内部类,接口,枚举,泛型的学习。
目录
1.static
(1)修饰成员变量
(2) 修饰成员变量的应用场景
(3)修饰成员方法
(4)修饰成员方法的应用场景
(5)注意事项
(6)应用知识
代码块
单例设计模式
2.继承
(1)介绍与入门
(2)注意事项
[1] 权限修饰符
[2] 单继承,Object类
[3] 方法重写
[4]子类访问其他成员的特点
[5] 子类构造器的特点
3.多态
(1)认识与入门
(2)使用好处
(3)多态下的类型转换问题
4.final
(1)认识与了解
(2)常量详解
5.抽象类
(1)认识与入门
(2)使用好处
(3)应用场景
6.接口
(1)概述
(2)综合案例
(3)接口的细节
7.内部类
(1)内部类概述
(2)成员内部类
(3)静态内部类
(4)局部内部类
(5)匿名内部类*
8.枚举
(1)介绍
(2)应用场景
9.泛型
(1)认识泛型
(2)泛型类
(3)泛型接口
(4)泛型方法,泛型通配符,上下限
(5)注意事项
1.static
静态,修饰成员变量,成员方法。
(1)修饰成员变量
成员变量按照有无static修饰,分为两种:
- 类变量:有static修饰,属于类,在计算机里只有一份,会被类的全部对象共享
- 实例变量(对象的变量):无static修饰,属于每个对象
package W.KN.d1_static;public class Student {//类变量static String name;//实例变量int age;
}
package W.KN.d1_static;public class Text {public static void main(String[] args) {//目标:掌握有无static修饰成员变量的用法,特点//1.类变量的用法//类名.类变量(推荐)Student.name = "郑大风";//对象.类变量(不推荐)Student s1 = new Student();s1.name = "陈清流";Student s2 = new Student();System.out.println(s1.name);System.out.println(Student.name);//实例变量的用法:属于每个对象s1.age = 45;s2.age = 123;System.out.println(s1.age);System.out.println(s2.age);}
}
成员变量执行原理:
类变量,与类一起加载一次,在堆内存中开辟一份空间(且只有一份),后续不论通过类或者对象访问修改的都是同一块空间。实例变量随对象的创建而创建,访问时还是通过对象的地址
(2) 修饰成员变量的应用场景
在开发中,如果某个数据只需要一份,且希望能够被共享(访问,修改),则该数据可以被定义为类变量使用。
案例
系统启动后,要求用户类可以记住自己创建了多少个用户对象
package W.KN.d1_static;public class User {//类变量:对外公开public static int number;public User(){//User.number++;//注意:在同一类中,访问自己类的类变量,可以省略类名不写number++;}}
package W.KN.d1_static;public class Text2 {public static void main(String[] args) {//目标:案例理解类变量的应用场景User u1 = new User();User u2 = new User();User u3 = new User();User u4 = new User();System.out.println(User.number);}
}
(3)修饰成员方法
成员方法按照有无static修饰,分为两种:
- 类方法:有static修饰,属于类(类和对象都可以访问)
- 实例方法:无static修饰,属于对象(只有对象可以访问)
package W.KN.d1_static;public class Student {public static void print(){System.out.println("HelloWorld");}//实例方法public void printfPass(double score){System.out.println("成绩"+(score >= 60 ? "及格":"不及格"));}}
package W.KN.d1_static;public class Text3 {public static void main(String[] args) {//目标:掌握有无static修饰方法的用法//类方法的用法//类名调用Student.print();Student s = new Student();s.print();s.printfPass(100);}
}
成员方法执行原理:
对象之所以可以调用类方法,是由于每个对象都会在堆内存中存储一份类的地址,可以通过地址去调用这些方法,至于类为什么不能调用成员方法,很简单,一是类中没有这些方法的地址,他们都在对象的空间中,二是一般这些方法都有涉及参数,类是无法访问的。
补充: main方法
(4)修饰成员方法的应用场景
类方法最常用的应用场景是做工具类(完成一些功能,给开发人员共同使用)
优点是调用方便,提高效率。工具类没有创建对象的需求,建议将工具类的构造器私有
案例:
对于实现验证码功能出现了重复,为避免浪费空间,在工具类中定义一个类方法实现
package W.KN.d1_static;import java.util.Random;public class MyUtil {public static String creatCoe(int n){//2.定义两个变量,一个用来存储最终产生的随机验证码 一个用来记住可能用到的全部字符String code = "";String data = "abccdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";Random r = new Random();//3.定义一个循环 产生每位随机字符for (int i = 0; i < n; i++) {int index = r.nextInt(data.length());code += data.charAt(index);}return code;}
}
(5)注意事项
- 类方法中可以直接访问类的成员,不可以直接访问实例对象
- 实例方法中既可以直接访问类成员,也可以直接访问实例成员
- 实例方法中可以出现this关键字,类方法中不可以出现this关键字
(6)应用知识
代码块
代码块是类的5大成分之一(成员变量,构造器,方法,代码块,内部块)
分类
静态代码块——格式:static{ }
特点:类加载时自动执行,类只加载一次,所以静态代码只执行一次
作用:完成类的初始化,比如对类的初始化赋值(成员复杂操作赋值)
实例代码块——格式:{ }
特点:每次创建对象时,执行实例代码块,并在构造器前执行
作用:同构造器,是用来完成对象的初始化的(实例变量进行初始化赋值)
package d3_tatic;public class Student {static int number = 80;static String name;//静态代码块static {System.out.println("静态代码块执行了...");name = "楠楠";}//实例代码块//用来执行一些构造器中的重复语句{System.out.println("实例代码块执行了。。。");}public Student(){System.out.println("无参数构造器执行了。。。");}public Student(String name){System.out.println("有参数构造器执行了。。。");}
}
package d3_tatic;public class Text {public static void main(String[] args) {//目标:认识两种代码块,了解他们的特点和基本作用System.out.println(Student.number);System.out.println(Student.number);System.out.println(Student.name);Student s1 =new Student();Student s2 =new Student("楠楠");}
}
单例设计模式
设计模式(Design pattern)
一种问题有n种解法,最优的解法被人总结出来,称之为设计模式
单例设计模式: 确保一个类只有一个对象 避免浪费内存
写法:
- 把类的构造器私有
- 定义一个类变量记住类的一个对象
- 定义一个类方法,返回对象
应用场景:
参照 Runtime 的写法 (返回当前编译环境)
实现方式:
- 饿汉式单例:拿对象时,对象早就创建好了
- 懒汉式单例:拿对象时,才开始创建对象
- .......
2.继承
(1)介绍与入门
java提供了一个关键字extends,使用可以让一个类和另一个类建立起父子关系。
继承的特点:子类能继承父类的非私有成员(成员变量,成员方法)
继承后的创建:子类的对象是由子类和父类共同完成的
package d5_extends;
//父类
public class A {public int i;public void print1(){System.out.println("==print1==");}private int j;private void print2(){System.out.println("==print2");}
}
package d5_extends;
//子类
public class B extends A{public void printf3(){System.out.println("==print3==");System.out.println(i);//子类可以世界使用父类公开的成员print1();//print2(); 父类私有的不可继承}
}
package d5_extends;public class Text {public static void main(String[] args) {//目标:认识继承,掌握继承的特点B b = new B();System.out.println(b.i);b.print1();b.printf3();}
}
继承的执行原理:
子类在方法区中读取时,会将自己的父类也读取一次。对于这个对象就是按照两个模式去创建的
继承的好处:
减少重复代码的编写
package d6_extends;public class People {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;} }package d6_extends;public class Teacher extends People{private String skill;public String getSkill() {return skill;}public void setSkill(String skill) {this.skill = skill;} } package d6_extends;public class Text {public static void main(String[] args) {//目标:清楚继承的好处Teacher t = new Teacher();t.setName("楠楠");t.setSkill("java");System.out.println(t);} }
(2)注意事项
[1] 权限修饰符
权限修饰符就是用来限制类中的成员(成员变量,成员方法,构造器,代码块...)能够访问的范围。
修饰符 | 在本类中 | 同一个包下的其他类里 | 任意包下的子类里 | 任意包的任意类里 |
private | √ | |||
省缺 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
private < 省缺 < protected < public
package d9_modifer;public class Fu {private void privateMethod(){System.out.println("private");}void Method(){System.out.println("省缺");}protected void protectedMethod(){System.out.println("protected");}public void publicMethod(){System.out.println("public");}public void text(){privateMethod();Method();protectedMethod();publicMethod();}
}
[2] 单继承,Object类
java是单继承的,类不支持多继承,但是支持多层继承,java中所有类都是继承于Object类。
[3] 方法重写
当子类觉得父类中某个方法不好用,或者无法满足自己的需求时,子类可以重写一个方法名称,参数列表一致的方法去覆盖父类的方法。重写后,java遵循就近原则访问方法。 (重写后,还想访问父类的方法或者变量,使用super.方法指定访问)
package d7_feature;public class A {public void print(){System.out.println("111");}public void printf(int a,int b){System.out.println("11122112");}
}package d7_feature;public class B extends A {//方法重写public void print(){System.out.println("222");}public void printf(int a,int b){System.out.println("22221313");}
}package d7_feature;public class Text {public static void main(String[] args) {B b = new B();b.print();b.printf(1,2);}
}
注意事项:
- 重写小技巧:使用Override注解,他可以指定java编译器,检查我们方法重写的格式是否正确,代码可读性会更好。(@Overrride)
- 子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限(public>protected>省缺)
- 重写的方法返回值类型,必须于被重写的方法返回类型一致,或者范围更小。
- 私有方法,静态方法不能被重写,如果重写会报错。
[4]子类访问其他成员的特点
子类方法中访问其他成员(成员变量,成员方法),是依照就近原则的。
[5] 子类构造器的特点
子类的全部构造器,都会先调用父类的构造器,再执行自己
package d10_constructor;class F{public F(){System.out.println("父类F的 无参数构造器 执行了");}
}class Z extends F{public Z(){super();//默认存在的System.out.println("子类Z的 无参数构造器 执行了");}public Z(String name){System.out.println("子类Z的 有参数构造器 执行了");}
}public class Text {public static void main(String[] args) {//目标:先认识子类构造器的特点,再掌握这个特点的常见应用场景Z z = new Z();Z z1 = new Z("楠楠");}
}
this(...)调用兄弟构造器(this() 和super()必须在构造器第一行)
package d10_constructor;class Student{private String name;private int age;private String school;public Student(String name,int age){this(name,age,"中北大学");}public Student() {}public Student(String name, int age, String school) {this.name = name;this.age = age;this.school = school;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getSchool() {return school;}public void setSchool(String school) {this.school = school;}
}public class Text {public static void main(String[] args) {//目标:先认识子类构造器的特点,再掌握这个特点的常见应用场景//学习this调用该类的其他构造器Student s2 = new Student("楠楠",19);System.out.println(s2.getName());System.out.println(s2.getAge());System.out.println(s2.getSchool());}
}
3.多态
(1)认识与入门
多态是在继承/实现情况下的一种现象,表现为:对象多态,行为多态。
前提:有继承/实现关系,存在父类引用子类对象,存在方法重写(才会有行为多态)
(2)使用好处
- 在多态形式下,右边对象是解耦合的,更便于拓展和维护。
- 定义方法时,使用父类类型的形参,可以接收一切子类对象,扩展性强,更便利
*多态下会产生下一个问题 :多态下不能使用子类的独有功能。
package d2_OPP;public class Student extends People{@Overridepublic void run(){System.out.println("学生跑的很快");}public void text(){System.out.println("学生需要考试");}
}package d2_OPP;public class Teacher extends People {@Overridepublic void run(){System.out.println("老师跑的气喘嘘嘘");}public void teach(){System.out.println("老师需要教书");}
}package d2_OPP;public class Text {public static void main(String[] args) {//理解多态的好处//好处1 可以实现解耦合 右边对象随时切换 后续业务随之改变People p1 = new Student(); //new Studentp1.run();//p1.text();Student s = new Student();go(s);Teacher t = new Teacher();go(t);}//好处2 可以使用父类类型的变量作为形参,可以接收一切子类对象public static void go(People p){}}
(3)多态下的类型转换问题
类型转换:(解决多态下不能调用子类独有方法的问题)
- 自动类型转换:父类 变量名 = new 子类();
- 强制类型转换:子类 变量名 = (子类)父类变量
强制类型看转换的一个注意事项:
- 存在继承/实现关系就可以在编译阶段进行强制类型转化,编译不报错
- 运行时,如果发现对象的真实类型与强转后的类型不同,会报类型转换异常(ClassCastException)的错误出来
- (使用关键字 instanceof 进行判断真实类型)
package d2_OPP;public class Text {public static void main(String[] args) {//理解多态的好处//好处1 可以实现解耦合 右边对象随时切换 后续业务随之改变People p1 = new Student(); //new Studentp1.run();//强制类型转化if(p1 instanceof Student) {Student s1 = (Student) p1;s1.text();}else {Teacher t2 = new Teacher();t2.teach();}//就可以执行独特功能Student s = new Student();go(s);Teacher t = new Teacher();go(t);}//好处2 可以使用父类类型的变量作为形参,可以接收一切子类对象public static void go(People p){if(p instanceof Student) {Student s1 = (Student) p;s1.run();}else {Teacher t2 = (Teacher) p;t2.run();}}}
4.final
(1)认识与了解
final关键字是最终的意思,可以修饰类,方法,变量
- 修饰类 :最终类 特点是不能被继承了
- 修饰方法:最终方法 特点是不能被重写了
- 修饰变量:该变量只能被赋值一次
- (final修饰基本类型的变量,变量存储的数据不能改变)
- (final修饰引用类型的变量 地址不能改变 但是地址指向的内容是可以改变的)
package d3_final;public class Text {public static void main(String[] args) {//final 修饰变懒 有且仅能赋值一次 /*变量一。局部变量二。成员变量1.静态成员变量2.实例成员变量 */final int a;a = 5;// a = 6; //第二次赋值会出错 保护数值}
}//1.final 修饰类,类不能被继承 (一般用于工作类)
final class A{}//class B extends A{}//2.final 修饰方法 方法不能被重写class C{public final void text (){}
}/*class D extends C{@Overridepublic void text(){}
}*/
(2)常量详解
- 使用了static final修饰的成员变量就称为常量
- 作用:通常用于记录系统的配置信息
注意:命名规范:大写英文字母,多个单词使用下划线
常量的优势和执行原理:
- 代码可读性好,可维护性也更好
- 编译后,常量会进行 “宏替换”
5.抽象类
(1)认识与入门
java 有一个关键字 abstract 抽象 用来修饰类和方法
package d4_abstrsact;
//抽象类
public abstract class A {//抽象方法 必须用abstract修饰,只有方法签名 一定不能有方法体public abstract void run();
}
抽象类的注意事项特点:
- 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类。
- 类该有的成员成员变量,方法,构造器,抽象类都可以有。
- 抽象类最主要的特点,抽象类不能创建对象,仅作为一特殊的父类让子类继承并实现。
- 一个类继承抽象类必须重写抽象类的全部抽象方法。否则这个类也必须定义为抽象类。
(2)使用好处
父类知道每个子类都要做某个行为,但每个子类要做的情况不一样,父类就定义为抽象方法。交给子类去重写实现。我们设计这样的抽象类就是为了更好的支持多态。
package d4_abstrsact;public abstract class Animal {private String name;public abstract void cry();public String getName() {return name;}public void setName(String name) {this.name = name;}
}package d4_abstrsact;public class Dog extends Animal {@Overridepublic void cry() {System.out.println("汪汪汪、、、");}
}package d4_abstrsact;public class Cat extends Animal{@Overridepublic void cry() {System.out.println("喵喵喵。。。");}
}package d4_abstrsact;public class Text {public static void main(String[] args) {Cat c = new Cat();Dog d = new Dog();c.cry();d.cry();}
}
(3)应用场景
模板方法设计模式
解决方法中存在重复代码的问题
写法:
- 1.定义一个抽象类
- 2.在里面定义两个方法;
一个是模板方法:把相同的代码放里面去
一个是抽象方法:具体实现交给子类实现
package d5_abstract;public class Text {public static void main(String[] args) {//目标:搞清楚抽象类的应用场景之一,经常用来设计模板方法设计模式//场景 :学生,老师都要写一篇作文//开头 结尾一样,正文自由发挥Teacher t = new Teacher();t.write();}
}package d5_abstract;public abstract class People {// 设计模板方式方法//定义一个模板方法public void write() {System.out.println("\t\t\t\t\t《我的爸爸》");//模板方法不清楚正文部分怎么写,但是它知道子类要去写System.out.println(writeMain());System.out.println("有这样的爸爸太好了");
}public abstract String writeMain();}package d5_abstract;public class Teacher extends People {public String writeMain() {return "也是非常厉害";}
}package d5_abstract;public class Student extends People {@Overridepublic String writeMain() {return " 厉害";}
}
建议 final关键字修饰模版方法 :
- 模板方法直接给对象使用,不能被子类重写
- 一旦子类重写了模板方法,模板方法就失效了
6.接口
(1)概述
java 提供了一个关键字interface ,用这个关键字可以定义一个特殊的结构:接口
接口中没有构造器和代码块之类的东西 ,接口也不可以创建对象。接口是被类实现(implements)的,实现接口的类称为实现类。
一个类可以实现多个接口(接口可以理解成干爹),实现类实现多个接口。必须重写完全部接口的全部抽象方法,否则实现类需要定义为抽象类
接口的好处:
弥补了类单继承的不足,一个类同时实现多个接口。(拓展功能)
让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现
package d6_interface;public class Text {public static void main(String[] args) {//目标:搞清楚使用接口的好处Driver s = new A();s.drive();}
}class A extends Student implements Driver {@Overridepublic void drive(){System.out.println("会开车");}
}class Student{}interface Driver {void drive();
}interface Singer{void sing();
}
(2)综合案例
需求:
请涉及一个班级学生的信息管理模块,学生的数据有:姓名,性别,成绩,
功能1:要求打印出全班学生的信息。功能2:要求打印出全班学生的平均成绩。
————————————————————————————————————————
以上业务的实现有多套方案。例如:
第一套方案能打印班级全部学生的信息,能打印班级全部学生的平均分。
第二套方案能打印出班级全部学生的信息(包括男女人数)。能打印班级全部学生的平均分(要求是去掉最高分,最低分)。
package d7_interface_demo;import java.util.ArrayList;public class student_mpl1 implements studentOperator {@Overridepublic void printAllInfo(ArrayList<Student> students){System.out.println("======全班全部学生信息======");for (int i = 0; i < students.size(); i++) {Student s = students.get(i);System.out.println("姓名:"+s.getName());System.out.println("性别:"+s.getSex());System.out.println("成绩:"+s.getScore());System.out.println("======================");}System.out.println("打印完毕");}@Overridepublic void printAverageScore(ArrayList<Student> students){double allScore = 0.0;for (int i = 0; i < students.size(); i++) {Student s = students.get(i);allScore += s.getScore();}System.out.println("平均分:"+(allScore/students.size()));}
}
package d7_interface_demo;import java.util.ArrayList;public class student_mpl2 implements studentOperator{@Overridepublic void printAllInfo(ArrayList<Student> students){System.out.println("======全班全部学生信息======");int count1 = 0;int count2 = 0;for (int i = 0; i < students.size(); i++) {Student s = students.get(i);System.out.println("姓名"+s.getName());System.out.println("性别"+s.getSex());if(s.getSex() == '男'){count1++;}else{count2++;}System.out.println("成绩"+s.getScore());System.out.println("======================");}System.out.println("男生人数:"+count1);System.out.println("女生人数:"+count2);System.out.println("班级总人数"+students.size());System.out.println("打印完毕");}@Overridepublic void printAverageScore(ArrayList<Student> students){double allScore = 0.0;double max = students.get(0).getScore();double min = students.get(0).getScore();for (int i = 0; i < students.size(); i++) {Student s = students.get(i);allScore += s.getScore();if(s.getScore() > max){max = s.getScore();}if(s.getScore() < min){min = s.getScore();}}System.out.println("学生的最高分:"+max);System.out.println("学生的最低分:"+min);System.out.println("平均分:"+((allScore-max-min)/students.size()-2));}
}
package d7_interface_demo;import java.util.ArrayList;public interface studentOperator {void printAllInfo(ArrayList<Student> students);void printAverageScore(ArrayList<Student> students);
}
package d7_interface_demo;import java.util.ArrayList;public class ClassManager {private ArrayList<Student> students = new ArrayList<>();private studentOperator stuopera = new student_mpl1();//private studentOperator stuopera = new student_mpl2();public ClassManager(){students.add(new Student("陈平安",'男',88));students.add(new Student("刘羡阳",'男',100));students.add(new Student("顾璨",'男',90));students.add(new Student("宁姚",'女',100));}//打印全班全部学生信息public void printInfo(){stuopera.printAllInfo(students);}//打印全班全部学生的平均分public void printScore(){stuopera.printAverageScore(students);}
}
package d7_interface_demo;public class Text {public static void main(String[] args) {//目标:完成班级学生信息管理的案例ClassManager opera = new ClassManager();opera.printInfo();opera.printScore();}
}
(3)接口的细节
JDK8后接口新增的三种方法(增强接口功能,便于系统维护)
package d8_jdk8;public interface A {//1.默认方法:必须使用default修饰,默认会被public修饰//实例方法:对象访问 ,必须通过实现类default void text1(){System.out.println("默认方法");text2();}//2.私有方法:必须使用private修饰//jkk9后支持 //在接口中调用private void text2(){System.out.println("私有方法");}//3.静态方法:必须使用static修饰//只能使用接口名来调用public static void text3(){System.out.println("静态方法");}
}
接口的多继承
便于类去实现
接口的注意事项(了解)
- 一个接口继承多个接口,如果多个接口中存在方法签名冲突,则此时不支持多继承。
- 一个类实现多个接口,如果多个接口中存在方法签名冲突,则此时不支持多实现.
- 一个类,继承了父类,又同时实现了接口。父类中和接口中有同名的默认方法实现类会优先用父类的。
- 一个类实现了多个接口,多个接口中存在同名的默认方法可以不冲突,这个类重写该方法即可。
7.内部类
(1)内部类概述
内部类是类中的五大成分之一(成员变量,方法,构造器,内部类,代码块),一个类定义在另一个类的内部,这个类就是内部类
(2)成员内部类
类中的一个普通成员,类似前面学过的普通的成员变量,成员方法(注意访问特点)
注意事项:
1.jdk16后支持内部类创建静态成员变量
2.内部类创建对象的格式:外部类名.内部类名 对象名 = new 外部类 (...)new 内部类(...);
(3)静态内部类
有static修饰的内部类,属于外部类自己持有。
(4)局部内部类
局部内部类是定义在方法中,代码中,构造体等执行体(鸡肋语法)
(5)匿名内部类*
就是一种特殊的内部类;所谓匿名:指程序员不需要为这个类声明名字
使用场景: 通常作为一个参数传输给方法
实际应用场景:
package d2_inner;import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;public class Text4 {public static void main(String[] args) {//拓展:搞清楚匿名内部类在着真实开发中的使用场景//GUI编程//1.创建窗口JFrame win = new JFrame("登录界面");JPanel panel = new JPanel();win.add(panel);JButton btn = new JButton("登录");win.add(btn);// 给按钮绑定单击事件监听器btn.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {JOptionPane.showMessageDialog(win,"欢迎");}});//最终的核心目的是:简化代码win.setSize(400,400);win.setLocationRelativeTo(null);win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);win.setVisible(true);} }
8.枚举
枚举是一种特殊类
(1)介绍
- 枚举类的第一行只能罗列一些名称,这些名称都是常量,并且每一个常量记住的都是枚举类的一个对象。
- 枚举类的构造器都是私有的(写与不写都只能是私有),因此枚举类对外不能创建对象。
- 枚举都是最终类,不可以被继承,枚举类中从第二行开始可以定义类的其他各种成员。
- 编译器为枚举类新增了几个方法,并且枚举类都是继承JAVA.long.Enum类。
package d3_enum;public class Text {public static void main(String[] args) {//目标 认识枚举A a1 = A.X ;System.out.println(a1);//枚举类提供一个一些额外的APIA[] as = A.values(); //拿到全部对象A a3 = A.valueOf("Z");System.out.println(a3.name());System.out.println(a3.ordinal()); //索引}
}
(2)应用场景
应用场景: 用来表示一组信息,然后作为参数进行传输
作为信息分类
9.泛型
(1)认识泛型
泛型:定义类,接口,方法时,同时声明了一个或者多个类型变量<E>,称为泛型类,泛型接口,泛型方法,统称为泛型
作用:泛型提供了在编译阶段约束所能操作的数据类型,并自动进行检查的能力,这样可以避免强制类型转换,及其可能出现的异常
泛型的本质:把具体的数据类型作为参数传给类型变量
(2)泛型类
package d5_generics;public class List <E>{private Object [] arr = new Object[10];private int size;public boolean add(E e){arr[size++] = e;return true;}public E get (int index){return (E) arr[index];}
}
(3)泛型接口
package d5_generics;import java.util.ArrayList;public interface Data<T> {void add(T t);ArrayList<T> getByName(String name);
}
泛型接口的类型变量建议使用大写英文字母
(4)泛型方法,泛型通配符,上下限
package d5_generics;import java.util.ArrayList;public class Text3 {public static void main(String[] args) {//目标:掌握泛型方法的定义和使用String rs = test("java");Dog d = test(new Dog());System.out.println(d);}//泛型方法public static <T> T test (T t){return t;}//使用extends限制输入类型 是car或者car的子类public static <T extends car > void go(ArrayList<T> car){}//? 通用符 使用泛型可以代表一切类型 一样可以限制 ?extends car(上限) ?super car(下限)public static void go1(ArrayList<? extends car> car){}
}
(5)注意事项
擦除问题
泛型是工作在编译阶段的,一旦程序编译成class文件。Class文件中就不存在泛型了,这就是泛型擦除。(底层还是基于Object类型)
泛型不支持基本数据类型。只能支持对象类型(引用数据类型)。
学习时间:2024.8.4