Java重温

(一)泛型(上) 1)No泛型

public class NeedGeneric1 { private static int add(int a, int b) { System.out.println(a + "+" + b + "=" + (a + b)); return a + b; }private static float add(float a, float b) { System.out.println(a + "+" + b + "=" + (a + b)); return a + b; }private static double add(double a, double b) { System.out.println(a + "+" + b + "=" + (a + b)); return a + b; }private static double add(T a, T b) { System.out.println(a + "+" + b + "=" + (a.doubleValue() + b.doubleValue())); return a.doubleValue() + b.doubleValue(); }public static void main(String[] args) { NeedGeneric1.add(1, 2); NeedGeneric1.add(1f, 2f); NeedGeneric1.add(1d, 2d); NeedGeneric1.add(Integer.valueOf(1), Integer.valueOf(2)); NeedGeneric1.add(Float.valueOf(1), Float.valueOf(2)); NeedGeneric1.add(Double.valueOf(1), Double.valueOf(2)); } }

我们不难发现,同一个add方法,我们需要写要几个不同参数形式的方法去适配所有的情况,这无疑是十分不方便的。
2)Have泛型
package com.jay.java.泛型.DefineGeneric; public class GenericClass { private T data; public T getData() { return data; }public void setData(T data) { this.data = https://www.it610.com/article/data; }public static void main(String[] args) { GenericClass> genericClass=new GenericClass<>(); genericClass.setData("Generic Class"); System.out.println(genericClass.getData()); } }

3)泛型的意义
  1. 适用于多种数据类型执行相同的代码(代码复用)
  2. 泛型中的类型在使用时指定,不需要强制类型转换(类型安全,编译器会检查类型)
4)视频部分代码 泛型Car
package lys.genericityup.Bean; public class Car { private T car; public Car(T car){ this.car = car; }public T getObject() { return this.car; } }

测试方法
package lys.genericityup.test; import lys.genericityup.Bean.Car; import org.junit.Test; import java.util.Date; public class TestMain {@Test public void testCar(){ Car> car = new Car<>("Bus"); System.out.println(car.getObject()); Car car2 = new Car(new Date()); System.out.println(car2.getObject()); } }

(二)泛型(下) 1) 泛型的继承规则
  1. 对于泛型参数是继承关系的泛型类之间是没有继承关系的
  2. 泛型类可以继承其它泛型类,例如: public class Car extends Vehicle
  3. 泛型类的继承关系在使用中同样会受到泛型类型的影响
2)视频中部分代码 Car类
package lys.genericitydown.bean; public class Car extends Vehicle{public Car(T name) { super(name); } }

Vehicle类
package lys.genericitydown.bean; public class Vehicle { private T name; public Vehicle(T name) { this.name = name; }@Override public String toString() { return "Vehicle{" + "name=" + name + '}'; } }

Test类
package lys.genericitydown.test; import lys.genericitydown.bean.Car; import org.junit.Test; import javax.xml.crypto.Data; import java.util.Date; public class TestMain { @Test public void test01(){ System.out.println(new Car>("BMW").toString()); }}

3) 泛型的通配符问题
  1. 指定了泛型类型的上级
  2. 指定了泛型类型的下级
  3. 指定了没有限制的泛型类型
Java重温
文章图片

4)参考代码
public class GenericByWildcard { private static void print(GenericClass fruitGenericClass) { System.out.println(fruitGenericClass.getData().getColor()); }private static void use() { GenericClass fruitGenericClass = new GenericClass<>(); print(fruitGenericClass); GenericClass orangeGenericClass = new GenericClass<>(); //类型不匹配,可以使用 来解决 //print(orangeGenericClass); }/** * 指定了泛型类型的上届 */ private static void printExtends(GenericClass genericClass) { System.out.println(genericClass.getData().getColor()); }public static void useExtend() { GenericClass fruitGenericClass = new GenericClass<>(); printExtends(fruitGenericClass); GenericClass orangeGenericClass = new GenericClass<>(); printExtends(orangeGenericClass); GenericClass foodGenericClass = new GenericClass<>(); //Food是Fruit的父类,超过了泛型上届范围,类型不匹配 //printExtends(foodGenericClass); //表示GenericClass的类型参数的上届是Fruit GenericClass extendFruitGenericClass = new GenericClass<>(); Apple apple = new Apple(); Fruit fruit = new Fruit(); /* * 道理很简单,? extends X表示类型的上界,类型参数是X的子类,那么可以肯定的说, * get方法返回的一定是个X(不管是X或者X的子类)编译器是可以确定知道的。 * 但是set方法只知道传入的是个X,至于具体是X的那个子类,不知道。 * 总结:主要用于安全地访问数据,可以访问X及其子类型,并且不能写入非null的数据。 */ //extendFruitGenericClass.setData(apple); //extendFruitGenericClass.setData(fruit); fruit = extendFruitGenericClass.getData(); }/** * 指定了泛型类型的下届 */ public static void printSuper(GenericClass genericClass) { System.out.println(genericClass.getData()); }public static void useSuper() { GenericClass foodGenericClass = new GenericClass<>(); printSuper(foodGenericClass); GenericClass fruitGenericClass = new GenericClass<>(); printSuper(fruitGenericClass); GenericClass appleGenericClass = new GenericClass<>(); printSuper(appleGenericClass); GenericClass hongFuShiAppleGenericClass = new GenericClass<>(); // HongFuShiApple 是Apple的子类,达不到泛型下届,类型不匹配 //printSuper(hongFuShiAppleGenericClass); GenericClass orangeGenericClass = new GenericClass<>(); // Orange和Apple是兄弟关系,没有继承关系,类型不匹配 //printSuper(orangeGenericClass); //表示GenericClass的类型参数的下界是Apple GenericClass supperAppleGenericClass = new GenericClass<>(); supperAppleGenericClass.setData(new Apple()); supperAppleGenericClass.setData(new HongFuShiApple()); /* * ? superX表示类型的下界,类型参数是X的超类(包括X本身), * 那么可以肯定的说,get方法返回的一定是个X的超类,那么到底是哪个超类?不知道, * 但是可以肯定的说,Object一定是它的超类,所以get方法返回Object。 * 编译器是可以确定知道的。对于set方法来说,编译器不知道它需要的确切类型,但是X和X的子类可以安全的转型为X。 * 总结:主要用于安全地写入数据,可以写入X及其子类型。 */ //supperAppleGenericClass.setData(new Fruit()); //get方法只会返回一个Object类型的值。 Object data = https://www.it610.com/article/supperAppleGenericClass.getData(); }/** * 指定了没有限定的通配符 */ public static void printNonLimit(GenericClass genericClass) { System.out.println(genericClass.getData()); }public static void useNonLimit() { GenericClass foodGenericClass = new GenericClass<>(); printNonLimit(foodGenericClass); GenericClass fruitGenericClass = new GenericClass<>(); printNonLimit(fruitGenericClass); GenericClass appleGenericClass = new GenericClass<>(); printNonLimit(appleGenericClass); GenericClass genericClass = new GenericClass<>(); //setData 方法不能被调用, 甚至不能用 Object 调用; //genericClass.setData(foodGenericClass); //genericClass.setData(new Object()); //返回值只能赋给 Object Object object = genericClass.getData(); }}

5)泛型中的约束和局限性
  1. 不能实例化泛型类
  2. 静态变量或方法不能引用泛型类型变量,但是静态泛型方法是可以的
  3. 基本类型无法作为泛型类型
  4. 无法使用 instanceof 关键字或==判断泛型类的类型
  5. 泛型类的原生类型与所传递的泛型无关,无论传递什么类型,原生类是一样的
  6. 泛型数组可以声明但无法实例化
  7. 泛型类不能继承Exception或者Throwable
  8. 不能捕获泛型类型限定的异常但可以将泛型限定的异常抛出
(三) Collection
1)List
@org.junit.Test public void test01(){ List list = new ArrayList(); list.add(10); list.add("hello"); list.add(true); list.add(99.9f); /* 第一种遍历方法 */ for (Object o : list) { System.out.println(o); } /* 第二中遍历方法 */ Iterator iterator = list.iterator(); while (iterator.hasNext()){ Object next = iterator.next(); System.out.println(next); } }

2)HashSet 【Java重温】HashSet中没有重复的元素,可以用于去重
@org.junit.Test public void test02(){ /** * HashSet中没有重复的元素 */ Set set = new HashSet(); set.add(1); set.add("Hello"); set.add(1246.4f); set.add("Hello"); for (Object o : set) { System.out.println(o); } }

3) Queue
@org.junit.Test public void test03(){ /** * 不要使用add方法添加 * 相同:两者都是往队列尾部插入元素, * 不同的:当超出队列界限的时候,add()方法是抛出异常让你处理,而offer()方法是直接返回false */ Queue queue = new LinkedList<>(); queue.offer(1); queue.offer("Hello"); queue.offer(999.9d); for (Object o : queue) { System.out.println(o); } /** * peek()方法会返回队列的头部 */ System.out.println("QueueHead:"+queue.peek()); System.out.println("QueueSize:"+queue.size()); /** * poll()会把队列的头部取出 */ System.out.println("QueueHead:"+queue.poll()); System.out.println("QueueSize:"+queue.size()); }

4)HashMap
@org.junit.Test public void test04(){ /* 添加键值对到map中去 */ Map,String> map = new HashMap,String>(); map.put("1a","Hello"); map.put("2b","World"); map.put("3c","Java"); /* 遍历方法一: 只获取出map中的values */ System.out.println("打印Values"); for (String value : map.values()){ System.out.println(value); } System.out.println("============================"); /* 遍历方法二: 获取出map中的key和value */ System.out.println("打印Key:Value"); Set> set = map.keySet(); for (String key : set) { String value = https://www.it610.com/article/map.get(key); System.out.println(key+":"+value); } System.out.println("============================"); /* 遍历方法三: 最常用的方法 */ System.out.println("最常用的方式打印"); for (Map.Entry, String> entry : map.entrySet()) { String key = entry.getKey(); String value = https://www.it610.com/article/entry.getValue(); System.out.println(key+":"+value); } }

5)Array
@org.junit.Test public void test05(){ /** * 一旦转换是不能修改的 */ List list = Arrays.asList(1,2,3,4,5,6,7,8,9); for (Object o : list) { System.out.println(o); }System.out.println("List转换为数组"); Object[] objects = list.toArray(); System.out.println(Arrays.toString(objects)); /** * 把List转换为不能更改的List */ArrayList list2 = new ArrayList<>(); list2.add(1); list2.add(2); List unlist = Collections.unmodifiableList(list2); /** * unlist不能更改 */}

    推荐阅读