Java学习笔记@泛型
泛型
以下是泛型相关的概念
| 字词 | 描述 |
|---|---|
| 泛型 | 允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型。 |
<T> 和<E> |
表示形式泛型类型,随后可使用实际具体的类型替换它 |
| 引用变量 | 存储一个对象地址的变量 比如 A a = new A(); 其中 a 就是引用变量 |
| 自动打包 | 把基本数据类型转化成对应类的对象。比如 Integer a = 1; a 作为值是1的 Integer对象。 |
| 自动拆箱 | 把类转化成对应的基本数据类型。比如int b = new Integer(1); |
| 接口 | 在JAVA中是抽象类型,是抽象方法的集合 |
| 原始类型 | 未指定具体类型的泛型类和泛型接口 |
| 通配泛型 | 三种情形?、? extends T、? super T (其中T是泛型类型) |
| 非受限通配 | ?等同于? extends Object |
| 上限通配 | ? extends T表示 T 或 T 的一个子类型 |
| 下限通配 | ? super T 表示 T 或 T 的一个父类型 |
| 类型消除 | 编译器可使用泛型信息,但这些信息在运行时不可用 |
泛型 < > 只支持引用类型
eg. list1是不合法的声明方式
public class test {
public static void main(String[] args) {
// ArrayList<int> list1= new ArrayList<>();
ArrayList<Integer> list2 = new ArrayList<>();
}
}
在泛型的规约下,list2对象只能存储 Integer类型的数据,但是list2.add(1)并不会报错,这是为什么呢?
因为在Java进行编译时,对基本类型和对应的引用类型有自动打包和自动拆箱的机制。
所以 ArrayList<Integer> 本质上是存储 int类型的数据,只是Integer 类包含许多遍历的操作方法。
| 基本类型 | 引用类型 |
|---|---|
| int | Integer |
| byte | Byte |
| short | Short |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
泛型类
定义格式:修饰符 class 类名 < 类型 >
范例:
class Person <T>{
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
泛型方法
定义格式:修饰符<类型> 返回值类型方法名(类型 变量名) { }
范例:
class Person{
public <T> void printData(T data){
System.out.println(data.toString())
}
}
此时可调用printData("test") 、printData(123)
泛型接口
定义格式:修饰符 interface 接口名 <类型> { }
范例:
interface Usb <T> {
void upload(T type);
}
class UsbImpl <T> implements Usb<T>{
@Override
public void upload(T type) {
System.out.println("连接" + type + "成功!");
}
public static void main(String[] args) {
Usb<String> usb = new UsbImpl<>();
usb.upload("usb3.0");
}
}
类型通配符
以 java.lang.Number为例
类型通配符:< ? >
- 上限
< ? extends 类型 >
List<? extends Number> list1 = new ArrayList<Number> ();
List<? extends Number> list2 = new ArrayList<Integer>();
new 后面的泛型类型只能是Number 类型或者其子类
- 下限
< ? super 类型 >
List<? super Number> list3 = new ArrayList<Object>();
List<? super Number> list4 = new ArrayList<Number>();
new 后面的泛型类型只能是Number类型或者其父类
可变参数
指参数个数可变,用作方法的形参出现,那么方法参数个数就可变
格式:修饰符 返回值类型 方法名(数据类型... 变量名 {}
范例:public static int sum(int... array){} (未使用泛型)
class Demo{
public static int sum(int...array){
int result = 0;
for (int x : array)
result += x;
return result;
}
public static void main(String[] args) {
System.out.println(sum(1, 2, 3, 4, 5));
}
}
注意事项:...后的变量为一个数组
若一个方法有多个参数,包含可变参数,那么可变参数要放在最后比如:int sum(int a, int b, int...c)
使用方法
java.util.Arrays类中有一个静态方法 public statci <T> List<T> asList<T...a> 返回由指定数组支持的固定大小的列表
import java.util.Arrays;
import java.util.List;
class Demo{
public static void main(String[] args) {
List<String> list = Arrays.asList("hello", "world");
System.out.println(list);
}
}
泛型案例
编写Stack的基本操作泛型类,并使用学生的实体类进行测试
import java.lang.reflect.Array;
import java.util.ArrayList;
public class test {
public static void main(String[] args) {
allStack<String> strStack = new allStack<>();
allStack<Student> stuStack = new allStack<>();
strStack.push("字符串1");
strStack.push("字符串2");
System.out.println(strStack);
stuStack.push(new Student("学生1", 20));
stuStack.push(new Student("学生2", 21));
System.out.println(stuStack);
}
}
class Student{
private String name;
private int age;
public Student(String name, int age){
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class allStack<E>{
private ArrayList<E> list = new ArrayList<>();
public int getSize(){
return list.size();
}
public E peek(){
return list.get(getSize() - 1);
}
public void push(E o){
list.add(o);
}
public E pop(){
E o = list.get(getSize() - 1);
list.remove(getSize() - 1);
return o;
}
public boolean isEmpty(){
return list.isEmpty();
}
@Override
public String toString() {
return "stack: " + list.toString();
}
}

浙公网安备 33010602011771号