泛型:
首先,我理解的泛型就是没有定义的类的模型,在定义类的时候只需要在后面加一个<>,就可以了,
例如
public class Fanxing<T>;
我们可以直接创建一个泛型:
Fanxing<String> fanxing=new Fanxing<String>();
上述代码需要注意的是,泛型对象在创建的时候必须指明创建的类型,否则不予通过;
泛型对于我们来说,避免了基本类型在转换时带来的错误,我们来看下面的代码
Object obj=new Float(15.6);//创建Object类对象
Float flo=obj;//执行向下转型操作;
此代码并不存在语法错误,但是在编译的时候会出现异常。接下来我们看一下怎么利用泛型执行上述操作;
Fanxing<Float> flo=new Fanxing<Float>();//创建泛型对象,并指定类型
flo=15.6;
泛型除了以上的用法,我们还可以在定义泛型类时,定义多个类型,语法如下
class Fanxing<T,X>
具有多个属性的泛型类在生成对象时,就需要同事指明每个类型的具体类型;
Fanxing<String,Integer> fanxing=new Fanxing<String,Integer>;
泛型同时也具备泛型方法,泛型方法定义如下:
public <T> T test(T t){
return t
}
首先我们要先声明一个泛型,同时指明返回值为T.上述方法的功能就是返回一个类型为T的值;
同时泛型也支持泛型集合,定义语法如下:
public class fan <T> {
private T[] array;//定义一个泛型结合
public void setArray(T[] array) {//传参方法
this.array = array;
}
public T[] getArray() {
return array;
}
public static void main(String[] args) {
fan <Integer> in=new fan<Integer>();声明泛型对象为Integer型
Integer array[]={1,6,7,9,4,7};创建一个数组,必须与泛型类型完全,注意啊,是完全一样,Integer就是Integer,不能使int;
in.setArray(array);//将创建好的数组传进泛型数组
for (int i = 0; i < in.getArray().length; i++) {
System.out.println(in.getArray()[i]);//遍历输出
}
}
我们需要注意,定义泛型数组时不能像定义普通数组那样
fan<String> []fan=new fan<String>[10]//错!
接下来我们来讲解一下怎么限制泛型的可用类型
我们说泛型的类型其实是自己定义的,那么我们在定义的时候加一个限制条件例如
enum Test<T extends List>
Test<ArrayList> test1=new Test<ArrayList>();
Test<LinkedList> test1=new Test<LinkedList>();
首先我们来看使用extends关键字,我们知道extends是继承的关键字,用在泛型的限制条件的时候就表明接下来我们定义的泛型的类型只能是后面接的类型的子类,如果extends后面接的是一个接口,那么定义的泛型类型必须实现此接口。以上述代码来说,由于ArrayList和LinkedList都实现了List接口,所以创建可以成功。
enum Test<T super List>
好,我们这次看到关键字换成了super,我们知道super是调用父类的关键字,所以根据上一例代码的经验我们可以推断出接下来定义的泛型的类型必须是后面接的父类。但是一般我们不用这个方法。
最后一讲:泛型通配符 “?”
在定义泛型类型或者方法的时候我们可以不声明具体的类型,我们可以这样
class Test<T>{
public void test(T<?> t){//定义方法,对与泛型,只能取出或删除,不能修改
}
Test<?> test1=new Test<?>;//定义泛型对象,只能取出或删除,不能修改
}
在加了通配符之后呢,我们可以看到,对于泛型的操作,只能是获取或者删除,不能对其增加内容,这是为了避免不同类型的泛型对象同时调用一个方法而导致的类型冲突,看例子
public class fan <T> {
private T test;
public T getTest() {//定义get方法
return test;
}
public void setTest(T test) {//定义set方法,为泛型赋值
this.test = test;
}
private fan(T t){//定义构造方法
this.test=t;
}
public static void main(String[] args) {
fan<String> test=new fan<String>("liqifeng");//定义泛型,为String
test.test(test);//String泛型调用方法,失败,但是编辑器不报错。
}
public void test(fan t){//定义方法,不声明泛型类型,默认为Object
System.out.println(t.getTest());//取出泛型的值
//t.setTest(100); 划重点啊:我们在使用set方法赋值的时候,我们赋的值为int值,但是如果是其他的泛型类型调用呢?
}
}
ok,我们泛型就说到这,根据以上的讲解我们来总结一下泛型的用法
- 泛型的类型参数只能是类类型,不可以是简单类型,例如A,就是错误的
- 泛型的类型参数可以是多个
- 可以使用extends或者super限制泛型的类型
- 可以使用通配符限制泛型的类型,并且默认只能取出或删除
枚举:
首先,我们先说明枚举的本质是类,可以使用枚举类型取代以往定义常量的方式,这是枚举带给我们的最大好处。好,接下来我们通过一串代码来看一下枚举带来的好处
public class enum{
enum one=new enum();
eunm two=new enum();
}
以上使我们常用的创建对象的方式,接下来我们看一下如何使用枚举来创建对象
enum enum{
one,two}
这样,我们就创建好了两个对象,是不是感觉非常方便呢。
从上数代码我们可以看出,创建一个枚举类型其实非常简单,只需要在类的前面加一个enum关键字就可以了。
划个重点:枚举类型的构造方法只能用private修饰符修饰。原理我说不上来
好的,接下来我们一下枚举的使用,我们可以将枚举类型看做一个类,它继承于java.lang.Enum接口,当定义一个枚举类型时,默认实现此接口。也就是说,该借口内的方法我们也可以拿到枚举类型中用。让我们看一下有哪些方法吧:
- values();该方法可以将枚举类型成员以数组的形式返回;
我们来看一下具体怎么实现方法
enum test {//定义test枚举类
one,two;//生成两个对象
public static void main(String[] args) {
for (int i = 0; i < test.values().length; i++) {
System.out.println(test.values()[i]);
}//使用values()方法
}
}
上述我们可以看到,我们直接使用valuse();返回了一个数组,并且遍历此枚举类型的对象;
2.compereTo();此方法用于比较两个枚举对象在定义时候的顺序;
enum test {
one,two;
public static void main(String[] args) {
int a =one.compareTo(two);//调用compareTo()方法直接比较,返回的值为int型
System.out.println(a);
}
}
`
3.valueOf();这个就厉害了,可以把普通的字符串转换成枚举的实例
`enum test {
one,two;
public static void main(String[] args) {
String abc="two";//定义一个字符串two
int a = test.valueOf(abc).compareTo(one);直接利用方法生成的对象进行对比
System.out.println(a);
}
}
划重点:刚才试了很多遍,发现那个字符串一定要是已有的枚举类型,如果String abc定义为‘three’或者任何与已存在的枚举类型不符的话,就会报错。
4.ordinal()z这个方法就比较简单了,就是返回一个枚举成员的位置索引
enum test {
one,two;
public static void main(String[] args) {
for (int i = 0; i < test.values().length; i++) {
System.out.println(test.values()[i]+"-"+test.values()[i].ordinal());
}
}
}
上述代码返回的结果是
one-0
two-1
接来下我们来讲一下枚举类实现接口的方法:
首先我们先编写一个接口
interface Test{
public String getName();
}
编写完接口我们需要编写一个枚举类来实现这个接口
enum Test2 implements Test {
one("liqifeng"), two("wuyachen");
private String name;// 定义name
public String getName() {// 实现接口中的getName方法
return this.name;
}
private Test2(String name) {// 定义构造方法,并且传参
this.name = name;
}
}
好吧,其实简单的来讲,通过上述代码我们可以看到,枚举类实现接口就和普通的类一样,但是复杂一点来讲,那就有点复杂了;看代码
enum Test2 implements Test{
one("liqifeng"){//生成一个对象
public String getName() {//在对象内实现接口
return "liqifeng";
}
},
two("wuyachen"){//生成一个对象
public String getName() {//在对象内实现接口
return "wuyachen";
}
};
private String name;
private Test2(String name){//定义构造方法,传参数
this.name=name;
}
public static void main(String[] args) {
System.out.println(one.getName());
System.out.println(two.getName());
}
}
上述代码输出结果是
liqifeng
wuyachen
从上述代码我们可以看出,我们的接口并没有在类中实现,而是在对象中实现。666,简直颠覆了我的三观
好吧,等我看到了抽象方法的时候,我的三观已经崩溃了,看代码吧
enum Test2 {
one("liqifeng"){//生成一个对象
public String getName() {//在对象内实现抽象方法
return "liqifeng";
}
},
two("wuyachen"){//生成一个对象
public String getName() {//在对象内实现抽象方法
return "wuyachen";
}
};
private String name;
public abstract String getName();//定义抽象方法
private Test2(String name){//定义构造方法,传参数
this.name=name;
}
public static void main(String[] args) {
System.out.println(one.getName());
System.out.println(two.getName());
}
}
上述代码输出结果是
liqifeng
wuyachen
嗯,这次我们把接口给撤了,我们直接定义了一个抽象方法,“public abstract String getName();”,然后在每个对象里面实现就行了。
不多解释,我已懵逼;
以上呢就是我对于枚举的全部理解,我总结了一下枚举的优点
- 方便
好的,结束