泛型的由来:通过Object转型问题引入
早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。(运行期)
也就存在这隐患,所以Java提供了泛型来解决这个安全问题。
泛型机制:将数据类型的明确工作推迟到,创建对象或者调用方法时才去明确的机制
泛型好处
(1):把运行时期的问题提前到了编译期间
(2):避免了向下转型
(3):优化了程序设计,解决了黄色警告线
注意:泛型只在编译期有效 但在运行期就擦除了。
package org.westos.demo;
import java.util.ArrayList;
/**
* @author lwj
* @date 2020/5/11 19:35
*/
public class MyTest {
public static void main(String[] args) {
//泛型机制:将数据类型的明确工作推迟到,创建对象或者调用方法时才去明确的机制
//泛型:参数化类型
//泛型可以定义在类、接口和方法上,<类型>,<类型,类型,...> 这些类型必须是引用类型
//泛型只在编译期有效,在运行期就会被擦除
//创建集合时使用泛型(没有使用泛型时,集合中可以存储多种引用类型,如果确实想要存储多种引用类型,可以把泛型设置为Object类型)
ArrayList<String> strings = new ArrayList<>();
//使用了泛型之后,集合中只能存储字符串类型
strings.add("aaa");
//strings.add(12);编译期报错
String s = strings.get(0);
//避免了向下转型,从Object类型转为String
System.out.println(s);
//aaa
}
}
ArrayList存储String类型并遍历泛型版
package org.westos.demo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.ListIterator;
/**
* @author lwj
* @date 2020/5/11 19:53
*/
public class MyTest2 {
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<>(Arrays.asList("aaa", "bbb", "ccc", "ddd"));
/*迭代器版本
ListIterator<String> iterator = strings.listIterator();
while (iterator.hasNext()) {
String next = iterator.next();
System.out.println(next);
}*/
//aaa
//bbb
//ccc
//ddd
/* 增强for */
/* 增强for用于遍历数组和Collection单列集合 */
for (String string : strings) {
System.out.println(string);
}
}
}
ArrayList存储自定义类型并遍历泛型版
package org.westos.demo;
import java.util.ArrayList;
/**
* @author lwj
* @date 2020/5/11 19:52
*/
public class MyDemo {
public static void main(String[] args) {
ArrayList<Student> students = new ArrayList<>();
students.add(new Student("张三", 11));
students.add(new Student("李四", 12));
students.add(new Student("王五", 13));
for (Student student : students) {
System.out.println(student);
}
//Student{name=‘张三‘, age=11}
//Student{name=‘李四‘, age=12}
//Student{name=‘王五‘, age=13}
}
}
定义格式:
public class 类名<泛型类型1,泛型类型2,…>
注意事项:
泛型的类型必须是引用类型。
package org.westos.demo2;
/**
* 设计一个泛型类
* @author lwj
* @date 2020/5/11 20:02
*/
public class MyClass<E> {
private E obj;
public E getObj() {
return obj;
}
public void setObj(E obj) {
this.obj = obj;
}
}
package org.westos.demo2;
/**
* @author lwj
* @date 2020/5/11 20:04
*/
public class MyTest {
public static void main(String[] args) {
MyClass<String> myClass = new MyClass<>();
myClass.setObj("aaa");
String obj = myClass.getObj();
//使用泛型避免了向下转型
System.out.println(obj);
//aaa
}
}
定义格式:
public interface 接口名<泛型类型1,泛型类型2,...>
package org.westos.demo2;
/**
* @author lwj
* @date 2020/5/11 20:09
*/
public interface MyInterface<E,T> {
boolean hasNext();
E next();
T show();
}
当使用匿名内部类实现泛型接口:
package org.westos.demo2;
/**
* @author lwj
* @date 2020/5/11 20:10
*/
public class MyDemo {
public static void main(String[] args) {
//使用匿名内部类
//在创建时传递泛型类型
MyInterface<Integer, String> myInterface = new MyInterface<Integer, String>() {
@Override
public boolean hasNext() {
return false;
}
@Override
public Integer next() {
return null;
}
@Override
public String show() {
return null;
}
};
}
}
当使用具体类实现泛型接口时:
package org.westos.demo2;
/**
* @author lwj
* @date 2020/5/11 20:17
*/
public class MyInterfaceImpl implements MyInterface<Integer, String> {
@Override
public boolean hasNext() {
return false;
}
@Override
public Integer next() {
return null;
}
@Override
public String show() {
return null;
}
}
class MyTest2 {
public static void main(String[] args) {
new MyInterfaceImpl();
}
}
当使用泛型类实现泛型接口时:
package org.westos.demo2;
import java.util.ArrayList;
/**
* @author lwj
* @date 2020/5/11 20:19
*/
public class MyInterfaceImpl2<E, T> implements MyInterface<E, T> {
@Override
public boolean hasNext() {
return false;
}
@Override
public E next() {
return null;
}
@Override
public T show() {
return null;
}
}
class MyDemo2 {
public static void main(String[] args) {
MyInterfaceImpl2<Integer, String> impl2 = new MyInterfaceImpl2<>();
//和ArrayList的创建方式一致,ArrayList是泛型类,实现List泛型接口
//public class ArrayList<E> extends AbstractList<E>
// implements List<E>, RandomAccess, Cloneable, java.io.Serializable
}
}
抽象类和普通类一样,可以使用泛型,可以本身使用泛型,也可以继承泛型接口,暂时不声明类型,等到最后创建对象时,和ArrayList一致,再声明类型。
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {}
public abstract class AbstractCollection<E> implements Collection<E> {}
定义格式:
public <泛型类型> 返回类型 方法名(泛型类型 变量名)
package org.westos.demo3;
/**
* @author lwj
* @date 2020/5/11 20:41
*/
public class MyClass {
/**
* 泛型方法:public <泛型类型> 返回值类型 方法名(泛型类型 参数名)
* @param t
* @param <T>
*/
public static <T> void show(T t) {
System.out.println(t.getClass().getName());
//java.lang.String
System.out.println(t);
//aaa
}
}
class Test {
public static void main(String[] args) {
MyClass.show("aaa");
}
}
泛型通配符:
<?>
任意类型,如果没有明确,那么就是Object以及任意的Java类。
<? extends E>
向下限定,E和E的子类
<? super E>
向上限定,E和E的父类
package org.westos.demo3;
import java.util.ArrayList;
/**
* @author lwj
* @date 2020/5/11 20:46
*/
public class MyTest {
public static void main(String[] args) {
ArrayList<?> objects = new ArrayList<Animal>();
//泛型通配符,代表任意类型
ArrayList<?> objects1 = new ArrayList<Object>();
//ArrayList<? extends Animal> list = new ArrayList<Object>();编译报错,不能存储Animal父类
ArrayList<? extends Animal> list = new ArrayList<Animal>();
ArrayList<? extends Animal> list1 = new ArrayList<Dog>();
ArrayList<? extends Animal> list2 = new ArrayList<Cat>();
ArrayList<? super Animal> list3 = new ArrayList<Animal>();
ArrayList<? super Animal> list4 = new ArrayList<Object>();
//ArrayList<? super Animal> list5 = new ArrayList<Dog>();编译报错,不能存储Animal的子类
}
}
class Animal {
}
class Dog extends Animal {
}
class Cat extends Animal {
}
泛型通配符的应用
package org.westos.demo3;
import java.util.ArrayList;
/**
* @author lwj
* @date 2020/5/11 20:56
*/
public class MyTest2 {
public static void main(String[] args) {
ArrayList<Integer> integers = new ArrayList<>();
ArrayList<Integer> integers1 = new ArrayList<>();
ArrayList<String> strings = new ArrayList<>();
integers.addAll(integers1);
//boolean addAll(Collection<? extends E> c)
//传递一个集合,元素是Integer类及其子类
//integers.addAll(strings);
//编译报错,required:Collection<? extends E> provided:ArrayList String
}
}
增强for用于简化数组和Collection单列集合的遍历。
定义格式:
for(元素数据类型 变量 : 数组或者Collection集合) {
使用变量即可,该变量就是元素
}
package org.westos.demo4;
import java.util.ArrayList;
import java.util.Arrays;
/**
* @author lwj
* @date 2020/5/11 21:02
*/
public class MyTest {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4};
for (int num : arr) {
System.out.println(num);
}
ArrayList<String> strings = new ArrayList<>(Arrays.asList("aaa", "bbb", "ccc"));
for (String string : strings) {
System.out.println(string);
}
}
}
快速生成增强for循环
数组名.for
集合名.for
增强for底层用的是迭代器遍历。
所以,在使用增强for遍历时,不能改变容器的长度。
如果在遍历过程中需要改变容器长度,则使用普通for循环,增强for只是简化遍历输出。
package org.westos.demo4;
import java.util.ArrayList;
import java.util.Arrays;
/**
* @author lwj
* @date 2020/5/11 21:09
*/
public class MyTest2 {
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<>();
strings.add("aaa");
strings.add("bbb");
strings.add("ccc");
strings.add("ddd");
System.out.println(strings);
for (String string : strings) {
if (string.equals("bbb")) {
strings.remove(string);
}
}
System.out.println(strings);
}
}
/*
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at org.westos.demo4.MyTest2.main(MyTest2.java:18)
*/
可变参数概述:定义方法的时候不知道该定义多少个参数。
定义格式:
修饰符 返回值类型 方法名(数据类型… 变量名){}
注意事项:
package org.westos.demo4;
/**
* @author lwj
* @date 2020/5/11 21:16
*/
public class MyDemo {
public static void main(String[] args) {
int add = add(true, 1, 2, 3, 4, 5);
System.out.println(add);
//15
}
private static int add(boolean flag, int... i) {
//如果方法有多个参数,那么可变参数必须放在最后一个
if (flag) {
int sum = 0;
for (int i1 : i) {
sum += i1;
}
return sum;
}
return 0;
}
}
将数组转换为集合,这个方法含有可变参数,并且是一个泛型方法。
获取到的这个集合长度是不能改变的,不能给这个集合中添加或者移除元素,只能获取元素。
package org.westos.demo4;
import java.util.ArrayList;
import java.util.Arrays;
/**
* @author lwj
* @date 2020/5/11 21:24
*/
public class MyDemo2 {
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<>(Arrays.asList("aaa", "bbb", "ccc"));
}
}
transient Object[] elementData;
//构造方法传入一个集合
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
//Object[] toArray()
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
package org.westos.demo4;
import org.westos.demo.Student;
import java.util.ArrayList;
/**
* @author lwj
* @date 2020/5/11 21:36
*/
public class Test {
public static void main(String[] args) {
ArrayList<Teenager> teenagers = new ArrayList<>();
teenagers.add(new Teenager("张三", 12, "六年级"));
teenagers.add(new Teenager("李四", 11, "六年级"));
ArrayList<Teenager> teenagers1 = new ArrayList<>();
teenagers1.add(new Teenager("王五", 9, "四年级"));
teenagers1.add(new Teenager("赵六", 8, "四年级"));
ArrayList<ArrayList<Teenager>> arrayLists = new ArrayList<>();
arrayLists.add(teenagers);
arrayLists.add(teenagers1);
for (ArrayList<Teenager> arrayList : arrayLists) {
for (Teenager teenager : arrayList) {
System.out.println(teenager);
}
}
//Teenager{grade=‘六年级‘} Student{name=‘张三‘, age=12}
//Teenager{grade=‘六年级‘} Student{name=‘李四‘, age=11}
//Teenager{grade=‘四年级‘} Student{name=‘王五‘, age=9}
//Teenager{grade=‘四年级‘} Student{name=‘赵六‘, age=8}
}
}
class Teenager extends Student {
private String grade;
public Teenager(String name, Integer age, String grade) {
super(name, age);
this.grade = grade;
}
@Override
public String toString() {
return "Teenager{" +
"grade=‘" + grade + ‘\‘‘ +
"} " + super.toString();
}
}
19、集合(泛型、泛型类、泛型接口、泛型方法、泛型高级之通配符、增强for、可变参数、Arrays数组工具类的asList(T... t)方法、ArrayList的嵌套)
原文:https://www.cnblogs.com/shawnyue-08/p/12872472.html