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 <T extends Number> 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方法,我们需要写要几个不同参数形式的方法去适配所有的情况,这无疑是十分不方便的。
package com.jay.java.泛型.DefineGeneric;
public class GenericClass<T> {
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public static void main(String[] args) {
GenericClass<String> genericClass=new GenericClass<>();
genericClass.setData("Generic Class");
System.out.println(genericClass.getData());
}
}
泛型Car
package lys.genericityup.Bean;
public class Car <T>{
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<String> car = new Car<>("Bus");
System.out.println(car.getObject());
Car<Date> car2 = new Car<Date>(new Date());
System.out.println(car2.getObject());
}
}
public class Car extends Vehicle
Car类
package lys.genericitydown.bean;
public class Car<T> extends Vehicle<T>{
public Car(T name) {
super(name);
}
}
Vehicle类
package lys.genericitydown.bean;
public class Vehicle<T> {
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<String>("BMW").toString());
}
}
public class GenericByWildcard {
private static void print(GenericClass<Fruit> fruitGenericClass) {
System.out.println(fruitGenericClass.getData().getColor());
}
private static void use() {
GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
print(fruitGenericClass);
GenericClass<Orange> orangeGenericClass = new GenericClass<>();
//类型不匹配,可以使用 extends Parent> 来解决
// print(orangeGenericClass);
}
/**
* extends Parent> 指定了泛型类型的上届
*/
private static void printExtends(GenericClass<? extends Fruit> genericClass) {
System.out.println(genericClass.getData().getColor());
}
public static void useExtend() {
GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
printExtends(fruitGenericClass);
GenericClass<Orange> orangeGenericClass = new GenericClass<>();
printExtends(orangeGenericClass);
GenericClass<Food> foodGenericClass = new GenericClass<>();
//Food是Fruit的父类,超过了泛型上届范围,类型不匹配
// printExtends(foodGenericClass);
//表示GenericClass的类型参数的上届是Fruit
GenericClass<? extends Fruit> 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();
}
/**
* super Child> 指定了泛型类型的下届
*/
public static void printSuper(GenericClass<? super Apple> genericClass) {
System.out.println(genericClass.getData());
}
public static void useSuper() {
GenericClass<Food> foodGenericClass = new GenericClass<>();
printSuper(foodGenericClass);
GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
printSuper(fruitGenericClass);
GenericClass<Apple> appleGenericClass = new GenericClass<>();
printSuper(appleGenericClass);
GenericClass<HongFuShiApple> hongFuShiAppleGenericClass = new GenericClass<>();
// HongFuShiApple 是Apple的子类,达不到泛型下届,类型不匹配
// printSuper(hongFuShiAppleGenericClass);
GenericClass<Orange> orangeGenericClass = new GenericClass<>();
// Orange和Apple是兄弟关系,没有继承关系,类型不匹配
// printSuper(orangeGenericClass);
//表示GenericClass的类型参数的下界是Apple
GenericClass<? super Apple> supperAppleGenericClass = new GenericClass<>();
supperAppleGenericClass.setData(new Apple());
supperAppleGenericClass.setData(new HongFuShiApple());
/*
* ? super X 表示类型的下界,类型参数是X的超类(包括X本身),
* 那么可以肯定的说,get方法返回的一定是个X的超类,那么到底是哪个超类?不知道,
* 但是可以肯定的说,Object一定是它的超类,所以get方法返回Object。
* 编译器是可以确定知道的。对于set方法来说,编译器不知道它需要的确切类型,但是X和X的子类可以安全的转型为X。
* 总结:主要用于安全地写入数据,可以写入X及其子类型。
*/
// supperAppleGenericClass.setData(new Fruit());
//get方法只会返回一个Object类型的值。
Object data = supperAppleGenericClass.getData();
}
/**
* > 指定了没有限定的通配符
*/
public static void printNonLimit(GenericClass<?> genericClass) {
System.out.println(genericClass.getData());
}
public static void useNonLimit() {
GenericClass<Food> foodGenericClass = new GenericClass<>();
printNonLimit(foodGenericClass);
GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
printNonLimit(fruitGenericClass);
GenericClass<Apple> appleGenericClass = new GenericClass<>();
printNonLimit(appleGenericClass);
GenericClass<?> genericClass = new GenericClass<>();
//setData 方法不能被调用, 甚至不能用 Object 调用;
// genericClass.setData(foodGenericClass);
// genericClass.setData(new Object());
//返回值只能赋给 Object
Object object = genericClass.getData();
}
}
instanceof
关键字或==判断泛型类的类型Throwable
@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);
}
}
HashSet
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);
}
}
@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());
}
HashMap
@org.junit.Test
public void test04(){
/*
添加键值对到map中去
*/
Map<String,String> map = new HashMap<String,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<String> set = map.keySet();
for (String key : set) {
String value = map.get(key);
System.out.println(key+":"+value);
}
System.out.println("============================");
/*
遍历方法三:
最常用的方法
*/
System.out.println("最常用的方式打印");
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+":"+value);
}
}
@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<Object> list2 = new ArrayList<>();
list2.add(1);
list2.add(2);
List<Object> unlist = Collections.unmodifiableList(list2);
/**
* unlist不能更改
*/
}