泛型

泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数

  • 使用 Java 泛型的概念,我们可以写一个泛型方法来对一个对象数组排序。然后,调用该泛型方法来对整型数组、浮点数数组、字符串数组等进行排序
  • 语法:T称为类型占位符,表示一种引用类型
1
<T...>

泛型类

  • 泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分
1
public class ClassName<T> {}
  • 和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开
  • 一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。因为他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//T为占位符,只能是引用类型
public class MyGeneric<T>{
//使用泛型T
//1. 创建变量
T t;

//2. 作为方法的参数
public void show(T t){
System.out.println(t);
}
//3. 泛型转为方法的返回值
public T getT(){
return t;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Demo01 {
public static void main(String[] args) {
//使用泛型类创建对象 给String类型
//注意:泛型只能使用引用类型,不同的泛型对象不能相互赋值
MyGeneric<String> myGeneric= new MyGeneric<String>();
myGeneric.t="hello";
myGeneric.show("大家好");
String str = myGeneric.getT();

//Integer类型
MyGeneric<Integer> myGeneric1 = new MyGeneric<>();
myGeneric1.t=100;
myGeneric1.show(200);
Integer integer = myGeneric1.getT();
}
}

泛型接口

  • 泛型接口的声明在接口名称后面添加了类型参数声明部分
1
2
3
4
5
6
public interface MyGeneric<T>{
String name = "张三";
//不能创建泛型常量
//方法
T server(T t);
}
  • 第一种实现方法:事先知道引用类型
1
2
3
4
5
6
7
8
9
10
11
12
public class Demo01 implements MyGeneric<String>{
@Override
public String server(String s) {
System.out.println(s);
return s;
}

public static void main(String[] args) {
Demo01 demo01 = new Demo01();
demo01.server("xxxx");
}
}
  • 第二种:不知道引用类型,让实现类也成为泛型类
1
2
3
4
5
6
7
8
9
10
11
public class Demo01<T> implements MyGeneric<T>{
@Override
public T server(T t) {
System.out.println(t);
return t;
}
public static void main(String[] args) {
Demo01<Integer> demo01 = new Demo01<Integer>();
demo01.server(1000);
}
}

泛型方法

  • 你可以写一个泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用
  • 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(在下面例子中的<E>
  • 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
  • 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
  • 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是基本类型
1
2
3
4
5
6
7
public class MyGenericMethod{
//泛型方法
public <T> T show(T t){
System.out.println("泛型方法"+t);
return t;
}
}
1
2
3
4
5
6
7
8
9
public class Demo01{
public static void main(String[] args) {
//泛型方法
MyGenericMethod method = new MyGenericMethod();
method.show("张三");
method.show(200);
method.show(3.14);
}
}

泛型集合

  • 参数化类型、类型安全的集合,强制集合元素的类型必须一致
  • 特点
    • 编译时即可检查,而非运行时抛出异常
    • 访问时,不必类型转换(拆箱)
    • 不同泛型之间引用不能相互赋值,泛型不存在多态
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Demo01{
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("xxx");
arrayList.add("yyy");

ArrayList<Student> arrayList1 = new ArrayList<Student>();
Student s1 = new Student("刘德华","20");
arrayList1.add(s1);
Iterator<Student> iterator = arrayList1.listIterator();
while(iterator.hasNext()){
//少了强制转换
Student s = iterator.next();
System.out.println(s.toString());
}

ArrayList<Integer> arrayList2 = new ArrayList<Integer>();
arrayList2.add(10);
}
}

枚举

  • Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。
  • Java 枚举类使用 enum 关键字来定义,各个常量使用逗号 , 来分割。
  • 例如定义一个颜色的枚举类。
1
2
3
4
enum Color 
{
RED, GREEN, BLUE;
}
  • 以上枚举类 Color 颜色常量有 RED, GREEN, BLUE,分别表示红色,绿色,蓝色。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enum Color
{
RED, GREEN, BLUE;
}

public class Test{
// 执行输出结果
public static void main(String[] args)
{
Color c1 = Color.RED;
System.out.println(c1);
}
}
/*
RED
*/

内部类中使用枚举

  • 枚举类也可以声明在内部类中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Test
{
enum Color
{
RED, GREEN, BLUE;
}

// 执行输出结果
public static void main(String[] args)
{
Color c1 = Color.RED;
System.out.println(c1);
}
}
/*
RED
*/
  • 每个枚举都是通过 Class 在内部实现的,且所有的枚举值都是 public static final
  • 以上的枚举类 Color 转化在内部类实现:
1
2
3
4
5
6
class Color
{
public static final Color RED = new Color();
public static final Color BLUE = new Color();
public static final Color GREEN = new Color();
}

迭代枚举元素

  • 可以使用 for 语句来迭代枚举元素:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enum Color
{
RED, GREEN, BLUE;
}
public class MyClass {
public static void main(String[] args) {
for (Color myVar : Color.values()) {
System.out.println(myVar);
}
}
}
/*
RED
GREEN
BLUE
*/

在 switch 中使用枚举类

  • 枚举类常应用于 switch 语句中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
enum Color
{
RED, GREEN, BLUE;
}
public class MyClass {
public static void main(String[] args) {
Color myVar = Color.BLUE;

switch(myVar) {
case RED:
System.out.println("红色");
break;
case GREEN:
System.out.println("绿色");
break;
case BLUE:
System.out.println("蓝色");
break;
}
}
}
/*
蓝色
*/

相关方法

  • enum 定义的枚举类默认继承了java.lang.Enum类,并实现了 java.lang.Seriablizable java.lang.Comparable 两个接口
常用方法 说明
values() 返回枚举类中所有的值
ordinal() 方法可以找到每个枚举常量的索引,就像数组索引一样
valueOf() 方法返回指定字符串值的枚举常量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
enum Color
{
RED, GREEN, BLUE;
}

public class Test
{
public static void main(String[] args)
{
// 调用 values()
Color[] arr = Color.values();

// 迭代枚举
for (Color col : arr)
{
// 查看索引
System.out.println(col + " at index " + col.ordinal());
}

// 使用 valueOf() 返回枚举常量,不存在的会报错 IllegalArgumentException
System.out.println(Color.valueOf("RED"));
// System.out.println(Color.valueOf("WHITE"));
}
}
/*
RED at index 0
GREEN at index 1
BLUE at index 2
RED
*/

枚举类成员

  • 枚举跟普通类一样可以用自己的变量、方法和构造函数,构造函数只能使用 private 访问修饰符,所以外部无法调用。

  • 枚举既可以包含具体方法,也可以包含抽象方法。 如果枚举类具有抽象方法,则枚举类的每个实例都必须实现它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
enum Color
{
RED, GREEN, BLUE;

// 构造函数
private Color()
{
System.out.println("Constructor called for : " + this.toString());
}

public void colorInfo()
{
System.out.println("Universal Color");
}
}

public class Test
{
// 输出
public static void main(String[] args)
{
Color c1 = Color.RED;
System.out.println(c1);
c1.colorInfo();
}
}
/*
Constructor called for : RED
Constructor called for : GREEN
Constructor called for : BLUE
RED
Universal Color
*/