1. 泛型
- 由于集合可以存储不同类型的数据,所以取元素时有可能会导致类型转换错误
- JDK1.5增加了新特性泛型,为了减少操作集合时出错的几率
- 集合一旦声明了泛型,便只能存储同一类型的对象了
1.1 好处
- 将运行时期出现问题ClassCastException,转移到了编译时期。方便于程序员解决问题。让运行时问题减少,安全。
- 避免了强制转换麻烦。
泛型格式:通过<>来定义要操作的引用数据类型。
- 在使用java提供的对象时,什么时候写泛型呢?
- 通常在集合框架中很常见,只要见到<>就要定义泛型。其实<> 就是用来接收类型的。当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
泛型方法
你可以写一个泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。
下面是定义泛型方法的规则:
- 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(在下面例子中的
)。 - 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
- 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
- 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像int,double,char的等)。
有界的类型参数:
可能有时候,你会想限制那些被允许传递到一个类型参数的类型种类范围。例如,一个操作数字的方法可能只希望接受Number
或者Number
子类的实例。这就是有界类型参数的目的。
要声明一个有界的类型参数,首先列出类型参数的名称,后跟extends关键字,最后紧跟它的上界。
1 | // 比较三个值并返回最大值 |
泛型类
泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分。
和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。因为他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。
1 | public class Box<T> { |
类型通配符
- 类型通配符一般是使用
?
代替具体的类型参数。例如 List<?> 在逻辑上是List<String>,List<Integer>
等所有List<具体类型实参>
的父类。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21public class GenericTest {
public static void main(String[] args) {
List<String> name = new ArrayList<String>();
List<Integer> age = new ArrayList<Integer>();
List<Number> number = new ArrayList<Number>();
name.add("icon");
age.add(18);
number.add(314);
getData(name);
getData(age);
getData(number);
}
public static void getData(List<?> data) {
System.out.println("data :" + data.get(0));
}
}
解析: 因为getData()
方法的参数是List
类型的,所以name,age,number
都可以作为这个方法的实参,这就是通配符的作用
- 类型通配符上限通过形如
List
来定义,如此定义就是通配符泛型值接受Number
及其下层子类类型。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25public class GenericTest {
public static void main(String[] args) {
List<String> name = new ArrayList<String>();
List<Integer> age = new ArrayList<Integer>();
List<Number> number = new ArrayList<Number>();
name.add("icon");
age.add(18);
number.add(314);
//getUperNumber(name);//1
getUperNumber(age);//2
getUperNumber(number);//3
}
public static void getData(List<?> data) {
System.out.println("data :" + data.get(0));
}
public static void getUperNumber(List<? extends Number> data) {
System.out.println("data :" + data.get(0));
}
}
解析: 在(//1)处会出现错误,因为getUperNumber()
方法中的参数已经限定了参数泛型上限为Number
,所以泛型为String
是不在这个范围之内,所以会报错
- 类型通配符下限通过形如
List<? super Number>
来定义,表示类型只能接受Number及其三层父类类型,如 Object 类型的实例。
2. 增强For循环
1 | for(数据类型 变量名 : 被遍历的集合(Collection)或者数组) |
对集合进行遍历。只能获取集合元素。但是不能对集合进行操作。
迭代器除了遍历,还可以进行remove集合中元素的动作。
如果是用ListIterator,还可以在遍历过程中对集合进行增删改查的动作。
2.1 传统for和高级for有什么区别呢?
- 高级for有一个局限性。必须有被遍历的目标。
- 建议在遍历数组的时候,还是希望是用传统for。因为传统for可以定义脚标。
3. 可变参数
方法的可变参数。
==在使用时注意==:可变参数一定要定义在参数列表最后面。
可变参数。
- 其实就是上一种数组参数的简写形式。
- 不用每一次都手动的建立数组对象。
- 只要将要操作的元素作为参数传递即可。
- 隐式将这些参数封装成了数组。
4. 静态导入
StaticImport 静态导入。
当类名重名时,需要指定具体的包名。
当方法重名是,指定具备所属的对象或者类。
1 | import java.util.*; |