【今日】️️️
苦尽甘来是真理
----致每一位坚持的伙伴
目录
目录
导读
一 枚举类型
1.1 使用枚举类型设置常量
1.2 深入了解枚举类型
1.3使用枚举类型的好处
二 泛型
2.1 定义泛型
2.2泛型的常规用法
2.3泛型的高级用法
2.4 泛型总结
枚举类型可以取代以往常量的定义方式,即将常量封装在类或接口中。此外,它还提供了安全检查功能。枚举类型本质上还是以类的形式存在的。泛型的出现不仅可以让程序员少写一些代码,更重要的是它可以解决类型安全问题。泛型提供了编译时的安全检查,不会因为将对象置于某个容器中而失去其类型。具体学习方面如下:
使用枚举类型,可以取代前面学习过的定义常量的方式,同时枚举类型还赋予程序在编译时进检查的功能。
设置常量时,我们通常将常量放置在接口中,这样在程序中就可以直接使用。该常量不能被修改因为在接口中定义常量时,该常量的修饰符为final与static。常规定义常量代码如下:
public interface Constants {//接口Constants public static final int Constants_A=1; public static final int Constants_B=12; }
而枚举类型可以取代上述接口实现设置常量的方法:枚举类型是一种特殊的数据类型,它允许我们定义一个有限的、指定值的集合。在Java中,枚举类型是通过关键字"enum"来定义的。使用枚举类型定义常量的语法如下:
public enum Constants { Constants_B, Constants_C, } /* * public enum 枚举类名 { * 枚举1, * 枚举2, * 枚举3, * .... * } */
其中,enum是定义枚举类型的关键词。当程序中需要使用该常量时。可以使用Constants.Comstants_A来表示。
我们用接口创建的常量与枚举放在一起对比一下:
代码️️️
public interface season {//创建四季接口
int SPRING = 1;
int SUMMER = 2;
int AUTMN = 3;
int WINTER = 4;
}//单独创建
public enum season1 {//四季枚举
SPRING,
SUMMER,
AUTUMN,
WINTER
}//单独创建
public class Dome {
public static void print1(int s) {//通过接口常量实现输出四季
switch(s){
case season.SPRING:
System.out.println("这是春季");break;
case season.SUMMER:
System.out.println("这是夏季");break;
case season.AUTMN:
System.out.println("这是秋季");break;
case season.WINTER:
System.out.println("这是冬季");break;
}
}
public static void print2(season1 s) {//通过枚举实现四季常量
switch(s) {
case SPRING:
System.out.println("这是春季");break;
case SUMMER:
System.out.println("这是夏季");break;
case AUTUMN:
System.out.println("这是秋季");break;
case WINTER:
System.out.println("这是冬季");break;
}
}
public static void main(String[] args) {
print1(season.WINTER);//接口常量做参数
print1(2);//数字做参数
print1(100);//可以使用接口常量值以外的数字冒充“常量“
print2(season1.AUTUMN);//只能使用枚举做参数
print2(season1.WINTER);
}
}
运行结果
分析:
我们可以发现代码中有一句没有运行出结果:
print1(100)这是因为接口创建的常量再运行时,我们给的参数可以冒充常量,而实际接口常量中并没有它,因此无法运行出结果。
而枚举常量不纯在这种结果:
当我们所给的参数不是枚举中的参数时就会报错。
枚举类型较传统定义常量的方式,除具有参数类型检测的优势外,还具有其他方面的优势。用户可以将一个枚举类型看作是一个类,它继承于java.lang.Enum类,当定义一个枚举类型时,每一个枚举类型成员都可以看作是枚举类型的一个实例,这些枚举类型成员都默认被final、public、staig修饰,所以当使用枚举类型成员时直接使用枚举类型名称调用枚举类型成员即可。
由于枚举类型对象继承于java.lang.Enum类,所以该类中一些操作枚举类型的方法都可以应用到枚举类型中。
枚举类型的常用方法
1.values()方法
该方法可以将枚举类型成员以数组的形式返回。
public enum Contants {
Contants_A,
Contants_B,
Contants_C,
Contants_D,
Contants_E,
Contants_F
}//单独创建
public class Dome {
public static void main(String[] args) {
Contants a[] = Contants.values();
for(int i=0;i
2.valueof()方法
该方法可以实现将普通字符串转换为枚举实例。
public enum Contants {
Contants_A,
Contants_B,
Contants_C,
Contants_D,
Contants_E,
Contants_F
}//单独创建
public class Dome {
public static void main(String[] args) {
Contants c1 = Contants.Contants_A;
Contants c2 = Contants.valueOf("Contants_A");
System.out.println("c1与c2是否相等?"+(c1==c2));
}
}
注意️️️
我们使用valueof()方法时要注意()里面的内容要真是存在,比如上面的”ko"在枚举常量中不存在因此会出现报错!
3.compareTo()方法
该方法用于比较两个枚举对象在定义时的顺序。规则如下:
public enum Contants {
Contants_A,
Contants_B,
Contants_C,
Contants_D,
Contants_E,
Contants_F
}//单独创建
public class Dome {
public static void main(String[] args) {
Contants c = Contants.valueOf("Contants_C");
Contants a[]= Contants.values();
for(int i=0;i
4.ordinal()方法
该方法用于得到枚举成员的位置索引。
public enum Contants {
Contants_A,
Contants_B,
Contants_C,
Contants_D,
Contants_E,
Contants_F
}//单独创建
public class Dome {
public static void main(String[] args) {
Contants a[]= Contants.values();
for(int i=0;i
5.枚举类型中的构造方法
在枚举类型中,可以添加构造方法,但是规定这个构造方法必须被private所修饰。枚举类型的构造方法语法如下:
public enum 枚举类型名称{
Constants_A("我是枚举成员A"),
Constants_B("我是枚举成员B"),
Constants_C("我是枚举成员C"),
Constants_D(32);
private String description;
private Constants2() {
}//定义默认构造方法
private Constants2(String description) {//定义带参数的构造方法,参数类型为字符串型
this.description=description;
}
private Constants2(int i) {//定义带参数的构造方法,参数类型为整型
this.i=i+1;
}
}
实列:
public enum Contants {
Contants_A("中年男神:秀才"),
Contants_B("中年女神:一笑倾城"),
Contants_C("不如蓝色妖姬");
private String str ;
private Contants(String str) {
this.str=str;
}
public String get() {
return str;
}
}//单独创建
public class Dome {
public static void main(String[] args) {
Contants a[]= Contants.values();
for(int i=0;i
枚举类型的特点如下:
️类型安全
紧凑有效的数据定义
可以和程序其他部分完美交互
运行效率高
Object类为最上层的父类,很多程序员为了使程序更为通用,设计程序时通常使传入的值与返回的值都以Object类型为主。当需要使用这些实例时,必须正确地将该实例转换为原来的类型,否则在运行时将会发生ClassCastException异常。
为了提前预防这种问题,Java提供了泛型机制。语法如下:类名<类型参数T, 类型参数T2, .... , 类型参数Tn> { }
其中,T是泛型的名称,代表某一种类型。开发者在创建该类对象时需要指定T所代表哪种具体的类型。如果不指定具体类型,T则采用Object类型。
注意:如果定义了泛型却不使用,Eclipse会发出警告。
public class Demo {
T over;
public T getOver() {
return over;
}
public void setOver(T over) {
this.over = over;
}
public static void main(String[] args) {
Demo d1 = new Demo();
d1.setOver(true);
Boolean b=d1.getOver();
System.out.println(b);
Demo d2 = new Demo();
d2.setOver(254);
int i=d2.getOver();
System.out.println(i);
}
}
1.继承泛型类和泛型接口
public class Dome{
}
class Father{//父类
T t;
public Father(T t) {//父类的构造方法
this.t = t;
}
}
interface TestInterface{//接口
}
class Child extends Father implements TestInterface{//这里T1与T2命名不影响主要看继承效果
public Child(T t) {//子类必须也要有相同的构造方法
super(t);
// TODO 自动生成的构造函数存根
}
}
继承泛型的四种情况:
1.全部继承:
public class Dome{ public static void main(String[] args) { Father
f = new Child<>(1,"Ok") ; //Child c = new Child<>(1,"KO"); Child c = new Child<>(1,true); } } class Father {//父类 T1 t1; T2 t2; public Father(T1 t1, T2 t2) { this.t1 = t1; this.t2 = t2; System.out.println("t1的类型:"+this.t1.getClass()); System.out.println("t2的类型:"+this.t2.getClass()); } } class Child extends Father { public Child(T1 t1, T3 t3) { super(t1, t3); // TODO 自动生成的构造函数存根 } } 注意:
参数要匹配不然报错,运行不出来结果。
2.部分继承
给父类实现一个类型,子类只继承一个。
public class Dome{ public static void main(String[] args) { Child
c = new Child<>(1,"2"); Child f= new Child<>("1","2"); } } class Father {//父类 T1 t1; T2 t2; public Father(T1 t1, T2 t2) { this.t1 = t1; this.t2 = t2; System.out.println("t1的类型:"+this.t1.getClass()); System.out.println("t2的类型:"+this.t2.getClass()); } } class Child extends Father { public Child(T1 t1, String t3) { super(t1,t3); // TODO 自动生成的构造函数存根 } } 3.实现父类泛型
public class Dome{ public static void main(String[] args) { Child
c = new Child<>(1,"2"); } } class Father {//父类 T1 t1; T2 t2; public Father(T1 t1, T2 t2) { this.t1 = t1; this.t2 = t2; System.out.println("t1的类型:"+this.t1.getClass()); System.out.println("t2的类型:"+this.t2.getClass()); } } class Child extends Father { public Child(Integer t1, String t2) { super(t1,t2); } } 4.不实现父类泛型
import java.util.Date; public class Dome{ public static void main(String[] args) { Child
c = new Child<>(new Object(),new Date()); } } class Father {//父类 T1 t1;//Object t1 T2 t2;//Object t2 public Father(T1 t1, T2 t2) { this.t1 = t1; this.t2 = t2; System.out.println("t1的类型:"+this.t1.getClass()); System.out.println("t2的类型:"+this.t2.getClass()); } } class Child extends Father{ public Child(Object t1, Object t2) {//这里可以输入任何类型 super(t1,t2); } }
1.限制泛型可用类型
语法:class 类名称
T必须是anyClass的一个子类.
HashSet不是List的子类,因此会报错。
2.泛型通配符
import java.util.ArrayList; import java.util.List; public class Dome{ public static void main(String[] args) { List
L1 = new ArrayList<>(); L1.add("成员1"); List>L2 = new ArrayList ();//使用泛型通配符以后不能进行添加和修改的操作了 List>L3 = L1; //L2.add(123); System.out.println("L1:"+L1.get(0)); //L3.set(0, "成员改变"); //L3.add("添加成员"); } } 从上面两张图种我们可以发现,一旦使用通配符以后就不能进行添加和改写的操作。
泛型中extend
指定了上界
import java.util.ArrayList; import java.util.List; public class Dome{ public static void main(String[] args) { List
L1 = new ArrayList<>(); L1.add("成员1"); List extends Object>L2 = new ArrayList (); List extends List>L2 = new ArrayList ();//ectends指定了上界,这个类最高为List,不能超过list } } 泛型中super
指定了下界
import java.util.ArrayList; import java.util.List; public class Dome{ public static void main(String[] args) { List
L1 = new ArrayList<>(); L1.add("成员1"); List extends Object>L2 = new ArrayList (); List super List>L2 = new ArrayList
️泛型的类型参数只能是类类型,不可以是简单类型,如A
可以使用extends关键字限制泛型的类型。
可以使用通配符限制泛型的类型。
感谢阅读