我在泛型(JAVA)中使用有界类型参数。
class First<T extends Use>{
T s;
First(T s){
this.s=s;
}
void setS(T s){
this.s=s;
}
void getS(){
System.out.println(s);
}
}
class UseChild extends Use{
public String toString(){
return "I am UseChild";
}
}
class Use{
public String toString(){
return "I am Use";
}
public static void main(String[] args){
First <Use> f1 = new First <Use> (new Use());
f1.getS();
f1.setS(new UseChild());
f1.getS();
}
}
输出是:
I am Use
I am UseChild
直到现在好了。我以为我可以将子类对象传递给setS(),因为“T extends Use”在Type-parameter中,否则我不能。
但如果我使用不带extends关键字的type-parameter,则输出相同:
class First<T>
{
//Same code as above
}
我怀疑是: 如果我可以将子类对象传递给没有extends关键字的setS(),那么extends关键字有什么特别之处?
答案 0 :(得分:1)
假设Use
定义了一种新方法(而不是覆盖toString
):
class Use {
...
public void printMe() { // Some nonsensical method for demonstration
System.out.println("printing Use");
}
}
此绑定允许您从First
类调用此方法:
class First<T extends Use> {
T s;
...
public void getS() {
s.printMe(); // not possible without the bound.
}
}
您使用First
的方式,根本不需要泛型。使用Use
类型而不是T
可以使用相同的内容:
class First {
Use s;
First(Use s) {
this.s = s;
}
void setS(Use s) {
this.s = s;
}
void getS() {
System.out.println(s);
}
}
输出结果相同。
答案 1 :(得分:0)
此处Use
充当限制。它指定您只能传递Use
类型或扩展类型<T>
的对象。
更改为<T extends Object>
相当于First<T>
- 换句话说,您将能够传递任何对象。
不同之处在于LinkedList
您可以传递任何对象,例如JFrame
或First<T extends Use>
。使用Use
,您只能传递Use
类型的对象或类型为Use
的对象。
如果类型First
具有您希望类<T extends Use>
使用的某些方法,那么这种方法非常有用。在这种情况下,您需要指定First
,以便Use
了解FactoryInterface
类的方法和属性。
答案 2 :(得分:0)
任何泛型类的Type-parameter(T)都接受type-argument和类型为argument的子类。我们可以在setS()中传递UseChild的对象,即使使用Use as type-argument创建了First类的对象。因为UseChild是Use的子类。因此,以下陈述完全有效:
First<Use>f = new First<Use>(new Use());
f.setS(newUseChild());
有界和无界类型之间的差异并不像问题中所述。下面讨论实际差异:
如果我们不使用有界类型,则T扩展Object,s成为对象类型的引用变量。
class Use
{
public String toString()
{
return "I am Use";
}
public void call()
{
System.out.println("I am call of Use");
}
public static void main(String[] args)
{
First <Use> f1 = new First <Use> (new Use());
f1.getS();
}
}
让我们检查第一课的各个领域:
import java.lang.reflect.*;
class First<T>
{
T s;
First(T s)
{
this.s=s;
}
void setS(T s)
{
this.s=s;
}
void getS()
{
Field[] flds = this.getClass().getDeclaredFields();
for(Field f:flds)
{
String name = f.getName();
String type = f.getType().getName();
int i = f.getModifiers();
String modifier = Modifier.toString(i);
System.out.println("Name = "+name+" type= "+type);
}
System.out.println(s.getClass().getName());
}
}
输出是:
Name = s type= java.lang.Object
Use
所以T扩展了java.lang.Object。 s是java.lang.Object类型的引用变量。我们不能使用变量s调用Use特定方法。
让我们检查类的各个字段First With bound type:
import java.lang.reflect.*;
class First<T extends Use>
{
T s;
First(T s)
{
this.s=s;
}
void setS(T s)
{
this.s=s;
}
void getS()
{
Field[] flds = this.getClass().getDeclaredFields();
for(Field f:flds)
{
String name = f.getName();
String type = f.getType().getName();
int i = f.getModifiers();
String modifier = Modifier.toString(i);
System.out.println("Name = "+name+" type= "+type);
}
System.out.println(s.getClass().getName());
}
}
输出是:
Name = s type= Use
Use
所以现在T扩展了Use,而不是java.lang.Object。 s是Use类型的引用变量。正如@jorn vernee所说,我们现在可以调用First中的Use特定方法。