这个是Mark Allen Weiss写的 数据结构与问题求解 第四版上面的源程序private Type[] theItems;//当前数组
private int size;//实际大小public boolean add(Type x){
if(theItems.length==size){//数组容量满
Type[] old = theItems;
theItems = (Type[]) new Object[size*2+1];//这行怎么都不理解,编译能通过是因为类型擦除,但是运行
//的时候假如类型参数是String,Object[]如何强转成String[]???
for(int i=0;i<size;i++)
theItems[i] = old[i];//循环复制元素
}
theItems[size++] = x;//插入元素
return true;}问题1:注释行的问题
问题2:因为new Type[size*2+1]语法不通过,因此还有其他方法扩展泛型数组的容量么?
private int size;//实际大小public boolean add(Type x){
if(theItems.length==size){//数组容量满
Type[] old = theItems;
theItems = (Type[]) new Object[size*2+1];//这行怎么都不理解,编译能通过是因为类型擦除,但是运行
//的时候假如类型参数是String,Object[]如何强转成String[]???
for(int i=0;i<size;i++)
theItems[i] = old[i];//循环复制元素
}
theItems[size++] = x;//插入元素
return true;}问题1:注释行的问题
问题2:因为new Type[size*2+1]语法不通过,因此还有其他方法扩展泛型数组的容量么?
theItems = (Type[]) new Object[size*2+1];
// 編譯之後: theItems = (Object[]) new Object[size*2+1];泛型的意义在于"编译时"。
// reflection:
theItems = (Type[])Arrays.newInstance(Object.class, size*2+1);
另,这种使用一般是用在封装得很好的泛型类或泛型方法的内部,除此之外,尽量不要把数组和泛型混用,因为数组的特性天生是与"编译时类型安全"有些冲突的。
楼主这里的 Type 如果写成 T ,你还有什么疑问么?
但是Java标准库List<String> list = new ArrayList<String>(); 然后调用List的内部方法get(i)可以直接得到不需要强制转换的String,这个不是矛盾么。
数组的特性天生是与"编译时类型安全"有些冲突的? 这个。有点不理解。数组为嘛类型不安全
class UserList<T> {
T[] elements; //泛型数组
Class<T> clazz;
int size; public UserList(Class<T> clazz) { //需要传入泛型Class类型
this.clazz = clazz;
elements = (T[])Array.newInstance(clazz, 20); //default capacity 20
} //这样的话toArray可以直接返回 elements
}//生成实例
UserList<String> ul = new UserList<String>(String.class); //需要传入Class
否则,内部数组应该使用Object数组,这就是为什么List的toArray方法需要参数T[](其实用Class<T>类型也可以)LZ可以研究一下java的ArrayList之类的源码
ArrayList的get(i)方法内部里做了转换了,LZ可以自己看源码
return (E)elementData[index];
然后调用List的内部方法get(i)可以直接得到不需要强制转换的String你看到的String str = list.get(i);是编译以前的代码,实际编译以后是这样的:String str = (String)list.get(i);这就是 Java 泛型的工作原理,也就是所谓的"类型释放"。所有 Type 的地方,都是 Object。
不好意思,很久没上论坛了。MyArrayList<String> list = new MyArrayList<String>()中,没有识别,就是Object但是下面的代码:
String str = list.get(0);会被编译器翻译成String str = (String)list.get(0);来编译,同样的:for(String str : list) {
// ...
}// 翻译成 ->
for(Iterator<String> it=list.iterator(); it.hasNext();) {
String str = it.next();
// ...
}// 翻译成 ->
for(Iterator it=list.iterator(); it.hasNext();) {
String str = (String)it.next();
// ...
}
在上述翻译的强制类型转换处,实际的类型信息被保存到了运行时。而假如编译的时候顺利通过且没有警告的话,这里的强制类型转换就能确保成功。
但即使按照您写的说法,您给的例子原始就是String所以能够强制转换,但我主贴里面是
theItems = (Type[]) new Object[size*2+1];运行的时候,我的原始类型是Object[]型,强制转换成Type[],这个也不行吧。
唉不理解啊不理解啊。
写了挺多泛型类了。还是把他们都记住吧。汗。分都给您了。谢谢了。
* 泛型代码
*
* @date 20/09/2012
*/
public class SafeArray<E> {
public static void main(String[] args) {
SafeArray<String> array = new SafeArray<String>(10);
array.add("asdf");
String str = array.get(0);
System.out.println(str);
}
private E[] items;
private int size;
public SafeArray(int capacity) {
if( capacity <= 0 )
throw new IllegalArgumentException();
items = (E[])new Object[capacity];
size = 0;
}
public boolean add(E item) {
if (items.length == size) {
E[] old = items;
items = (E[])new Object[size * 2 + 1];
System.arraycopy(old, 0, items, 0, old.length);
}
items[size] = item;
size++;
return true;
}
public E get(int index) {
if( index < 0 || index >= items.length )
throw new IndexOutOfBoundsException();
return index >= size ? null : items[index];
}
}
/**
* 擦除后的代码(编译后的字节码与上面的泛型代码编译后相等)。
*
* @date 20/09/2012
*/
public class SafeArray {
public static void main(String[] args) {
SafeArray array = new SafeArray(10);
array.add("asdf");
String str = (String)array.get(0);
System.out.println(str);
}
private Object[] items;
private int size;
public SafeArray(int capacity) {
if( capacity <= 0 )
throw new IllegalArgumentException();
items = (Object[])new Object[capacity];
size = 0;
}
public boolean add(Object item) {
if (items.length == size) {
Object[] old = items;
items = (Object[])new Object[size * 2 + 1];
System.arraycopy(old, 0, items, 0, old.length);
}
items[size] = item;
size++;
return true;
}
public Object get(int index) {
if( index < 0 || index >= items.length )
throw new IndexOutOfBoundsException();
return index >= size ? null : items[index];
}
}
总结:在泛型定义的作用范围(类或方法)内,类型擦除后泛型类型声明会被 Object 代替;而在应用代码中(声明了实际类型的地方),类型擦除后会自动添加必要的强制类型转换。