aClass_Person
package com.se.Genericity.aClass;
import java.util.Date;
/**
* 泛型: 类型参数化。 定义期间,有些东西不确定是什么类型,在使用期间确定
* 这样就可以使用泛型。给形参赋值具体类型名
* 泛型类 泛型应用在类上。一般用在类名后,使用尖括号括起来。用大写字母作为泛型参数。
*
*/
public class Person<T> {
private T idCard;
public Person(T idCard){
this.idCard = idCard;
}
public static void main(String[] args) {
//创建一个Person对象,需要给泛型参数赋值具体类型
Person p1 = new Person<String>("123456");
Person<String> p2 = new Person("123456");
//泛型参数,只能赋值引用类型,不能赋值八大基本数据类型
Person<Long> p3 = new Person<>(34567890L);
Date date = new Date();
//tips: 实例化过程中,可以只在一遍给泛型参数赋值,但是两边的尖括号都不可以省略
Person<Date> p4 = new Person<>(date);
}
}
/**
* 当一个子类继承带有泛型的父类时,一般情况下要给泛型参数赋值具体类名
*/
class Student extends Person<Integer>{
public Student(Integer idcard) {
super(idcard);
}
}
/**
* 子类的泛型参数可以赋值给父类的泛型参数
* 下面的例子就是 E赋值给了T
*/
class Teacher<E> extends Person<E>{
public Teacher(E idcard) {
super(idcard);
}
}
/**
* 如果 子类在定义期间,没有给泛型父类参数赋值,默认Object
*/
class President extends Person{
public President(Object idcard) {
super(idcard);
}
}
bInterface_MyComparable
package com.se.Genericity.bInterface;
import java.util.Arrays;
import java.util.Comparator;
/**
* 泛型接口: 泛型用在接口上
*/
public interface MyComparable<T, M> {
//两种类型进行比较
public int mycompare(T o1, M o2);
public static void main(String[] args) {
Employee[] employees = new Employee[3];
employees[0] = new Employee("xin", 19);
employees[1] = new Employee("zin", 18);
employees[2] = new Employee("din", 17);
//使用比较器接口,来重新定义比较规则
// 从泛型的角度来说,在实例化接口时,要给泛型参数传具体类型
Comparator c = new Comparator<Employee>() {
//重写比较器里的compare方法
public int compare(Employee o1, Employee o2) {
//调用了自定义的员工类里的比较方法
return o1.mycompare(o1, o2);
}
};
Arrays.sort(employees, c);
System.out.println(Arrays.toString(employees));
}
}
//子类实现接口 通常子类要给泛型接口的泛型参数赋值具体类型名
//下面案例,就是给T和M都赋值了Employee这个类型
class Employee implements MyComparable<Employee, Employee> {
String name;
int age;
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return "[" + name + "," + age + "]";
}
public int mycompare(Employee o1, Employee o2) {
return o2.age - o1.age;
}
}
cMethod_MyUtil
package com.se.Genericity.cMethod;
import java.util.Objects;
/**
* 泛型方法: 泛型应用在方法上位置位于返回值类型的前面
* <p>
* 案例演示: 定义一个工具类, 用于比较两个对象是否一样
*/
public class MyUtil {
public static <T> boolean equals(T t1, T t2) {
return t1.equals(t2);
}
public static void main(String[] args) {
Cat c1 = new Cat("小花");
Cat c2 = new Cat("小花");
//泛型方法在调用期间,不需要指定具体类型,只需要传入具体类型,编译器会自动推断对象的类型
//泛型方法调用期间,并没有给泛型参数赋值,下面的案例是c1给t1赋值,c2给t2赋值
boolean result = MyUtil.equals(c1, c2);
System.out.println(result);
}
}
class Cat {
String name;
@Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
Cat cat = (Cat) object;
return Objects.equals(name, cat.name);
}
@Override
public int hashCode() {
return Objects.hashCode(name);
}
public Cat(String name) {
this.name = name;
}
}
dSymbol_MyUtil
package com.se.Genericity.dSymbol;
/**
* 泛型通配符:? 用来表明不关心调用时的具体类型。
*/
import java.util.ArrayList;
import java.util.List;
public class MyUtil {
/*
将集合元素打印在控制台上
*/
public static void print(List<?> list) {
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
/*
上边界的定义: <? extends 具体类名>
具体使用的时候,可以是上边界的任何子类型或者本类型
*/
public static void print2(List<? extends Number> list) {
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
/*
下边界的定义: <? super 具体类名>
具体使用的时候,可以是下边界的任何父类型或者本类型
*/
public static void print3(List<? super Integer> list) {
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
public static void main(String[] args) {
List<Integer> nums = new ArrayList<Integer>();
nums.add(1);
nums.add(2);
nums.add(3);
MyUtil.print(nums);
List<Long> ns = new ArrayList<Long>();
ns.add(1L);
ns.add(2L);
ns.add(3L);
MyUtil.print(ns);
//上边界的测试
print2(new ArrayList<Long>());
print2(new ArrayList<Number>());
// print2(new ArrayList<Object>()); 最高到达的类型是Number,所以只能是Number或者Number的子类
//下边界的测试
print3(new ArrayList<Integer>());
print3(new ArrayList<Number>());
print3(new ArrayList<Object>());
// print3(new ArrayList<Long>()); Long和Integer没有关系
}
}
eDateStructrue_MyDoubleList
package com.se.Genericity.eDateStructrue;
import java.net.BindException;
/**
* 自定义一个双链表的数据结构
*/
public class MyDoubleList<E> {
// 新创建容器时,头部和尾部都没有节点,都是null;size是0。
private Node headNode; // 头部节点
private Node tailNode; // 尾部节点
private int size; // 元素个数
/**
* 添加元素到链表尾部
*
* @param e 要添加的元素
*/
public void addLast(E e) {
// 创建一个新节点,当前节点的element是e,preNode和nextNode都是null
Node newNode = new Node(e);
if (headNode == null) {
// 如果链表为空,则头部节点和尾部节点都是当前节点
headNode = newNode;
tailNode = newNode;
} else {
// 将新节点添加到尾部
newNode.preNode = tailNode;
tailNode.nextNode = newNode;
tailNode = newNode;
}
size++; // 更新链表大小
}
/**
* 将元素添加到链表头部
*
* @param e 要添加的元素
*/
public void addFirst(E e) {
Node newNode = new Node(e);
if (headNode == null) {
// 如果链表为空,则头部节点和尾部节点都是当前节点
headNode = newNode;
tailNode = newNode;
} else {
// 将新节点添加到头部
newNode.nextNode = headNode;
headNode.preNode = newNode;
headNode = newNode;
}
size++; // 更新链表大小
}
/**
* 向指定索引位置添加元素
*
* @param index 要插入的位置索引
* @param e 要插入的元素
*/
public void addAt(int index, E e) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("索引越界");
}
if (index == 0) {
// 如果索引为0,则将元素添加到头部
addFirst(e);
} else if (index == size) {
// 如果索引等于链表大小,则将元素添加到尾部
addLast(e);
} else {
// 创建新节点
Node newNode = new Node(e);
// 找到索引位置的前一个节点
Node current = headNode;
for (int i = 0; i < index; i++) {
current = current.nextNode;
}
// 插入新节点
newNode.nextNode = current;
newNode.preNode = current.preNode;
current.preNode.nextNode = newNode;
current.preNode = newNode;
size++; // 更新链表大小
}
}
/**
* 获取指定索引位置的元素
*
* @param index 要获取元素的索引
* @return 指定索引位置的元素
*/
public E get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("索引越界");
}
//根据索引位置决定从头尾哪一侧开始遍历
Node current = (index < size / 2) ? headNode : tailNode;
for (int i = 0; i < index; i++) {
current = current.nextNode;
}
// 返回当前节点的元素
return current.element;
}
/**
* 设置指定索引位置的元素
*
* @param index 要设置元素的索引
* @param e 新的元素
* @return 被替换的旧元素
*/
public E set(int index, E e) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("索引越界");
}
//根据索引位置决定从头尾哪一侧开始遍历
Node current = (index < size / 2) ? headNode : tailNode;
for (int i = 0; i < index; i++) {
current = current.nextNode;
}
// 保存旧元素
E oldElement = current.element;
// 设置新元素
current.element = e;
// 返回旧元素
return oldElement;
}
/**
* 移除指定索引位置的元素
*
* @param index 要移除元素的索引
* @return 被移除的元素
*/
public E remove(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("索引越界");
}
Node current = (index < size / 2) ? headNode : tailNode;
for (int i = 0; i < index;i++ ){
current = current.nextNode;
}
E oldElement = current.element;
current.element=null;
return oldElement;
}
/**
* 返回链表的字符串表示形式
*
* @return 链表的字符串表示形式
*/
public String toString() {
StringBuilder sb = new StringBuilder();
Node node = headNode;
for (int i = 0; i < size; i++) {
sb.append(node.element + ",");
node = node.nextNode;
}
return sb.toString();
}
/**
* 双链表的节点类
*/
private class Node {
E element; // 当前节点的元素
Node preNode; // 前一个节点
Node nextNode; // 后一个节点
/**
* 一参构造器,给当前元素赋值
*
* @param element 节点的元素
*/
public Node(E element) {
this.element = element;
}
/**
* 全参构造器
*
* @param element 节点的元素
* @param preNode 前一个节点
* @param nextNode 后一个节点
*/
public Node(E element, Node preNode, Node nextNode) {
this.element = element;
this.preNode = preNode;
this.nextNode = nextNode;
}
}
/**
* 主方法,用于测试双链表的功能
*
* @param args 命令行参数
*/
public static void main(String[] args) {
MyDoubleList list = new MyDoubleList();
list.addLast("a");
list.addLast("b");
list.addLast("c");
System.out.println(list); // 输出: a,b,c,
list.addAt(0, "m");
System.out.println(list); // 输出: m,a,b,c,
}
}