由于泛型数组,变量不能初始化,查了查资料,感觉别人的好不可靠啊!自己搞了个方法搞定了,记一下! 直接上代码:我们的目标是构造一个栈,基本的三个功能,push,pop,peek. ###code
package Book;
import java.lang.reflect.Array;
import java.security.PrivateKey;
/**
* Created by pinker on 17-3-18.
*/
public class MyStack<T> {
// private T t;
private T[] ele;
private int cursor;
private Class clazz;
public MyStack(Class clazz) {
this(clazz, 5);
}
public MyStack(Class clazz, int size) {
this.clazz = clazz;
ele = (T[]) Array.newInstance(clazz, size);
cursor = -1;
}
public void push(T t) {
//自动扩容
if (cursor == ele.length - 1) {
T[] temp = (T[]) Array.newInstance(clazz, ele.length * 2);
for (int i = 0; i < ele.length; i++)
temp[i] = ele[i];
ele = temp;
}
ele[++cursor] = t;
}
public T peek() {
if (cursor < 0) {
System.out.println("没有元素啦!");
return null;
}
return ele[cursor];
}
public T pop() {
if (cursor < 0) {
System.out.println("没有元素啦!");
return null;
}
return ele[cursor--];
}
public static void main(String[] args) {
MyStack<Integer> stack1 = new MyStack<>(Integer.class);
MyStack<String> stack2 = new MyStack<>(String.class);
stack1.push(1);
stack1.push(2);
stack1.push(3);
stack1.push(4);
stack1.push(5);
stack1.push(6);
stack1.push(7);
stack1.push(8);
stack2.push("HS");
stack2.push("YS");
stack2.push("ZS");
stack2.push("DS");
System.out.println(stack1.peek());
System.out.println(stack1.pop());
System.out.println(stack1.peek());
System.out.println(stack2.peek());
System.out.println(stack2.pop());
System.out.println(stack2.peek());
}
}
###result
8
8
7
DS
DS
ZS
###自己想了想,如果泛型能在内部搞定,那么多API也就不会让我们传这种Class这种具体的对象类型了。此猜想留待以后看源码解决。
#泛型的类与方法之间的关系小记:
public class GenericTypeDemo<T> {
public <T> T test(T... a) {
return a[a.length - 2];
}
public static void main(String[] args) {
Object obj = new GenericTypeDemo<String>().test("123", 0, "HS");
System.out.println(obj.getClass() + "-->" + obj);
}
}
class java.lang.Integer-->0
我们分析一下这段代码,类的泛型T我们规定为String,是不是意味着方法的泛型T也是String了呢?我们返现不是String,因为方法前面也声明了<T>,故我们能看到最后的结果是Integer.
- 泛型方法有自己的类型参数,泛型类的成员方法使用的是当前类的类型参数。
- 方法中有<T> 是泛型方法;没有的,称为泛型类中的成员方法
###如果限制只有特定某些类可以传入T参数,那么可以对T进行限定
//我们知道final类不可继承,在继承机制上class SomeString extends String是错误的,
// 但泛型限定符使用时是可以的:<T extends String>,只是会给一个警告
public void test() {
Test<child1, child2> demo = new Test<>();
}
class Test<T extends Parent, S extends Comparable & Parent> {
}
interface Parent {
void say();
}
class child1 implements Parent {
@Override
public void say() {
System.out.println("i am child1");
}
}
class child2 extends child1 implements Comparable {
@Override
public int compareTo(Object o) {
System.out.println("i am in compare method");
return 0;
}
@Override
public void say() {
System.out.println("i am child2");
}
}
泛型擦除时:有多个限定符的,替换为第一个限定类型名。如果引用了第二个限定符的类对象,编译器会在必要的时候进行强制类型转换
#泛型的约束和限制 ##不能使用8个基本类型实例化类型参数 原因在于类型擦除,Object不能存储基本类型: byte,char,short,int,long,float,double,boolean ##类型检查不可使用泛型
if(aaa instanceof Pair<String>){}//error
Pair<String> p = (Pair<String>) a;//warn
Pair<String> p;
Pair<Integer> i;
i.getClass()==p.getClass();//true
###泛型数组(见本博文上面),有一个特例是方法的可变参数,虽然本质上是数组,却可以使用泛型. ###不能实例化泛型对象 若要实例化泛型对象,必须传入Class<T> t参数,调用t.newInstance()。
public <E> void test3(Class<E> t) {
E obj = null;
try {
obj = t.newInstance();
} catch (InstantiationException e) {//实例化异常
e.printStackTrace();
} catch (IllegalAccessException e) {//非法访问异常
e.printStackTrace();
}
System.out.println(obj.getClass());
}
class java.lang.String
可以看出泛型的实例化和数组的有的一比! ##泛型类的静态域中不能使用泛型类型;静态的泛型方法可以使用泛型类型 ##不能泛型重载 setName(T t)和setName(String t)不能同时存在!