请仔细阅读整个问题以获得完整的想法。
首先让课程Box
给出如下: -
public class Box <T>{
private T t;
public void set(T t){
this.t = t;
System.out.println("value:\n");
System.out.printf("%s", t.toString());
}
public T get() {
return t;
}
static int retInt(){
return 5;
}
public <U extends Number> void inspect(U u){
System.out.println("T: " + t.getClass().getName());
System.out.println("U: " + u.getClass().getName());
}
}
通用课程Util
如下: -
public class Util<T>{
private T t;
//Generic method
public <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
/* Static generic or non-generic methods can be declared in generic class
but they can not make use of generic parameter type(as generics static
methods using class type variable must know the type argument
(i.e value of type parameter); and knowledge of type argument is
possible only when object of same generic class are instantiated
(meaning assigning value of generic type parameter <T> or better to
say declared object have it's type argument; for example
as in List<T> replace T with Integer,String, Float etc);
but static method may be called without having
instance of class; so such declaration for static generic method are
not allowed) here it is <T>; like for example as shown below
public static int checkFun(T t){
return 5;
} // this generate compiler error complaining "can not make static
// reference to non-static type T".
*/
public static <K> boolean cmp(Box<K> b1, Box<K> b2){
// implement comparator to compare but here
return true;
}
// Inner class Pair
public class Pair <K, V> {
private K key;
private V value;
// Generic constructor
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public void setKey(K key) {
int i = 6;
if(i >4 || i<9);
this.key = key;
}
public void setValue(V value) {
this.value = value;
}
public K getKey(){
return key;
}
public V getValue(){
return value;
}
}
public void main1() {
//The complete syntax for invoking this method would be:
// <Integer, String> new Util<T>().
Pair<Integer, String> p1 = new Pair<Integer,String>(1, "apple");
Pair<Integer, String> p2 = new Pair<Integer, String>(2, "pear");
boolean same = compare(p1, p2);
//boolean same = true;
if(same)System.out.println("it is true: they are the same");
else System.out.println("nah! they are not the same...");
//boolean sm = compare();
}
public static void main (String[] args) /*throws FileNotFoundException */{
//new Util<Integer>(). main1();
Util<Integer> util = new Util<>();
util.main1();
}
}
上面的代码编译并执行得很好,我的不适就在于:
如果我们向方法
添加static
修饰符
public <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) -------(1)
// called in method main1()
并制作
public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) -------(2)
然后编译器会抱怨无法对非静态类型对进行静态引用而类似方法
public static <K> boolean cmp(Box<K> b1, Box<K> b2) -------(3)
这也是静态但不抱怨。即使我们在<T>
方法but
中没有使用类型参数big but
,我们在eq-1
中讨论它所使用的参数来自内部类Pair
(因此可以参考此功能解释我的歧义的推理)。
但仍然;从逻辑上讲,我觉得向static
中的方法添加修饰符eq-1
不应该生成编译时错误,因为无论调用eq-2
中的方法,都应该使用正确的参数调用该方法到eq-2
中的方法,应该允许它像静态方法一样被调用。
问题: - 不对该方法使用静态修饰符的解释是什么:
public <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2)
感谢您的帮助。
答案 0 :(得分:9)
这样做的原因是Util类的类型参数和内部类Pair是非静态的。因为Pair是一个非静态内部类,所以它可以使用Util的T类型参数(即使在这种情况下它不会)。因此,当使用Pair时,必须通过在Util实例的上下文中访问它(T隐式可用)来指定T,或者通过通过特定Util<T>
访问它来进行限定。 Util<Integer>.Pair<String,Object>
。另一种思考方式是,Pair的类型取决于Util的类型参数,而Util<String>.Pair<K,V>
与Util<Object>.Pair<K,V>
不兼容。
要保持Util上的类型参数T并将Pair保持为非静态内部类,您可以将compare的签名更改为
public static <T, K, V> boolean compare(Util<T>.Pair<K, V> p1, Util<T>.Pair<K, V> p2)
或
public static <K,V> boolean compare(Util<?>.Pair<K,V> p1, Util<?>.Pair<K,V> p2)
这是可能的,因为T的实例化与方法的主体无关。
作为替代方案,由于Pair不引用Util内部的任何内容(非静态),您可以将Pair的定义更改为
public static class Pair <K, V> { /* ... */ }
最后,为了完整性,如果Util没有类型参数,那么
public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2)
和
public class Pair<K, V> { /* ... */ }
会没事的。