zea*_*eal 7 java generics static inner-classes
请仔细阅读整个问题以获得完整的想法.
首先让课程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());
}
}
Run Code Online (Sandbox Code Playgroud)
通用类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();
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码编译并执行得很好,我的不适就在于:
如果我们static在方法中添加修饰符
public <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) -------(1)
// called in method main1()
Run Code Online (Sandbox Code Playgroud)
并使它
public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) -------(2)
Run Code Online (Sandbox Code Playgroud)
然后编译器会抱怨无法对非静态类型的对进行静态引用,而类似的方法
public static <K> boolean cmp(Box<K> b1, Box<K> b2) -------(3)
Run Code Online (Sandbox Code Playgroud)
这也是静态但不抱怨.即使我们不使用类型参数<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)
Run Code Online (Sandbox Code Playgroud)
谢谢您的帮助.
原因是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>.
要将类型参数T保留在Util上并将Pair保持为非静态内部类,可以将compare的签名更改为
public static <T, K, V> boolean compare(Util<T>.Pair<K, V> p1, Util<T>.Pair<K, V> p2)
Run Code Online (Sandbox Code Playgroud)
要么
public static <K,V> boolean compare(Util<?>.Pair<K,V> p1, Util<?>.Pair<K,V> p2)
Run Code Online (Sandbox Code Playgroud)
这是可能的,因为T的实例化与方法的主体无关.
作为替代方案,由于Pair不引用Util内部的任何内容(非静态),您可以将Pair的定义更改为
public static class Pair <K, V> { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
最后,为了完整性,如果Util没有类型参数那么
public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2)
Run Code Online (Sandbox Code Playgroud)
和
public class Pair<K, V> { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
会没事的.
| 归档时间: |
|
| 查看次数: |
526 次 |
| 最近记录: |