关于泛型
(1)泛型类
泛型类也就是把泛型定义在类上,这样用户在使用类的时候才把类型给确定下来。
(2)泛型方法
有时候只关心某个方法,那么使用泛型时可以不定义泛型类,而是只定义一个泛型方法,定义泛型方法时,必须在返回值前边加一个< T>,来声明这是一个泛型方法,持有一个泛型T,然后才可以用泛型T作为方法的返回值。
泛型方法最好要结合具体的返回值,否则和Object作为参数差别不大。
(3)继承关系
泛型类在继承时,可以明确父类(泛型类)的参数类型,也可以不明确。 以前写过一个超级数组和链表,现在用泛型来用策略模式来实现
public class Student {
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void play(){
System.out.println(this.name+"is playing");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public interface Super<T> {
/**
* 超级数组
*/
//对数据的增删改查
//创建一个数组nums
//对数据的插入
void add(T data,int index);
//对数据的增加
void addToHead(T data);
void addToTail(T data);
//对数据删除
void delete(int index);
//对数据的修改
void updata(int index,T data);
//对数据的查询
Object select(int index);
//返回数组的大小
int size();
String ToString();
//打印数据
}
public class SuperArray<T> implements Super<T> {
/**
* 超级数组
*/
//对数据的增删改查
//创建一个数组nums
private Object[] nums;
//创建一个下标CurrentIndex
private int currentIndex=-1;
//使用构造器初始化创建大小为10的数组
public SuperArray(){
nums=new Object[2];
}
//方法重载创建任意大小的数组
public SuperArray(int capacity){
nums=new Object[capacity];
}
//对数据的插入
public void add(T data,int index){
// 是否扩容
currentIndex++;
if (currentIndex>nums.length-1){
Object tager[]=new Object[nums.length*2];
for (int i = 0; i < nums.length; i++) {
tager[i]=nums[i];
}
//改变引用
nums=tager;
}
for (int i =currentIndex-1; i >=index ; i--) {
nums[i+1]=nums[i];
}
nums[index]=data;
}
//对数据的增加
public void addToHead(T data){
this.add(data,0);
}
public void addToTail(T data){
this.add(data,currentIndex+1);
}
//对数据删除
public void delete(int index) {
//是否在内
if (index<0||index > currentIndex) {
System.out.println("您想删除的下标"+index+"不在范围之内");
} else {
for (int i = index+1; i < nums.length; i++) {
nums[i - 1] = nums[i];
}
currentIndex--;
System.out.println("删除成功");
}
}//对数据的修改
public void updata(int index,T data){
if (index<0||index > currentIndex) {
System.out.println("您想修改的数据不在范围之内");
}else {
nums[index]=data;
}
}
//对数据的查询
public Object select(int index) {
if (index<0||index > currentIndex) {
System.out.println("您想查询的数据不在范围之内");
return null;
}else
return (T)nums[index];
}
//返回数组的大小
public int size(){
return currentIndex+1;
}
//打印数据
public String ToString(){
String result="[";
for (int i = 0; i < currentIndex+1; i++) {
result+=nums[i].toString()+",";
}
return result.substring(0, result.length()-1)+"]";
}
}
public class SuperLink <T> implements Super<T>{
/**
* 创建一个超级链表
*/
private Node head;
private int CuurentIndex=-1;
private int length;
//链表对于数据的增加
public void addToHead(T data){
this.add(data,0);
}
public void addToTail(T data){
this.add(data,CuurentIndex+1);
}
//链表对于数据的插入
public void add(T data,int index) {
if (head == null) {
head = new Node(data, null);
} else {
if (index == 0) {
Node node = new Node(data, head);
head = node;
} else {
Node node=selectNode(index-1);
Node node1=new Node(data,node.getNext());
node.setNext(node1);
}
}
CuurentIndex++;
}
//链表对于数据的删除
public void delete(int index){
if (index==0){
head=head.getNext();
}else {
//查找删除节点前一个的位置
selectNode(index).setNext(selectNode(index-1).getNext().getNext());
}
CuurentIndex--;
}
//链表对于数据的修改
public void updata(int index,T data){
selectNode(index).setData(data);
}
//链表对于数据的查询
public T select(int index){
return (T)selectNode(index).getData();
}
private Node selectNode(int index){
Node node=head;
for (int i = 0; i <index ; i++) {
node=node.getNext();
}
return node;
}
//打印链表的所有数据
public String ToString(){
String result="[";
for (int i = 0; i <CuurentIndex+1 ; i++) {
result+=select(i).toString()+",";
}
return result.substring(0,result.length()-1)+"]";
}
public int size(){
int length=CuurentIndex+1;
return length;
}
public class Node {
private Node next;
private T data;
public Node(){
}
public Node(T data, Node next){
this.data=data;
this.next=next;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
public <T> T getData() {
return (T)data;
}
public void setData(T data) {
this.data =data;
}
}
}
public class Test {
public static void print(Super<? super Student> super1){
for (int i = 0; i < super1.size(); i++) {
System.out.println(super1.select(i));
}
}
public static void main(String[] args) {
Super<Object> superArray=new SuperArray<>();
superArray.addToHead(new Student("assd",17));
superArray.addToHead(new Student("assd",17));
superArray.addToHead("DD");
Test.print(superArray);
}
}
(4)、关于泛型通配符的定义
无界>
Super< Object >与Super< Student > 并非继承关系 但在利用通配符时可以写成Super< ? >与Super< Student >让 Student 对于 ? 传入参数时可以传进去
public static void print(Super<?> super1){
for (int i = 0; i < super1.size(); i++) {
System.out.println(super1.select(i));
}
}
public static void main(String[] args) {
Super<Student> superArray=new SuperArray<>();
superArray.addToHead(new Student("assd",17));
superArray.addToHead(new Student("assd",17));
superArray.addToHead("DD");
Test.print(superArray);
}
上界 super XXX>
下界 extends XXX>
(5)、泛型擦除
1、
泛型不能作为基础类型
2、
因为泛型不同的重载方法(方法签名相同,数据类型相同)不是方法重载 在编译时会有类型擦除------成员方法
3.类型擦除与多态
本来以为重写但实际在类型擦除的时候发生了重载-----父子类(父类变为0bject,子类为所设定的数据类型)
但是常规的两个方法,他们的方法签名是一样的,也就是说虚拟机根本不能分辨这两个方法。如果是我们自己编写Java代码,这样的代码是无法通过编译器的检查的,但是虚拟机却是允许这样做的,编译器为了实现泛型的多态允许自己做这个看起来“不合法”的事情,然后交给虚拟机去区别。不用我们操心,只顾着重写方法就行了。
4、静态方法和静态类中的问题
泛型类中的静态常量和静态变量不可以使用泛型类所声明的泛型类型参数
没有进行new不知道什么类型,但是静态方法会在类加载的时候传参,明确数据类型。