编译时,检查添加元素的类型,提高安全性。减少了类型转换的次数,提高效率。不在提示编译警告..起到约束类型的作用
一、泛型
@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>(); //只能添加String类型的数据
Person<String> person = new Person<>("你好");
person.show();
new Person<Integer>("你好");//报错因为指定的时int传入的是字符串
}
}
class Person<E>{
E s;//E 表示 s数据类型,该数据类型在定义Person对象时候指定,及编译期间,就确定E是什么类型
public Person(E s){//E也是参照类型
this.s = s;
}
public E f(){ //返回值用E
return s;
}
public void show(){
System.out.println(s.getClass()); //获取运行类型
}
}
(1)案例:
1.创建3个学生对象 2. 放入到HashSetr,促用I3.放入到 HashMap中,要求 Key是 String name, Value就是学生对象 4 .使用两种方式遍历
@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
public static void main(String[] args) {
Map<String, Student> map = new HashMap<>();
map.put("zs", new Student("张三", 19));
map.put("ls", new Student("李四", 29));
map.put("ww", new Student("王五", 39));
System.out.println("==========第一种=========");
Set<String> keySet = map.keySet();
for (String key : keySet) {
System.out.println(key + " ================> " + map.get(key));
}
System.out.println("==========第二种=========");
Set<Map.Entry<String, Student>> entrySet = map.entrySet();
for (Object o : entrySet) {
Map.Entry<String, Student> entry = (Map.Entry<String, Student>) o;
System.out.println(entry.getKey() + " ================> " + entry.getValue());
}
}
}
class Student {
public String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "姓名: " + name + " 年龄: " + age;
}
}
(2)注意事项:
- interface List<T>{} , public class HashSet<E>{}...等等。说明:T,E只能是引用类型
- 给泛型指定具体类型后,可以传入该类型或者子类类型
- 开发中我们简写方式推荐写法 Map<String, Student> map = new HashMap<>(); 类型推断
- List list = new ArrayList() 这样写默认添加的是Object
(3)案例:
@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
public static void main(String[] args) {
ArrayList<Employee> arrayList = new ArrayList<>();
arrayList.add(new Employee("张三", 1000, new MyDate(10, 10, 10)));
arrayList.add(new Employee("李四", 3000, new MyDate(1, 12, 19)));
arrayList.add(new Employee("王五", 2000, new MyDate(3, 11, 10)));
//排序按工资升序
arrayList.sort(new Comparator<Employee>() {
@Override
public int compare(Employee o1, Employee o2) {
return (int) (o1.getSal() - o2.getSal());
}
});
for (Employee employee : arrayList){
System.out.println(employee);
}
}
}
class Employee {
private String name;
private double sal;
private MyDate birthday;
public Employee(String name, double sal, MyDate birthday) {
this.name = name;
this.sal = sal;
this.birthday = birthday;
}
public double getSal() {
return sal;
}
@Override
public String toString() {
return "姓名:" + name + " 工资:" + sal + " 生日:" + birthday;
}
}
class MyDate {
private int year;
private int month;
private int day;
public MyDate(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
@Override
public String toString() {
return year + "年" + month + "月" + day + "日";
}
}
二、自定义泛型类
@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
public static void main(String[] args) {
Tiger<String, Double, Integer> jhon = new Tiger("Jhon", 123, 1,123);
}
}
//1.Tiger 后面泛型,所以我们把Tiger称为自定义泛型类
//2.T,R,M 泛型的标识符,一般是单个大写字母
//3.泛型标识符可以有多个
//4.普通成员可以使用泛型
//5.使用泛型不能初始化泛型
//6.静态方法不能使用泛型 因为静态的在类加载的时候创建,泛型在实例创建完才知道
class Tiger<T,R,M>{
String name;
T t;
R r;
M m;
public Tiger(String name, T t, R r, M m) {
this.name = name;
this.t = t;
this.r = r;
this.m = m;
}
}
三、自定义接口泛型
@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
public static void main(String[] args) {}
}
//1.接口中,静态成员也不能使用泛型(这个和泛型类的规定一样)
//2.泛型接口的类型,在继承接口或实现接口时确定
//3.没有指定类型,默认为Object
interface IUsb<U,R>{
int n = 10;
// U name; 报错
R get(U u);
void h1(R r);
default R method(U u){
return null;
}
}
//继承接口的时候指定泛型的类型
interface IA extends IUsb<String,Integer>{}
class A implements IUsb<String,String>{
@Override
public String get(String s) {
return null;
}
@Override
public void h1(String s) {
}
}
class Dog implements IA{
@Override
public Integer get(String s) {
return null;
}
@Override
public void h1(Integer integer) {
}
}
四、自定义泛型方法
@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
public static void main(String[] args) {
Car car = new Car();
car.fly("123",123);
System.out.println("第二组");
car.fly(123,123);
}
}
//泛型方法,可以定义在普通类中,也可以定义在泛型类中
class Car{//普通类
public void run(){} //普通方法
public <T,R> void fly(T t,R r){ //泛型方法
System.out.println(t.getClass());
System.out.println(r.getClass());
}
}
class Fish<T,R>{//泛型类
public void run(){}//普通方法
public <U,M> void eat(U u , M m){} //泛型方法
public void hi(T t){} //这不是泛型方法
}
(1)案例:
五、泛型继承和通配
@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
public static void main(String[] args) {
Object o = new String("xx");
//泛型没有继承性
// List<Object> list = new ArrayList<String>();
//举例说明下面三个方法的使用
List<Object> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
List<AA> list3 = new ArrayList<>();
List<BB> list4 = new ArrayList<>();
List<CC> list5 = new ArrayList<>();
//如果是List<?>可以接受任意泛型类型
print1(list1);
print1(list2);
print1(list3);
print1(list4);
print1(list5);
//如果是List<? extends AA> 可以接收AA或者AA的子类
//print2(list1); //x
//print2(list2); //x
print2(list3); //v
print2(list4); //v
print2(list5); //v
//如果是List<? super AA> 可以接收AA或者AA的父类,不一定是直接父类
print3(list1); //v
//print3(list2); //x
print3(list3); //v
//print3(list4); //x
//print3(list5); //x
}
//List<?> 表示任意泛型类型都可以接受
public static void print1(List<?> c){
for (Object o :c) {
System.out.println(o);
}
}
//? extends AA 表示上限 可以接受 AA或者AA的子类
public static void print2(List<? extends AA> c){
for (Object o :c) {
System.out.println(o);
}
}
//? super 子类类名AA支持AA类或者AA类的父类,不限于直接父类
public static void print3(List<? super AA> c){
for (Object o :c) {
System.out.println(o);
}
}
}
class AA{}
class BB extends AA{}
class CC extends BB{}
@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
public static void main(String[] args) {
DAO<User> userDAO = new DAO<>();
//save方法
userDAO.save("zs", new User(1, 19, "张三"));
userDAO.save("ls", new User(2, 20, "李四"));
userDAO.save("ww", new User(3, 21, "王五"));
//get
System.out.println("get返回的值" + userDAO.get("zs"));
//update 更新张三的年龄为30岁
userDAO.update("zs", new User(1, 30, "张三"));
//删除王五
userDAO.delete("ww");
//获取所有对象
System.out.println(userDAO.list());
ArrayList<User> list = (ArrayList<User>) userDAO.list();
System.out.println("======遍历所有对象======");
for (User user : list) {
System.out.println(user);
}
}
}
class DAO<T> {
private final Map<String, T> map = new HashMap<>();
public void save(String id, T entity) {
map.put(id, entity);
}
public T get(String id) {
return map.get(id);
}
public void update(String id, T entity) {
map.put(id, entity);
}
public List<T> list() {
ArrayList<T> list = new ArrayList<>();
list.addAll(map.values());
return list;
}
public void delete(String id) {
map.remove(id);
}
}
class User {
private int id;
private int age;
private String name;
public User(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
六、JUnit测试框架
1.使用junit5.4,可以快速测试某个方法
import org.junit.jupiter.api.Test;
public class Hello {
public static void main(String[] args) {
//传统的太麻烦了
// new Hello().m1();
// new Hello().m2();
}
@Test
public void m1(){
System.out.println("m1被调用");
}
@Test
public void m2(){
System.out.println("m2被调用");
}
}