- 浏览: 90457 次
- 性别:
- 来自: 烟台
最新评论
-
daxiaoli123:
1 http://sourceforge.net/projec ...
GCJ让Java程序脱离jre执行 -
zhangtongysu:
楼主 ,那个下载 怎么回事啊。
利用Ant和Eclipse有效地提高部署工作效率
从jdk1.5开始,Java中开始支持范型了。范型是一个很有用的编程工具,给我们带来了极大的灵活性。在看了《java核心编程》之后,我小有收获,写出来与大家分享。
所谓范型,我的感觉就是,不用考虑对象的具体类型,就可以对对象进行一定的操作,对任何对象都能进行同样的操作。这就是灵活性之所在。但是,正是因为没有考虑对象的具体类型,因此一般情况下不可以使用对象自带的接口函数,因为不同的对象所携带的接口函数不一样,你使用了对象A的接口函数,万一别人将一个对象B传给范型,那么程序就会出现错误,这就是范型的局限性。所以说,范型的最佳用途,就是用于实现容器类,实现一个通用的容器。该容器可以存储对象,也可以取出对象,而不用考虑对象的具体类型。因此,在学习范型的时候,一定要了解这一点,你不能指望范型是万能的,要充分考虑到范型的局限性。下面我们来探讨一下范型的原理以及高级应用。首先给出一个范型类:
public class Pair<T>
...{
public Pair() ...{ first = null; second = null; }
public Pair(T first, T second) ...{ this.first = first; this.second = second; }
public T getFirst() ...{ return first; }
public T getSecond() ...{ return second; }
public void setFirst(T newValue) ...{ first = newValue; }
public void setSecond(T newValue) ...{ second = newValue; }
private T first;
private T second;
}
我们看到,上述Pair类是一个容器类(我会多次强调,范型天生就是为了容器类的方便实现),容纳了2个数据,但这2个数据类型是不确定的,用范型T来表示。关于范型类如何使用,那是最基本的内容,在此就不讨论了。
下面我们来讨论一下Java中范型类的实现原理。在java中,范型是在编译器中实现的,而不是在虚拟机中实现的,虚拟机对范型一无所知。因此,编译器一定要把范型类修改为普通类,才能够在虚拟机中执行。在java中,这种技术称之为“擦除”,也就是用Object类型替换范型。上述代码经过擦除后就变成如下形式: public class Pair
...{
public Pair(Object first, Object second)
...{
this.first = first;
this.second = second;
}
public Object getFirst() ...{ return first; }
public Object getSecond() ...{ return second; }
public void setFirst(Object newValue) ...{ first = newValue; }
public void setSecond(Object newValue) ...{ second = newValue; }
private Object first;
private Object second;
}
大家可以看到,这是一个普通类,所有的范型都被替换为Object类型,他被称之为原生类。每当你用一个具体类去实例化该范型时,编译器都会在原生类的基础上,通过强制约束和在需要的地方添加强制转换代码来满足需求,但是不会生成更多的具体的类(这一点和c++完全不同)。我们来举例说明这一点: Pair<Employee> buddies = new Pair<Employee>();
//在上述原生代码中,此处参数类型是Object,理论上可以接纳各种类型,但编译器通过强制约束
//你只能在此使用Employee(及子类)类型的参数,其他类型编译器一律报错
buddies.setFirst(new Employee("张三"));
//在上述原生代码中,getFirst()的返回值是一个Object类型,是不可以直接赋给类型为Employee的buddy的
//但编译器在此做了手脚,添加了强制转化代码,实际代码应该是Employee buddy = (Employee)buddies.getFirst();
//这样就合法了。但编译器做过手脚的代码你是看不到的,他是以字节码的形式完成的。
Employee buddy = buddies.getFirst();
下面我们再来考察一个更复杂的情况,如果我们的Pair类要保证第二个属性一定要大于第一个属性,该如何做?这就涉及到两个属性的比较,但是这2个属性类型未知,可以比较吗?我们前面也讲过,一般情况下不要涉及类型的具体信息。但是现在要比较2个属性,不得不涉及类型的具体信息了。Java还是考虑到了这一点,那就是,范型类可以继承自某一个父类,或者实现某个接口,或者同时继承父类并且实现接口。这样的话,就可以对类型调用父类或接口中定义的方法了。代码如下: public class Pair<T extends Comparable>
...{
public boolean setSecond(T newValue) ...{
boolean flag = false;
If(newValue.compareTo(first)>0) ...{
second = newValue;
flag = true;
}
return flag;
}
private T first;
private T second;
}
我们看到,上面的范型T被我们添加了一个约束条件,那就是他必须实现Comparable接口,这样的话,我们就可以对范型T使用接口中定义的方法了,也就可以实现2个元素大小的比较。有人可能要问了,实现一个接口不是用implements吗?上面怎么用extends呢??为了简化范型的设计,无论是继承类还是实现接口,一律使用extends关键字。这是规定,没办法,记住就行了。若同时添加多个约束,各个约束之间用“&”分隔,比如:public class Pair<T extends Comparable & Serializable>。那么编译器是如何处理这种情况呢?前面讲过,范型类最终都会被转化为原生类。在前面没有添加约束的时候,编译器将范型通通替换为Object;而增加了约束之后,通通用第一个约束来替换范型(上面的代码就会用Comparable来替换所有范型),当需要用到其他约束中定义的方法的时候,通过插入强制转化代码来实现。在此就不给出具体的例子了。
下面我们来看看最后一个知识点,定义一个函数,该函数接受一个范型类作为参数。首先让我们来看一个最简单的情况,参数是一个实例化的范型类: public static void test(ArrayList<Number> l) ...{
l.add(new Integer(2));
}
上述代码中,形参list的元素被实例化为Number类型。在使用该函数的时候我们能不能传入一个元素为Integer的list呢?看看下面代码合法吗? ArrayList<Integer> l = new ArrayList<Integer>();
test(l); //此处编译器会报错!!
答案上面已经给出了:不行!对于这种形参,实参的类型必须和他完全一致,即也应该是一个元素为Number的list才可以,其他的实参一律不行。这是为什么呢?Integer不是Number的子类吗?子类的对象传递给父类的引用,不可以吗?这里我们就要注意了,Integer确实是Number的子类,但是,ArrayList<Integer>并不是ArrayList<Number>的子类,二者之间没有任何的继承关系!!因此这样传递参数是不允许的。如果允许的话,会出现什么问题吗?当然会,我们对test函数重新定义一下: public static void test(ArrayList<Number> l) ...{
l.add(new Float(2));
}
大家可以看到,在函数内部,我们把Float类型的元素插入到链表中。因为链表是Number类型,这条语句没问题。但是,如果实参是一个Integer类型的链表,他能存储Float类型的数据吗??显然不能,这样就会造成运行时错误。于是,编译器干脆就不允许进行这样的传递。
通过分析我们看到,出错的可能性只有一个:在向容器类添加内容的时候可能造成类型不匹配。那么有些人可能会有这种要求:“我保证一定不对容器添加内容,我非常希望能够将一个Integer类(Number类的子类)组成的链表传递进来”。Sun的那帮大牛们当然会考虑到这种诉求,这样的功能是可以实现的,并且还有两种方式呢,看下面代码: // 1.在定义方法的时候使用Wildcard(也就是下述代码中的问号)。
public static void test1(ArrayList<? extends Number> l) ...{
Integer n = new Integer(45);
Number x = l.get(0); //从链表中取数据是允许的
l.add(n); //错误!!往链表里面插入数据是被编译器严格禁止的!!
}
// 2.定义一个范型方法。代码如下:
public static <T extends Number> void test2(ArrayList<T> l) ...{
Number n = l.get(0);
T d = l.get(0);
l.add(d); //与上面的方法相比,插入一个范型数据是被允许的,相对灵活一些
l.add(n); //错误!!只可以插入范型数据,绝不可插入具体类型数据。
}
按照上述代码的写法,只要我们对形参添加了一定的约束条件,那么我们在传递实参的时候,对实参的严格约束就会降低一些。上述代码都指定了一个类Number,并用了extends关键字,因此,在传递实参的时候,凡是从Number继承的类组成的链表,均可以传递进去。但上面代码的注释中也说的很清楚,为了不出现运行时错误,编译器会对你调用的方法做严格的限制:凡是参数为范型的方法,一律不需调用!! l.get(0)是合法的,因为参数是整型而不是范型;l.add(x)就不合法,因为add函数的参数是范型。但是定义一个范型方法还是有一定灵活性的,如果传入的数据也是范型,编译器还是认可的,因为范型对范型,类型安全是可以保证的。
从上述代码可以看出,定义一个范型方法要比Wildcard稍微灵活一些,可以往链表中添加T类型的对象,而Wildcard中是不允许往链表中添加任何类型的对象的。那么我们还要Wildcard干什么呢?Wildcard还是有他存在的意义的,那就是,Wildcard支持另外一个关键字super,而范型方法不支持super关键字。换句话说,如果你要实现这样的功能:“传入的参数应该是指定类的父类”,范型方法就无能为力了,只能依靠Wildcard来实现。代码如下: public static void test5(ArrayList<? super Integer> l) ...{
Integer n = new Integer(45);
l.add(n); //与上面使用extends关键字相反,往链表里面插入指定类型的数据是被允许的。
Object x = l.get(0); //从链表里取出一个数据仍然是被允许的,不过要赋值给Object对象。
l.add(x); //错误!!将刚刚取出的数据再次插入链表是不被允许的。
} 这种实现方式的特点我们前面已经说过了,就是对实参的限制更改为:必须是指定类型的父类。这里我们指定了Integer类,那么实参链表的元素类型,必须是Number类及其父类。下面我们重点讨论一下上述代码的第四条语句,为什么将刚刚取出的数据再次插入链表不被允许??道理很简单,刚刚取出的数据被保存在一个Object类型的引用中,而链表的add方法只能接受指定类型Integer及其子类,类型不匹配当然不行。有些人可能立刻会说,我将他强制转化为Integer类(即l.add((Integer)x); ),编译器不就不报错了吗?确实,经过强制转化后,编译器确实没意见了。不过这种强制转化有可能带来运行时错误。因为你传入的实参,其元素类型是Integer的父类,比如是Number。那么,存储在该链表中的第一个数据,很有可能是Double或其他类型的,这是合法的。那么你取出的第一个元素x也会是Double类型。那么你把一个Double类型强制转化为Integer类型,显然是一个运行时错误。
难道“把取出的元素再插入到链表中”这样一个功能就实现不了吗?当然可以,不过不能直接实现,要借助范型函数的帮忙,因为在范型函数中,刚刚取出的元素再存回去是不成问题的。定义这样一个范型函数,我们称之为帮助函数。代码如下: //帮助函数
public static <T>void helperTest5(ArrayList<T> l, int index) ...{
T temp = l.get(index);
l.add(temp);
}
//主功能函数
public static void test5(ArrayList<? super Integer> l) ...{
Integer n = new Integer(45);
l.add(n);
helperTest5(l, 0); //通过帮助类,将指定的元素取出后再插回去。
}
上述两个函数结合的原理就是:利用Wildcard的super关键字来限制参数的类型(范型函数不支持super,要是支持的话就不用这么麻烦了),然后通过范型函数来完成取出数据的再存储。
以上就是我学习范型的所有心得。下面再把《Java核心编程》中列出的使用范型时的注意事项列出来(各种操作被禁止的原因就不具体说明了),供大家参考: //1、不可以用一个本地类型(如int float)来替换范型
//2、运行时类型检查,不同类型的范型类是等价的(Pair<String>与Pair<Employee>是属于同一个类型Pair),
// 这一点要特别注意,即如果a instanceof Pair<String>==true的话,并不代表a.getFirst()的返回值是一个String类型
//3、范型类不可以继承Exception类,即范型类不可以作为异常被抛出
//4、不可以定义范型数组
//5、不可以用范型构造对象,即first = new T(); 是错误的
//6、在static方法中不可以使用范型,范型变量也不可以用static关键字来修饰
//7、不要在范型类中定义equals(T x)这类方法,因为Object类中也有equals方法,当范型类被擦除后,这两个方法会冲突
//8、根据同一个范型类衍生出来的多个类之间没有任何关系,不可以互相赋值
// 即Pair<Number> p1; Pair<Integer> p2; p1=p2; 这种赋值是错误的。
//9、若某个范型类还有同名的非范型类,不要混合使用,坚持使用范型类
// Pair<Manager> managerBuddies = new Pair<Manager>(ceo, cfo);
// Pair rawBuddies = managerBuddies; 这里编译器不会报错,但存在着严重的运行时错误隐患
所谓范型,我的感觉就是,不用考虑对象的具体类型,就可以对对象进行一定的操作,对任何对象都能进行同样的操作。这就是灵活性之所在。但是,正是因为没有考虑对象的具体类型,因此一般情况下不可以使用对象自带的接口函数,因为不同的对象所携带的接口函数不一样,你使用了对象A的接口函数,万一别人将一个对象B传给范型,那么程序就会出现错误,这就是范型的局限性。所以说,范型的最佳用途,就是用于实现容器类,实现一个通用的容器。该容器可以存储对象,也可以取出对象,而不用考虑对象的具体类型。因此,在学习范型的时候,一定要了解这一点,你不能指望范型是万能的,要充分考虑到范型的局限性。下面我们来探讨一下范型的原理以及高级应用。首先给出一个范型类:
public class Pair<T>
...{
public Pair() ...{ first = null; second = null; }
public Pair(T first, T second) ...{ this.first = first; this.second = second; }
public T getFirst() ...{ return first; }
public T getSecond() ...{ return second; }
public void setFirst(T newValue) ...{ first = newValue; }
public void setSecond(T newValue) ...{ second = newValue; }
private T first;
private T second;
}
我们看到,上述Pair类是一个容器类(我会多次强调,范型天生就是为了容器类的方便实现),容纳了2个数据,但这2个数据类型是不确定的,用范型T来表示。关于范型类如何使用,那是最基本的内容,在此就不讨论了。
下面我们来讨论一下Java中范型类的实现原理。在java中,范型是在编译器中实现的,而不是在虚拟机中实现的,虚拟机对范型一无所知。因此,编译器一定要把范型类修改为普通类,才能够在虚拟机中执行。在java中,这种技术称之为“擦除”,也就是用Object类型替换范型。上述代码经过擦除后就变成如下形式: public class Pair
...{
public Pair(Object first, Object second)
...{
this.first = first;
this.second = second;
}
public Object getFirst() ...{ return first; }
public Object getSecond() ...{ return second; }
public void setFirst(Object newValue) ...{ first = newValue; }
public void setSecond(Object newValue) ...{ second = newValue; }
private Object first;
private Object second;
}
大家可以看到,这是一个普通类,所有的范型都被替换为Object类型,他被称之为原生类。每当你用一个具体类去实例化该范型时,编译器都会在原生类的基础上,通过强制约束和在需要的地方添加强制转换代码来满足需求,但是不会生成更多的具体的类(这一点和c++完全不同)。我们来举例说明这一点: Pair<Employee> buddies = new Pair<Employee>();
//在上述原生代码中,此处参数类型是Object,理论上可以接纳各种类型,但编译器通过强制约束
//你只能在此使用Employee(及子类)类型的参数,其他类型编译器一律报错
buddies.setFirst(new Employee("张三"));
//在上述原生代码中,getFirst()的返回值是一个Object类型,是不可以直接赋给类型为Employee的buddy的
//但编译器在此做了手脚,添加了强制转化代码,实际代码应该是Employee buddy = (Employee)buddies.getFirst();
//这样就合法了。但编译器做过手脚的代码你是看不到的,他是以字节码的形式完成的。
Employee buddy = buddies.getFirst();
下面我们再来考察一个更复杂的情况,如果我们的Pair类要保证第二个属性一定要大于第一个属性,该如何做?这就涉及到两个属性的比较,但是这2个属性类型未知,可以比较吗?我们前面也讲过,一般情况下不要涉及类型的具体信息。但是现在要比较2个属性,不得不涉及类型的具体信息了。Java还是考虑到了这一点,那就是,范型类可以继承自某一个父类,或者实现某个接口,或者同时继承父类并且实现接口。这样的话,就可以对类型调用父类或接口中定义的方法了。代码如下: public class Pair<T extends Comparable>
...{
public boolean setSecond(T newValue) ...{
boolean flag = false;
If(newValue.compareTo(first)>0) ...{
second = newValue;
flag = true;
}
return flag;
}
private T first;
private T second;
}
我们看到,上面的范型T被我们添加了一个约束条件,那就是他必须实现Comparable接口,这样的话,我们就可以对范型T使用接口中定义的方法了,也就可以实现2个元素大小的比较。有人可能要问了,实现一个接口不是用implements吗?上面怎么用extends呢??为了简化范型的设计,无论是继承类还是实现接口,一律使用extends关键字。这是规定,没办法,记住就行了。若同时添加多个约束,各个约束之间用“&”分隔,比如:public class Pair<T extends Comparable & Serializable>。那么编译器是如何处理这种情况呢?前面讲过,范型类最终都会被转化为原生类。在前面没有添加约束的时候,编译器将范型通通替换为Object;而增加了约束之后,通通用第一个约束来替换范型(上面的代码就会用Comparable来替换所有范型),当需要用到其他约束中定义的方法的时候,通过插入强制转化代码来实现。在此就不给出具体的例子了。
下面我们来看看最后一个知识点,定义一个函数,该函数接受一个范型类作为参数。首先让我们来看一个最简单的情况,参数是一个实例化的范型类: public static void test(ArrayList<Number> l) ...{
l.add(new Integer(2));
}
上述代码中,形参list的元素被实例化为Number类型。在使用该函数的时候我们能不能传入一个元素为Integer的list呢?看看下面代码合法吗? ArrayList<Integer> l = new ArrayList<Integer>();
test(l); //此处编译器会报错!!
答案上面已经给出了:不行!对于这种形参,实参的类型必须和他完全一致,即也应该是一个元素为Number的list才可以,其他的实参一律不行。这是为什么呢?Integer不是Number的子类吗?子类的对象传递给父类的引用,不可以吗?这里我们就要注意了,Integer确实是Number的子类,但是,ArrayList<Integer>并不是ArrayList<Number>的子类,二者之间没有任何的继承关系!!因此这样传递参数是不允许的。如果允许的话,会出现什么问题吗?当然会,我们对test函数重新定义一下: public static void test(ArrayList<Number> l) ...{
l.add(new Float(2));
}
大家可以看到,在函数内部,我们把Float类型的元素插入到链表中。因为链表是Number类型,这条语句没问题。但是,如果实参是一个Integer类型的链表,他能存储Float类型的数据吗??显然不能,这样就会造成运行时错误。于是,编译器干脆就不允许进行这样的传递。
通过分析我们看到,出错的可能性只有一个:在向容器类添加内容的时候可能造成类型不匹配。那么有些人可能会有这种要求:“我保证一定不对容器添加内容,我非常希望能够将一个Integer类(Number类的子类)组成的链表传递进来”。Sun的那帮大牛们当然会考虑到这种诉求,这样的功能是可以实现的,并且还有两种方式呢,看下面代码: // 1.在定义方法的时候使用Wildcard(也就是下述代码中的问号)。
public static void test1(ArrayList<? extends Number> l) ...{
Integer n = new Integer(45);
Number x = l.get(0); //从链表中取数据是允许的
l.add(n); //错误!!往链表里面插入数据是被编译器严格禁止的!!
}
// 2.定义一个范型方法。代码如下:
public static <T extends Number> void test2(ArrayList<T> l) ...{
Number n = l.get(0);
T d = l.get(0);
l.add(d); //与上面的方法相比,插入一个范型数据是被允许的,相对灵活一些
l.add(n); //错误!!只可以插入范型数据,绝不可插入具体类型数据。
}
按照上述代码的写法,只要我们对形参添加了一定的约束条件,那么我们在传递实参的时候,对实参的严格约束就会降低一些。上述代码都指定了一个类Number,并用了extends关键字,因此,在传递实参的时候,凡是从Number继承的类组成的链表,均可以传递进去。但上面代码的注释中也说的很清楚,为了不出现运行时错误,编译器会对你调用的方法做严格的限制:凡是参数为范型的方法,一律不需调用!! l.get(0)是合法的,因为参数是整型而不是范型;l.add(x)就不合法,因为add函数的参数是范型。但是定义一个范型方法还是有一定灵活性的,如果传入的数据也是范型,编译器还是认可的,因为范型对范型,类型安全是可以保证的。
从上述代码可以看出,定义一个范型方法要比Wildcard稍微灵活一些,可以往链表中添加T类型的对象,而Wildcard中是不允许往链表中添加任何类型的对象的。那么我们还要Wildcard干什么呢?Wildcard还是有他存在的意义的,那就是,Wildcard支持另外一个关键字super,而范型方法不支持super关键字。换句话说,如果你要实现这样的功能:“传入的参数应该是指定类的父类”,范型方法就无能为力了,只能依靠Wildcard来实现。代码如下: public static void test5(ArrayList<? super Integer> l) ...{
Integer n = new Integer(45);
l.add(n); //与上面使用extends关键字相反,往链表里面插入指定类型的数据是被允许的。
Object x = l.get(0); //从链表里取出一个数据仍然是被允许的,不过要赋值给Object对象。
l.add(x); //错误!!将刚刚取出的数据再次插入链表是不被允许的。
} 这种实现方式的特点我们前面已经说过了,就是对实参的限制更改为:必须是指定类型的父类。这里我们指定了Integer类,那么实参链表的元素类型,必须是Number类及其父类。下面我们重点讨论一下上述代码的第四条语句,为什么将刚刚取出的数据再次插入链表不被允许??道理很简单,刚刚取出的数据被保存在一个Object类型的引用中,而链表的add方法只能接受指定类型Integer及其子类,类型不匹配当然不行。有些人可能立刻会说,我将他强制转化为Integer类(即l.add((Integer)x); ),编译器不就不报错了吗?确实,经过强制转化后,编译器确实没意见了。不过这种强制转化有可能带来运行时错误。因为你传入的实参,其元素类型是Integer的父类,比如是Number。那么,存储在该链表中的第一个数据,很有可能是Double或其他类型的,这是合法的。那么你取出的第一个元素x也会是Double类型。那么你把一个Double类型强制转化为Integer类型,显然是一个运行时错误。
难道“把取出的元素再插入到链表中”这样一个功能就实现不了吗?当然可以,不过不能直接实现,要借助范型函数的帮忙,因为在范型函数中,刚刚取出的元素再存回去是不成问题的。定义这样一个范型函数,我们称之为帮助函数。代码如下: //帮助函数
public static <T>void helperTest5(ArrayList<T> l, int index) ...{
T temp = l.get(index);
l.add(temp);
}
//主功能函数
public static void test5(ArrayList<? super Integer> l) ...{
Integer n = new Integer(45);
l.add(n);
helperTest5(l, 0); //通过帮助类,将指定的元素取出后再插回去。
}
上述两个函数结合的原理就是:利用Wildcard的super关键字来限制参数的类型(范型函数不支持super,要是支持的话就不用这么麻烦了),然后通过范型函数来完成取出数据的再存储。
以上就是我学习范型的所有心得。下面再把《Java核心编程》中列出的使用范型时的注意事项列出来(各种操作被禁止的原因就不具体说明了),供大家参考: //1、不可以用一个本地类型(如int float)来替换范型
//2、运行时类型检查,不同类型的范型类是等价的(Pair<String>与Pair<Employee>是属于同一个类型Pair),
// 这一点要特别注意,即如果a instanceof Pair<String>==true的话,并不代表a.getFirst()的返回值是一个String类型
//3、范型类不可以继承Exception类,即范型类不可以作为异常被抛出
//4、不可以定义范型数组
//5、不可以用范型构造对象,即first = new T(); 是错误的
//6、在static方法中不可以使用范型,范型变量也不可以用static关键字来修饰
//7、不要在范型类中定义equals(T x)这类方法,因为Object类中也有equals方法,当范型类被擦除后,这两个方法会冲突
//8、根据同一个范型类衍生出来的多个类之间没有任何关系,不可以互相赋值
// 即Pair<Number> p1; Pair<Integer> p2; p1=p2; 这种赋值是错误的。
//9、若某个范型类还有同名的非范型类,不要混合使用,坚持使用范型类
// Pair<Manager> managerBuddies = new Pair<Manager>(ceo, cfo);
// Pair rawBuddies = managerBuddies; 这里编译器不会报错,但存在着严重的运行时错误隐患
发表评论
-
调试MAVEN项目appfuse-light-struts2-spring-jdbc-1.8的问题
2008-03-07 16:31 2285出现问题: Project appfuse-light-str ... -
MVC设计思想
2008-03-01 22:13 2144MVC英文即Model-View-Controll ... -
当前Java软件开发中几种认识误区(转)
2008-03-01 22:11 970软件的生命性 软件是有生命的,这可能是老调重弹了,但是因 ... -
给servlet写单元测试的总结(转)
2008-02-19 11:19 3545servlet的测试一般来说需要容器的支持,不是像通常的jav ... -
取得参数的几中形式
2008-02-18 12:54 882java -DSTOP.PORT=8080 -DSTOP.KE ... -
正则表达式
2008-02-18 12:34 900目录 本文目标 如何使 ... -
关于Java中类在构造对象时的初始化步骤详解
2008-02-18 12:17 2100很多人在学习Java的过程 ... -
Java连接各种数据库的实例
2008-02-18 12:13 1166一、jsp连接Oracle8/8i/9i数据库(用thin模式 ... -
为什么要使用接口编程(转)
2008-02-17 21:42 1285看了接口编程这篇文章, ... -
JAVA中浅复制与深复制
2008-02-17 21:38 7211.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变 ... -
短信网关发送部分源代码
2008-02-17 21:37 1216package com.etonenet.iiie.sdk; ... -
appfuse结合eclipse开发流程
2008-02-17 21:33 1220Appfuse应用的核心在于ant ... -
使用Antlr和JfreeChart实现项目源代码行数计算图表
2008-02-17 21:30 1541Antlr的功能在我的其他文章里提到了就不多说了,JFreeC ... -
使用ANT协助开发java项目
2008-02-17 21:29 896ANT是Apache的开源项目,目前在java的项目开发中被广 ... -
利用Ant和Eclipse有效地提高部署工作效率
2008-02-17 21:26 1265本文主要介绍 Ant 在多 ... -
使用开源软件 Mantis 实施缺陷跟踪的成功实践
2008-02-17 21:22 1699内容摘要 中国开源 注:当前Mantis稳定发布版本为1.0. ... -
开源缺陷跟踪系统mantis安装指南
2008-02-17 21:14 18881. 简介 mantis(螳螂)是一个基于php/MySQL/ ... -
无所不能的“蚂蚁”-Ant(转)
2008-02-17 21:12 3233说他无所不能,好像有点夸张,但是用过Ant之后,感觉真的是只有 ... -
Java华为面试题
2008-02-17 21:08 1470第一部分:选择题 QUESTION NO: 1 1、publi ... -
java中读取Properties文件
2008-02-17 21:06 907ResourceBundle resourceBundle = ...
相关推荐
Java泛型的用法及T.class的获取过程解析 Java泛型是Java编程语言中的一种重要特性,它允许开发者在编写代码时指定类型参数,从而提高代码的灵活性和可读性。本文将详细介绍Java泛型的用法 及T.class的获取过程解析...
Java 泛型详解 Java 泛型是 Java SE 5.0 中引入的一项特征,它允许程序员在编译时检查类型安全,从而减少了 runtime 错误的可能性。泛型的主要优点是可以Reusable Code,让程序员编写更加灵活和可维护的代码。 ...
Java泛型是Java编程语言中的一个强大特性,它允许我们在定义类、接口和方法时指定类型参数,从而实现代码的重用和类型安全。在Java泛型应用实例中,我们可以看到泛型如何帮助我们提高代码的灵活性和效率,减少运行时...
Java泛型机制详解 Java泛型是Java语言中的一种机制,用于在编译期检查类型安全。Java泛型的出现解决了Java早期版本中类型安全检查的缺陷。Java泛型的好处是可以在编译期检查类型安全,避免了运行时的...
综上所述,虽然Java泛型在编译后会进行类型擦除,但通过上述技巧,我们仍然能够在运行时获得关于泛型类实例化类型的一些信息。在实际开发中,这些方法可以帮助我们编写更加灵活和安全的代码。在示例文件`GenericRTTI...
Java泛型是Java编程语言中的一个关键特性,它在2004年随着Java SE 5.0的发布而引入,极大地增强了代码的类型安全性和重用性。本篇文章将深入探讨Java泛型的发展历程、核心概念以及其在实际开发中的应用。 1. **发展...
Java泛型是Java编程语言中的一个关键特性,它在2004年随着JDK 5.0的发布被引入。这个特性极大地提高了代码的类型安全性和可读性,减少了在运行时出现ClassCastException的可能性。SUN公司的Java泛型编程文档,包括...
下面我们将详细探讨Java泛型接口的相关知识点。 1. **泛型接口的定义** 泛型接口的定义方式与普通接口类似,只是在接口名之后添加了尖括号`<T>`,其中`T`是一个类型参数,代表某种未知的数据类型。例如: ```java...
下面我们将深入探讨Java泛型方法的概念、语法以及使用示例。 **一、泛型方法概念** 泛型方法是一种具有类型参数的方法,这些类型参数可以在方法声明时指定,并在方法体内部使用。与类的泛型类似,它们提供了编译时...
Java泛型是Java编程语言中的一个强大特性,它允许在定义类、接口和方法时使用类型参数,从而实现参数化类型。这使得代码更加安全、可读性更强,并且能够减少类型转换的必要。在“java泛型的内部原理及更深应用”这个...
这是一个使用JAVA实现的泛型编程,分为两部分,第一部分创建泛型类,并实例化泛型对象,得出相加结果。 第二部分用户自行输入0--4,选择要进行的加减乘除运算或退出,再输入要进行运算的两个数,并返回运算结果及...
Java 泛型是一种强大的工具,它允许我们在编程时指定变量的类型,提供了编译时的类型安全。然而,Java 的泛型在运行时是被擦除的,这意味着在运行时刻,所有的泛型类型信息都会丢失,无法直接用来创建对象或进行类型...
"Java 泛型学习" Java 泛型是 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的...
Java 泛型使用详细分析 Java 泛型是 Java 语言中的一种类型系统特性,允许开发者在编译期检查类型安全,以避免在运行时出现类型相关的错误。在本文中,我们将详细介绍 Java 泛型的使用方法和实现原理。 一、泛型的...
Java泛型是Java编程语言中的一个关键特性,它在2004年随着Java SE 5.0的发布而引入,极大地增强了代码的类型安全性和重用性。本篇文章将深入探讨Java泛型的发展历程、核心概念以及其在实际开发中的应用。 1. **发展...
#### 一、什么是Java泛型? Java泛型(Generics)是一种在编译时确保类型安全的机制,它允许程序员编写类型安全的通用类或方法,而无需进行显式的类型转换。在Java 1.5引入泛型之前,集合类(如`ArrayList`)只能...