Java泛型
Java泛型


每日一考
- 如何遍历Map的key类,value类,key-value类,使用泛型
Map<String,Integer> map = new HashMap<String,Integer>();
map.put();..
//遍历key
Set<String> keySet = map.keySet();
for(String key:keySet)
{
sout(key);
}
//遍历value
Collection<Integer> values = map.values()l
Iterator<Integer> iterator = values.iterator();
while(iterator.hasNext()){
sout(iterator.next());
}
//遍历key-value
//Set的泛型是Map.Entry
//entry的泛型是<String,Integer>
Set<Map.Entry<String,Integer>> set = map.entrySet();
Iterator<Map.Entry<String,Integer>> it = set.iterator<Map.Entry<String,Integer>>();
while(it.hasNext()){
Map.Entry entry = it.next();
String key = entry.getKey();
Integer value = entry.getValue();
}
- 创建一个与a.txt文件同目录下的另外一个文件b.txt
File f1 = new File("d:\\a\\a.txt");
File f2 = new File(file1.getParent(),"b.txt");
- Map接口中的常用方法
增:put(K k,V v)
删:V remove(K k)
改:put(K k,V v)
查:V get(K k)
长度:int size()
遍历:
复习
泛型的理解
- 泛型的概念
- 所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类 型或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如, 继承或实现这个接口,用这个类型声明变量、创建对象时)确定(即传入实 际的类型参数,也称为类型实参)
- 泛型的引入
泛型在集合中的使用

public class GenericTest {
@Test
public void test1(){
ArrayList list = new ArrayList();
list.add(12);
list.add(99);
//问题一:类型不安全
list.add("Tom");
for(Object item:list){
//Object-强转-》Integer-自动装箱-》int
//java.lang.String cannot be cast to java.lang.Integer
int score = (Integer) item;
System.out.println(score);
}
}

//集合中使用泛型的情况,以HashMap为例
@Test
public void test3(){
HashMap<String,Integer> map = new HashMap<String,Integer>();
map.put("Tom",12);
map.put("pp",90);
// map.entrySet();
//泛型的嵌套 Set<E> Map.Entry<K,E>
Set<Map.Entry<String,Integer>> entry = map.entrySet();
Iterator<Map.Entry<String,Integer>> it= entry.iterator();
while(it.hasNext()){
Map.Entry<String,Integer> e = it.next();
System.out.println(e.getKey()+"->"+e.getValue());
}
}
- 集合中使用泛型总结
/**
* 泛型的使用
* 1. jdk5.0新增的特性
* 2. 在集合中使用泛型
* 总结:
* ①集合接口或者集合类在jdk5.0时都修改为带泛型的结构
* ②在实例化集合类时,可以指明具体的泛型类型
* ③指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如方法,构造器,属性)只用到类的泛型的位置,都指定为实例化的泛型类型.
* 比如add(E e) --> 实例化以后:add(Integer e)
* ④ 注意点:泛型的类型必须是类,不能是基本数据类型,需要用到基本数据类型的位置,都用包装类.
* ⑤如果实例化时,没有指明泛型的类型,默认类型为java.lang.Object
* 3. 如何自定义范型结:泛型类,泛型接口;泛型方法。见GenericTest1
* @author shc
* @create 2021-06-02 14:30
*/
自定义泛型类
/**
* 自定义的泛型类
* 1.
* @author shc
* @create 2021-06-02 18:22
*/
public class Order <T>{
String name;
int id;
//类的内部结构可以使用类的泛型
T ordert;
public void method(){
//编译不通过
//new的话得是一个类,T在这里是一个参数而非类
// T[] arr = new T[10];
//编译通过.但要注意传入的Object[0,1,2,3...]都必须是T类型的
T[] arr = (T[])new Object[10];
}
public Order(){}
//如下三个方法都不是泛型方法
public Order(String name,int id,T ordert){
this.name = name;
this.id = id;
this.ordert = ordert;
}
public T getOrdert(){
return this.ordert;
}
public void setOrdert(T ordert){
this.ordert = ordert;
}
//静态方法中给不能使用泛型,因为泛型是在实例化对象时才确定的。不属于类
// public static void f(T ordert){
// ordert = null;
// }
//泛型方法:在方法中,出现了泛型的结构,泛型参数与类的泛型参数没有任何关系
//换句话说,泛型方法所属的类是不是泛型都没关系
//public后面有个<E>是为了告诉编译器,E不是一个类,而是一个泛型参数
//泛型方法可以声明为static的。原因:泛型参数是在调用方法时确定的,并非在实例化时确定的。
public static <E> List<E> copyFromArrayToList(E[] arr){
ArrayList<E> list = new ArrayList<E>();
for(E item:arr){
list.add(item);
}
return list;
// list = (ArrayList<E>) Arrays.asList(arr);
}
}
//SubOrder是一个普通类,不再是一个泛型类
public class SubOrder extends Order<Integer>{
}
//实例化时,如下代码是错误的
SubOrder<Integer> o = new SubOrder<>();
//SubOrder1仍然是一个泛型类public class Suborder1<T> extends Order<T>{}
/** * 如何自定义范型结构、泛型类、泛型接口、泛型方法 * 1. 关于自定义泛型类,泛型接口 * * @author shc * @create 2021-06-02 18:25 */public class GenericTest1 { @Test public void test1(){ //如果定义了泛型类,实例化没有指明类的泛型。则认为此泛型类型为Object类. //要求:如果大家定义了类是带泛型的,建议在实例化时要指明类的泛型 Order order = new Order(); order.setOrdert(123); order.setOrdert("ABC"); System.out.println(order.ordert); //建议:实例化时,指明类的泛型 Order<String> order1 = new Order<String>("hh",45,"cnm"); order1.setOrdert("AA:Bye"); } @Test public void test2(){ SubOrder sub1 = new SubOrder(); //由于子类在继承带泛型的父类时,指明了泛型类型。则实例化子类对象时,不再需要指明泛型 sub1.setOrdert(45); //泛型类Suborder1 Suborder1<String> sub2 = new Suborder1<String>(); sub2.setOrdert("AAAA"); } //测试泛型方法 @Test public void test3(){ Order<String> order = new Order<String>(); Integer[] arr = new Integer[]{1,2,3,4}; List<Integer> list = order.copyFromArrayToList(arr); System.out.println(list); }}

- 应用场景
- ORM思想:Java中的一个类对应于数据库中的一个表
public class Customer {}
//专门用于操作Customer表public class CustomerDAO extends DAO<Customer>{}
package com.shc.java2;import java.util.List;/** * DAO:data(base) access object * 操作数据库的通用操作 * @author shc * @create 2021-06-02 19:26 */public class DAO <T>{ //添加一条记录 public void add(T t){ } //删除一条记录 public boolean reomve(int idx){ return false; } //修改一条记录 public void update(int idx,T t){ } //查询一条记录 public T getT(int idx){return null;} //查询多条记录 public List<T> getForList(int idx){ return null; } //泛型方法: public <E> E getValue(){ return null; }}
public class DAOTest { @Test public void test1(){ CustomerDAO dao1 = new CustomerDAO(); dao1.add(new Customer()); List<Customer> list = dao1.getForList(10); }}
泛型&继承
/* 1. 泛型在继承方面的体现 类A是类B的父类,G<A> 和 G<B> 不具备子父类关系。二者并列关系 补充:类A是类B的父类,A<G>是B<G>的父类 */ @Test public void test1(){ List<Object> list1 = null; List<String> list2 = null;// list2 = list1; list1和list2不具有子父类关系 //如果构成了子父类关系,则意味着list1可以管理list2,那么list2本来add("string"),但是list1优惠让他可以add(123)。(Object嘛)所以不可以 } //show1和show2不能相互替代,且不能构成重载 public void show1(List<String> l){ } public void show2(List<Object> l){ }
通配符
/* 2. 通配符的使用 通配符:? 类A是类B的父类,G<A>和G<B>是没有关系的。二者共同的父类时:G<?> */ @Test public void test2(){ List<Object> l1 = null; List<String> l2 = null; List<?> l = null; l = l1; l = l2; //编译通过,但是由于我们没有初始化l1,l2 所以运行时会有NullPointerException// print(l1);// print(l2); } public static void print(List<?> list){ Iterator it = list.iterator(); while(it.hasNext()){ Object obj = it.next(); System.out.println(obj);// System.out.println(it.next()); } } @Test public void test3(){ List<String> l = new ArrayList<String>(); l.add("aa"); l.add("bb"); List<?> l1 = null; l1 = l; //添加(写入):对于List<?>就不能向其内部添加数据 //除了添加null之外// l1.add("11"); //获取(读取): Object obj = l1.get(0); System.out.println(obj); }
/* 3. 有限制条件的通配符的使用 ? extends A: G<? extends A> 可以作为G<A>和G<B>的父类的,即?是A的子类或A本身 ? super A: G<? super A> 可以作为G<A>和G<B>的父类的,即?是A的父类或A本身 */ @Test public void test4(){ //extends <= //super >= List<? extends Person> l1 = null; List<? super Person> l2 = null; List<Student> l3 = new ArrayList<Student>(); List<Person> l4 = new ArrayList<Person>(); List<Object> l5 = new ArrayList<Object>(); l1 = l3; l1 = l4;// l1 = l5;// l2 = l3; l2 = l4; l2 = l5; //读取数据 l1 = l3; Person p = l1.get(0); //编译不通过 l2 = l4;// Person p = l2.get(0); //写入数据: //编译不通过 因为?代表的可能是比Student还小的类或者和其并列的类// l1.add(new Student()); //ok:?代表的至少是比Person大的类 所以一定可以加入<=Person的类 l2.add(new Person()); l2.add(new Student()); }
File
- File类的理解
/** * File类的使用 * 1. File类的一个对象,代表一个文件或者一个文件目录(俗称:文件夹) * 2. File类声明在java.io包下 * 3. File类中涉及到关于文件或者文件目录的创建、删除、重命名、修改时间、文件大小等方法 * 并未涉及到写入或者读取文件内容的操作,如果需要读取或写入文件内容,必须使用IO流来完成 * 4. 后续File类的对象常会作为参数传递到流的constructor中,指明读取或者写入的“终点” * @author shc * @create 2021-06-03 12:05 */
- File类的实例化
/* 1. 如何创建File类的实例 File(String filePath) File(String parentPath,String childPath) File(File parentFile,String child) 2. 相对路径:相较于某个路径下,指明的路径 绝对路径:包含在盘符在内的文件或文件目录的路径3. 路径分隔符windows:\\unix:/ */ @Test public void test1(){ //构造器1 现在还只是内存层面的对象,并没有在硬盘中造一个文件 File file1 = new File("hello.txt"); //相对路径:相较于当前Module(在当前Module下有一个hello.txt) File file2 = new File("C:\\Users\\de'l'l\\IdeaProjects\\workspace_idea1\\day08");//绝对路径 System.out.println(file1); System.out.println(file2); //构造器2 File file3 = new File("C:\\Users\\de'l'l\\IdeaProjects","workspace_idea1");//文件目录 System.out.println(file3); //构造器3 File file4 = new File(file3,"hh.txt"); System.out.println(file4); }
-
IDEA相对路径
- Junit的单元测试方法里:相较于Module(因为每个Module都要新引入Junit)
- main方法里:相较于当前工程下
-
Eclipse:无论是单元测试方法还是main(),相对路径都是在当前Module下。



- -子类和父类的同名方法,要么都是static,要么都不是static

浙公网安备 33010602011771号