什么是泛型 所谓的泛型,就是允许在定义类,接口时通过一个标识表示类中某个属性的类型或者某个方法的返回值或者参数的类型。这个类型参数可以在使用时(例如:继承或者实现这个接口,用这个类型声明变量、创建对象时)确定(即传入实际的类型参数,也称为类型实参)。
泛型的概念是在 jdk5.0 之后提出来的概念。
使用泛型初体验 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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 package com.songzx.generic;import org.junit.Test;import java.util.*;public class Exer1 { @Test public void test1 () { ArrayList list = new ArrayList(); list.add(86 ); list.add(99 ); list.add(82 ); list.add(83 ); for (Object o : list) { int per = (Integer) o; System.out.println(per); } } @Test public void test2 () { ArrayList<Integer> integers = new ArrayList<Integer>(); integers.add(56 ); integers.add(99 ); integers.add(89 ); integers.add(96 ); for (Integer integer : integers) { int i = integer; System.out.println(i); } } @Test public void test3 () { HashMap<String, Integer> map = new HashMap<String, Integer>(); map.put("Tome" ,96 ); map.put("Jack" ,69 ); map.put("Jary" ,89 ); Set<Map.Entry<String, Integer>> entries = map.entrySet(); Iterator<Map.Entry<String, Integer>> iterator = entries.iterator(); while (iterator.hasNext()){ Map.Entry<String, Integer> next = iterator.next(); String key = next.getKey(); Integer value = next.getValue(); System.out.println(key + "------" + value); } } }
在 TreeSet 中使用泛型减少条件判断 首先定义 Employee
和 Mydate
类
Employee 类
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 34 35 36 package com.songzx.generic;public class Employee implements Comparable <Employee > { public String name; public int age; public MyDate brithday; public Employee (String name, int age, MyDate brithday) { this .name = name; this .age = age; this .brithday = brithday; } public MyDate getBrithday () { return brithday; } public void setBrithday (MyDate brithday) { this .brithday = brithday; } @Override public String toString () { return "Employee{" + "name='" + name + '\'' + ", age=" + age + ", brithday=" + brithday + '}' ; } @Override public int compareTo (Employee o) { return this .name.compareTo(o.name); } }
Mydate 类
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 34 35 36 37 38 39 40 41 42 package com.songzx.generic;import java.util.Objects;public class MyDate implements Comparable <MyDate > { public Integer year; public int month; public int day; public MyDate (int year, int month, int day) { this .year = year; this .month = month; this .day = day; } @Override public String toString () { return "MyDate{" + "year=" + year + ", month=" + month + ", day=" + day + '}' ; } @Override public boolean equals (Object o) { if (this == o) return true ; if (o == null || getClass() != o.getClass()) return false ; MyDate myDate = (MyDate) o; return year == myDate.year && month == myDate.month && day == myDate.day; } @Override public int hashCode () { return Objects.hash(year, month, day); } @Override public int compareTo (MyDate o) { return this .year.compareTo(o.year); } }
定义 TreeSet 类实行自然排序和定制排序
自然排序
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 package com.songzx.generic;import org.junit.Test;import java.util.Comparator;import java.util.TreeSet;public class Exer2 { @Test public void test1 () { TreeSet<Employee> empls = new TreeSet<>(); Employee tome = new Employee("tome" , 21 , new MyDate(2000 , 01 , 06 )); Employee anni = new Employee("anni" , 19 , new MyDate(1999 , 05 , 06 )); Employee mame = new Employee("mame" , 20 , new MyDate(2001 , 10 , 10 )); empls.add(tome); empls.add(anni); empls.add(mame); for (Employee empl : empls) { System.out.println(empl); } } }
定制排序
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 package com.songzx.generic;import org.junit.Test;import java.util.Comparator;import java.util.TreeSet;public class Exer2 { @Test public void test2 () { TreeSet<Employee> employees = new TreeSet<>(new Comparator<Employee>() { @Override public int compare (Employee o1, Employee o2) { return o1.getBrithday().compareTo(o2.getBrithday()); } }); Employee tome = new Employee("tome" , 21 , new MyDate(2000 , 01 , 06 )); Employee anni = new Employee("anni" , 19 , new MyDate(1999 , 05 , 06 )); Employee mame = new Employee("mame" , 20 , new MyDate(1998 , 10 , 10 )); employees.add(tome); employees.add(anni); employees.add(mame); for (Employee employee : employees) { System.out.println(employee); } } }
在集合中使用泛型总结
集合接口或者集合类在jdk5.0之后都修改为了带泛型的结构
在实例化集合时,可以指明具体的泛型类型
指明完泛型后,在定义类或接口时内部的数据类型就被确定了,不能再有其他类型的数据
泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置用包装类替代
如果实例化是没有指定泛型,则默认是 Object 类型
在 jdk7.0 之后,定义泛型时后面尖括号内的类型可以省略 ArrayList<Integer> integers = new ArrayList<>()
自定义泛型类 首先定义泛型时使用一对尖括号 <>
,常用一个大写字母表示泛型类型参数。常见的有 <E>,<T>,<K>,<V>
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 package com.songzx.generic;public class Exer3 { public static void main (String[] args) { Order<String> orders = new Order<>(); orders.setO("name" ); String o = orders.getO(); System.out.println(o); Order2 order2 = new Order2(); order2.setO(123 ); Integer o1 = order2.getO(); System.out.println(o1); Order3<Boolean> order3 = new Order3<>(); order3.setO(true ); Boolean o2 = order3.getO(); System.out.println(o2); } } class Order <E > { String name; E o; public Order () { this .name = name; this .o = o; } public E getO () { return o; } public void setO (E o) { this .o = o; } } class Order2 extends Order <Integer > {} class Order3 <E > extends Order <E > {}
自定义泛型方法
如果方法中使用了类中的泛型类型,则不能被定义成静态方法
如果方法中没有使用类中的泛型类型,则该类即使不是泛型类也可以定义成泛型方法
泛型方法可以是声明成静态的
定义泛型方法时要在 public
之后定义一个 表示这是一个泛型方法,如果不定义则认为这个 T
是一个自定义类
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 package com.songzx.generic;import org.junit.Test;import java.util.ArrayList;import java.util.List;public class Exer4 { @Test public void test1 () { Utils utils = new Utils(); Integer[] intarr = new Integer[]{15 ,65 ,32 }; List<Integer> integers = utils.copyArrToList(intarr); System.out.println(integers); } } class Utils { public Utils () { } public <T> List<T> copyArrToList (T[] arr) { ArrayList<T> ts = new ArrayList<>(); for (T t : arr) { ts.add(t); } return ts; } }
泛型类的使用场景 定义一个 DAO
类,将操作数据库的方法全部封装起来,这个类是泛型类,具体操作那个数据库由各个类去继承时确定
首先定义 DAO
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 34 35 36 package com.songzx.dao;import java.util.List;public class DAO <E > { public void addData (E e) { } public Boolean removeData (int index, E e) { return null ; } public Boolean UpdateData (int index, E e) { return null ; } public E getIndex (int index) { return null ; } public List<E> getAllData (int index) { return null ; } }
然后定义 Customer
类
1 2 3 4 5 package com.songzx.dao;public class Customer {}
接着定义 CustomerDAO
类,这个类要去继承 DAO 类
1 2 3 4 5 package com.songzx.dao;public class CustomerDAO extends DAO <Customer > {}
然后编写 DAOTEST
测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package com.songzx.dao;import java.util.List;public class DAOTEST { public static void main (String[] args) { Customer customer = new Customer(); CustomerDAO customerDAO = new CustomerDAO(); customerDAO.addData(customer); Boolean aBoolean = customerDAO.removeData(0 , customer); Boolean aBoolean1 = customerDAO.UpdateData(0 , customer); Customer cus = customerDAO.getIndex(0 ); List<Customer> allData = customerDAO.getAllData(0 ); } }
泛型继承和相互赋值 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 package com.songzx.generic;import org.junit.Test;import java.util.ArrayList;public class Exer5 { @Test public void test1 () { ArrayList<Integer> list1 = new ArrayList<>(); ArrayList<String> list2 = new ArrayList<>(); ArrayList<Integer> integers = new ArrayList<>(); ArrayList<Integer> integers1 = new ArrayList<>(); integers = integers1; integers.add(123 ); System.out.println(integers1); } }
通配符的使用 通配符使用英文的问号 ?
表示。不确定泛型类型是可以使用
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 34 package com.songzx.generic;import org.junit.Test;import java.util.ArrayList;import java.util.List;public class Exer6 { @Test public void test1 () { ArrayList<String> strings = new ArrayList<>(); ArrayList<Integer> integers = new ArrayList<>(); strings.add("tome" ); strings.add("jack" ); integers.add(123 ); integers.add(456 ); each(strings); each(integers); } public void each (List<?> list) { for (Object o : list) { System.out.println(o); } } }
使用通配符后数据的写入和读取操作
使用通配符赋值后,只能添加 null
值
使用通配符赋值后,读取的数据类型为 Object
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 package com.songzx.generic;import org.junit.Test;import java.awt.*;import java.util.ArrayList;import java.util.List;public class Exer7 { @Test public void test () { ArrayList<String> strings = new ArrayList<>(); strings.add("AA" ); strings.add("BB" ); ArrayList<Integer> integers = new ArrayList<>(); List<?> list = null ; list = strings; list.add(null ); Object o = list.get(0 ); System.out.println(o); } }
有限制条件的通配符使用
<? extends Supper>
该泛型类型只能是 Supper
或者 Supper
的子类。相当于 ? <= Supper
<? super Supper>
该泛型类型只能是 Supper
或者 Supper
的父类。相当于 ? >= Supper
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 package com.songzx.generic; import org.junit.Test;import java.util.ArrayList;import java.util.List;public class Exer8 { @Test public void test () { List<? extends Supper> list1 = new ArrayList<>(); List<? super Supper> list2 = new ArrayList<>(); List<Dog> dogs = new ArrayList<>(); dogs.add(new Dog()); List<Supper> suppers = new ArrayList<>(); suppers.add(new Supper()); List<Object> objects = new ArrayList<>(); objects.add("object" ); list1 = dogs; list1 = suppers; list2 = suppers; list2 = objects; Supper supper = list1.get(0 ); System.out.println(supper); Object object = list2.get(0 ); System.out.println(object); } } class Supper {}class Dog extends Supper {}
泛型练习题1 题目要求:
首先定义 DAO
类,在其内部声明内部变量 Map<String,T> map = new HashMap<>();
然后定义增删改查方法
save(String id,T entity)
update(String id,T entity)
T get(String id)
List<T> list()
delete(String id)
定义一个 User
类
private 成员变量 (int)id、age;(String)name
定义一个测试类,分别调用 DAO
类中的方法
定义 DAO
类
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 34 35 36 37 38 39 40 41 package com.songzx.Exer;import java.util.*;public class DAO <T > { 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> ts = new ArrayList<>(); Collection<T> values = map.values(); for (T value : values) { ts.add(value); } return ts; } public void delete (String id) { map.remove(id); } }
定义 User
类
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 package com.songzx.Exer;import java.util.Objects;public class User { private int id; private int age; String name; public int getId () { return id; } public void setId (int id) { this .id = id; } public int getAge () { return age; } public void setAge (int age) { this .age = age; } public String getName () { return name; } public void setName (String name) { this .name = 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 + '\'' + '}' ; } @Override public boolean equals (Object o) { if (this == o) return true ; if (o == null || getClass() != o.getClass()) return false ; User user = (User) o; return id == user.id && age == user.age && Objects.equals(name, user.name); } @Override public int hashCode () { return Objects.hash(id, age, name); } }
实现测试类
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 34 35 36 37 38 package com.songzx.Exer;import java.util.List;public class UserDao { public static void main (String[] args) { DAO<User> userDAO = new DAO<>(); User jack = new User(1 , 25 , "Jack" ); User Tome = new User(2 , 18 , "Tome" ); User Moma = new User(3 , 26 , "Moma" ); userDAO.save("a001" ,jack); userDAO.save("a002" ,Tome); userDAO.save("a003" ,Moma); User a002 = userDAO.get("a002" ); System.out.println(a002); userDAO.update("a002" ,new User(2 ,19 ,"Koam" )); User a0021 = userDAO.get("a002" ); System.out.println(a0021); List<User> list = userDAO.list(); System.out.println(list); userDAO.delete("a002" ); List<User> list2 = userDAO.list(); System.out.println(list2); } }
创建 File 类的实例 File 类的一个对象,代表一个文件或者方法。
三种构造方法:
构造方法1。 new File(String pathname)
构造方法2。 new File(String parent,String child)
构造方法3。 new File(File file,String child)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.songzx.File;import java.io.File;public class Exer1 { public static void main (String[] args) { File file = new File("hello.txt" ); File file1 = new File("D:\\students\\javascript" , "Promise.js" ); File file2 = new File(file1, "Ajax.js" ); System.out.println(file); System.out.println(file1); System.out.println(file2); } }
File 类常用方法1
String absolutePath = file.getAbsolutePath();
获取绝对路径
String path = file.getPath();
获取相对路径
String name = file.getName();
获取文件名称
String parent = file.getParent();
返回上层文件目录路径,若无返回null
long length = file.length();
获取文件的长度(即字节数),不能获取目录的长度
long l = file.lastModified();
获取最后一次修改时间
String[] list = d.list();
获取指定目录下的所有文件或者文件夹的名称数组
File[] files = d.listFiles();
获取指定目录下的所有文件或者文件夹的File数组
boolean b = file.renameTo(file1);
将一个文件重命名并移动到一个新的目录中
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 package com.songzx.File;import org.junit.Test;import java.io.File;import java.text.SimpleDateFormat;import java.util.Date;public class Exer2 { @Test public void test1 () { File file = new File("hello.txt" ); String absolutePath = file.getAbsolutePath(); System.out.println(absolutePath); String path = file.getPath(); System.out.println(path); String name = file.getName(); System.out.println(name); String parent = file.getParent(); System.out.println(parent); long length = file.length(); System.out.println(length); long l = file.lastModified(); Date date = new Date(l); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-DD HH:mm:ss" ); System.out.println(simpleDateFormat.format(date)); } @Test public void test2 () { File d = new File("D:\\mygitee\\学习Java\\java" ); String[] list = d.list(); for (String s : list) { System.out.println(s); } File[] files = d.listFiles(); for (File file : files) { System.out.println(file); } } @Test public void test3 () { File file = new File("D:\\mygitee\\学习Java\\java\\14泛型和File\\copyhello.txt" ); File file1 = new File("D:\\mygitee\\学习Java\\java\\14泛型和File\\src\\hello.txt" ); boolean b = file.renameTo(file1); System.out.println(b); } }
File 类常用方法2
boolean directory = file.isDirectory();
判断是否是文件目录
boolean isfile = file.isFile();
判断是否是文件
boolean exists = file.exists();
判断是否存在
boolean isread = file.canRead();
判断是否可读取
boolean b = file.canWrite();
判断是否可写
boolean hidden = file.isHidden();
判断是否隐藏
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 34 35 36 package com.songzx.File;import org.junit.Test;import java.io.File;public class Exer3 { @Test public void test1 () { File file = new File("hello.txt" ); boolean directory = file.isDirectory(); System.out.println(directory); boolean isfile = file.isFile(); System.out.println(isfile); boolean exists = file.exists(); System.out.println(exists); boolean isread = file.canRead(); System.out.println(isread); boolean b = file.canWrite(); System.out.println(b); boolean hidden = file.isHidden(); System.out.println(hidden); } }
文件的创建和删除
boolean newFile = file.createNewFile();
创建文件,如果文件没有声明盘符或者路径,则默认在当前项目路径下新建文件
boolean delete = file.delete();
删除文件
boolean mkdir = file.mkdir();
创建文件夹,如果上一层目录不存在,则创建失败
boolean mkdirs = file1.mkdirs();
创建文件夹,如果上一级目录不存在,也会创建成功,自动创建上一层目录
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 package com.songzx.File;import org.junit.Test;import java.io.File;import java.io.IOException;public class Exer4 { @Test public void test () { File file = new File("newhello.txt" ); if (file.exists()){ boolean delete = file.delete(); if (delete){ System.out.println("删除成功" ); }else { System.out.println("删除失败" ); } }else { try { boolean newFile = file.createNewFile(); if (newFile){ System.out.println("创建成功" ); }else { System.out.println("删除失败" ); } } catch (IOException e) { e.printStackTrace(); } } } @Test public void test2 () { File file = new File("D:\\mygitee\\学习Java\\java\\IO" ); boolean mkdir = file.mkdir(); System.out.println(mkdir); File file1 = new File("D:\\mygitee\\学习Java\\java\\IO2\\Test" ); boolean mkdirs = file1.mkdirs(); System.out.println(mkdirs); } }
递归删除文件夹下的文件和当前文件夹 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 package com.songzx.File;import java.io.File;public class Exer6 { public static void main (String[] args) { File file = new File("D:\\mygitee\\学习Java\\java\\IO" ); Exer6.deleteFile(file); } static void deleteFile (File file) { if (file.isDirectory()){ File[] files = file.listFiles(); for (File file1 : files) { deleteFile(file1); } } file.delete(); } }
练习题:
遍历Map的key集和value集合key-value集合,要求使用泛型
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 34 35 36 37 38 39 40 41 package com.songzx.Topic;import java.util.Collection;import java.util.HashMap;import java.util.Map;import java.util.Set;public class Exer1 { public static void main (String[] args) { HashMap<String, Integer> map = new HashMap<>(); map.put("tome" ,56 ); map.put("tac" ,56 ); map.put("jack" ,23 ); Set<String> keys = map.keySet(); for (String key : keys) { System.out.println(key); } Collection<Integer> values = map.values(); for (Integer value : values) { System.out.println(value); } Set<Map.Entry<String, Integer>> entries = map.entrySet(); for (Map.Entry<String, Integer> entry : entries) { String key = entry.getKey(); Integer value = entry.getValue(); System.out.println(key + "-->" + value); } } }
使用 Iterator
和增强 for
遍历 List<String>
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 package com.songzx.Topic;import java.util.ArrayList;import java.util.Iterator;import java.util.List;public class Exer2 { public static void main (String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("aa" ); list.add("bb" ); list.add("cc" ); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()){ String next = iterator.next(); System.out.println(next); } for (String s : list) { System.out.println(s); } } }
创建一个返回 Map
中所有 value
组成的 list
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.songzx.Topic;import java.util.*;public class Exer3 { public static void main (String[] args) { HashMap<String, String> map = new HashMap<>(); map.put("age" ,"13" ); map.put("name" ,"23" ); List mapAllValus = Exer3.getMapAllValus(map); System.out.println(mapAllValus); } static List<String> getMapAllValus (HashMap<String,String> map) { Collection<String> values = map.values(); ArrayList<String> strlist = new ArrayList<>(); for (String value : values) { strlist.add(value); } return strlist; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.songzx.Topic;import java.io.File;import java.io.IOException;public class Exer4 { public static void main (String[] args) throws IOException { File file = new File("b.txt" ); file.createNewFile(); } }