相关疑难解决方法(0)

为什么java.lang.Class的getInterfaces()方法返回Class <?> []而不是Class <?超级T> []?

(要清除问题,'T'指的是在Class中声明的类型参数)

举个例子,请查看以下应用程序:

public class TestClass {

    interface InterfaceA{}

    interface InterfaceB{}

    interface InterfaceC{}

    class ClassA implements InterfaceA, InterfaceB,  InterfaceC{}


    public static void main(String[] args){    

        Class<? super ClassA> superClass1 = ClassA.class;
        Class<? super ClassA> superclass2 = InterfaceA.class;
        Class<? super ClassA> superclass3 = InterfaceB.class;
        Class<? super ClassA> superclass4 = InterfaceC.class;

        for(Class<?> clazz : ClassA.class.getInterfaces()){
            System.out.println(clazz.getName());
        }   
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是人们所期望的:

TestClass$InterfaceA
TestClass$InterfaceB
TestClass$InterfaceC
Run Code Online (Sandbox Code Playgroud)

因此,基于上面的这个例子,我们可以看到编译器认识到InterfaceA 确实符合通配符的边界,所有其他接口也是如此.

直观地说,我希望以下是安全的,但它不是:

Class<? super ClassA>[] interfaces = ClassA.class.getInterfaces();
Run Code Online (Sandbox Code Playgroud)

编译器发出警告,因为签名表示它返回Class; 但是,Class的javadoc声明如下:

如果此对象表示类,则返回值是一个数组,其中包含表示该类实现的所有接口的对象.

'这个对象'在我们的例子中指的是ClassA.基于此声明,如果我们致电:

ClassA.class.getInterfaces()
Run Code Online (Sandbox Code Playgroud)

然后我们从逻辑上知道Class<?>返回数组中的每一个都将包含对超类型的引用ClassA …

java generics interface bounded-wildcard

12
推荐指数
1
解决办法
2139
查看次数

为什么Java中没有实例级的Stream.concat方法?

我知道Stream.concat存在(doc)来连接两个流.但是,我遇到了需要在现有流中添加"更多"项目,然后继续处理它的情况.在这种情况下,我本来希望能够将以下方法联系在一起:

getStream(someArg)
  .map(Arg::getFoo)
  .concat(someOtherStreamOfFoos) // Or append, or...
  .map(...)
Run Code Online (Sandbox Code Playgroud)

但是,不存在这种实例级可链接append/concat方法.

这不是一个问题,要求解决这个问题,或更优雅的方法(虽然我当然会感激任何其他观点!).相反,我问的是导致这一决定的设计因素.我相信,Stream界面是由一些非常聪明的人设计的,他们都知道最小惊讶原则 - 所以,我必须假设他们决定省略这个(对我来说)直观明显的方法,这意味着该方法是一个反模式,或由于某些技术限制而无法实现.我很想知道原因.

java java-8 java-stream

12
推荐指数
1
解决办法
292
查看次数

为什么Collection.toArray(T [])不采用E []

toArray方法(可以接在执行java.util.ArrayList)如下:

class ArrayList<E> ....{
    public <T> T[] toArray(T[] a){
        if(a.length < size)
            return (T[]) Arrays.copyof(elementData, size, a.getClass());
        System.arraycopy(elementData, 0, a, 0, size);
        if(a.length > size)
            a[size] = null;
        return a;
    }    
}
Run Code Online (Sandbox Code Playgroud)

我想知道我们可以使用<E>而不是<T>在这种情况下吗?喜欢

public E[] toArray(E[] a){
      if(a.length < size)
             return (E[]) Arrays.copyof(elementData, size, a.getClass());
      System.arraycopy(elementData, 0, a, 0, size);
      if(a.length > size)
            a[size] = null;
      return a;
}    
Run Code Online (Sandbox Code Playgroud)

由于ArrayList类iteself已经是通用的<E>,所以我们可以使用它而不是新的泛型类型<T>吗?

java generics arraylist

11
推荐指数
2
解决办法
733
查看次数

如何在单个约束中使用方法和类类型参数?

我将尝试在以下简化示例中说明我的问题:

public class DataHolder<T> {
  private final T myValue;

  public DataHolder(T value) {
    myValue = value;
  }

  public T get() {
    return myValue;
  }

  // Won't compile
  public <R> DataHolder<R super T> firstNotNull(DataHolder<? extends R> other) {
    return new DataHolder<R>(myValue != null ? myValue : other.myValue);      }

  public static <R> DataHolder<R> selectFirstNotNull(DataHolder<? extends R> first,
                                                     DataHolder<? extends R> second) {
    return new DataHolder<R>(first.myValue != null ? first.myValue : second.myValue);
  }
}
Run Code Online (Sandbox Code Playgroud)

在这里,我想写泛型方法firstNotNull返回DataHolder的类型参数的共同参数化父Tthis和 …

java generics

11
推荐指数
1
解决办法
151
查看次数

Java中破坏的逆变边界的安全解决方法?

正如Bounding泛型中使用'super'关键字所讨论的那样,当涉及到方法泛型的下限时,Java类型系统被破坏/不完整.由于Optional现在是JDK的一部分,我开始更多地使用它,并且Guava遇到的问题与他的可选性开始变得困难.我提出了一个体面的工作,但我不确定它是否安全.首先,让我设置一个例子:

public class A {}
public class B extends A {}
Run Code Online (Sandbox Code Playgroud)

我希望能够声明一个方法,如:

public class Cache {
   private final Map<String, B> cache;
   public <T super B> Optional<T> find(String s) {
       return Optional<T>.ofNullable(cache.get(s));
   }
}
Run Code Online (Sandbox Code Playgroud)

以下两项工作:

A a = cache.find("A").orElse(new A())
B b = cache.find("B").orElse(new B())
Run Code Online (Sandbox Code Playgroud)

作为一种解决方法,我有一个静态实用方法如下:

public static <S, T extends S> Optional<S> convertOptional(Optional<T> optional) {
    return (Optional<S>)optional;
} 
Run Code Online (Sandbox Code Playgroud)

所以我的最后一个问题是,这是上述"理想"代码的类型安全吗?

A a = OptionalUtil.<A,B>convertOptional(cache.find("A")).orElse(new A());
Run Code Online (Sandbox Code Playgroud)

java generics

9
推荐指数
1
解决办法
243
查看次数

是不是<U,T延伸U>和<T,U super T>相同?

我对以下两个方法声明感到困惑:

    private <U, T extends U> T funWorks(T child, U parent) {
      // No compilation errors
    }

    private <T, U super T> T funNotWorks(T child, U parent) {
      // compilation errors    
    }
Run Code Online (Sandbox Code Playgroud)

以上两者都不应该有效吗?比喻 如果U是T的父,那么T是U的子.那为什么第二个会出现编译错误?

编辑::我认为,T extends TT super T都是有效的.对 ?

java generics collections type-parameter

8
推荐指数
1
解决办法
384
查看次数

带有有界通配符的 Java Map.getOrDefault

得到一个Map<String, ? extends Map<String, Integer>> mapOfMaps变量。

Map<String, Integer> result = mapOfMaps.get("aaa");
Run Code Online (Sandbox Code Playgroud)

有效,但是

Map<String, Integer> result = mapOfMaps.getOrDefault("aaa",Collections.emptyMap());
Run Code Online (Sandbox Code Playgroud)

类型 Map<String,capture#1-of ? 中的方法 getOrDefault(Object, capture#1-of ? extends Map<String,Integer>) extends Map<String,Integer>> 不适用于参数 (String, Map<String,Integer>)

同样适用于

Map<String, Integer> result = mapOfMaps.getOrDefault("aaa",Collections.<String,Integer>emptyMap());
Run Code Online (Sandbox Code Playgroud)

或者

Map<String, Integer> result = mapOfMaps.getOrDefault("aaa",(Map<String,Integer>)Collections.EMPTY_MAP);
Run Code Online (Sandbox Code Playgroud)

甚至

Map<String, Integer> result = mapOfMaps.getOrDefault("aaa",new HashMap<String, Integer>());
Run Code Online (Sandbox Code Playgroud)

有没有办法像这样使用 getOrDefault 或者我必须使用笨重的方式?

Map<String, Integer> result = mapOfMaps.get("aaa");
if( result == null ) {
  result = Collections.emptyMap();
}
Run Code Online (Sandbox Code Playgroud)

java generics

7
推荐指数
1
解决办法
378
查看次数

Java泛型:通配符

因此,我正在阅读泛型,以便重新熟悉这些概念,特别是在涉及通配符的情况下,因为我几乎没有使用它们或碰到它们.从我所做的阅读中我无法理解为什么他们使用通配符.我不断遇到的一个例子如下.

void printCollection( Collection<?> c ) {
  for (Object o : c){
    System.out.println(o);
  }
}
Run Code Online (Sandbox Code Playgroud)

为什么你不写这个:

<T> void printCollection( Collection<T> c ) {
    for(T o : c) {
        System.out.println(o);
    }
}
Run Code Online (Sandbox Code Playgroud)

来自oracle网站的另一个例子:

public static double sumOfList(List<? extends Number> list) {
    double s = 0.0;
    for (Number n : list)
        s += n.doubleValue();
    return s;
}
Run Code Online (Sandbox Code Playgroud)

为什么这不是写的

public static <T extends Number> double sumOfList(List<T> list) {
    double s = 0.0;
    for (Number n : list)
        s += n.doubleValue();
    return s;
} …
Run Code Online (Sandbox Code Playgroud)

java generics

6
推荐指数
1
解决办法
194
查看次数

使用下限通配符(Java)的"意外令牌"

我有类似的东西:

interface Foo<T> {
    //... lines [0,45]...

/*line 46*/ <R, X super T&R> List<X> weave(R value);
    //...
}
Run Code Online (Sandbox Code Playgroud)

但是IntelliJ正在报道:

  1. 错误:(46,18)java:>预期
  2. 错误:(46,19)java:非法启动类型
  3. 错误:(46,26)java:'('预期
  4. 错误:(46,28)java:<identifier>预期
  5. 错误:(46,29)java:'l'预计
  6. 错误:(46,43)java:<identifier>预期

有什么问题?我不允许将名字绑定到下限吗?或者我只允许R&X在上限中使用表达式?

把它改成

interface Foo<T> {
    //... lines [0,45]...

/*line 46*/ <R> List<? super T&R> weave(R value);
    //...
}
Run Code Online (Sandbox Code Playgroud)

产量

  1. 错误(46,31)java:>预期
  2. 错误(46,32)java:'('预期
  3. 错误(46,33)java:非法启动类型

java generics syntax-error bounded-wildcard

5
推荐指数
1
解决办法
994
查看次数

为什么不可能有逆变返回类型

我正在玩Java中的泛型,我发现了一些奇怪的东西:


以下编译:

public static <A, B extends A> B reduce(Function2<A, A, B> func)
{  
   //code doesn't matter
}
Run Code Online (Sandbox Code Playgroud)


但以下不是:

public static <A, B super A> B reduce(Function2<A, A, B> func)
{  
   //code doesn't matter
}
Run Code Online (Sandbox Code Playgroud)


在我看来上面是完全有效的(毕竟,这几乎是Scala集合中reduce方法的签名).


为什么Java不允许逆变返回类型,特别是在这种情况下,因为将推断返回(通过Function2的第三个参数)?

java generics contravariance

5
推荐指数
0
解决办法
54
查看次数

Java泛型类型中的"super"关键字有什么问题

我在项目中遇到了一个奇怪的问题.现在我简化了问题并在这里写了一个小例子来说明我的困惑:

public class Question {
    class Q1 {}

    class Q2 extends Q1 {}

    interface In<T> {
        void f(T t);
    }

    List<Q2> list;

    void f(In<? super List<? super Q2>> in) {
        in.f(list);
    }

    static void g() {
        Question question = new Question();
        In<Collection<Q1>> in1 = new In<Collection<Q1>>() {
            @Override
            public void f(Collection<Q1> o) {}
        };
        In<List<Q2>> in2 = new In<List<Q2>>() {
            @Override
            public void f(List<Q2> o) {}
        };
        question.f(in1); //Error!
        question.f(in2); //Error!
    }
}
Run Code Online (Sandbox Code Playgroud)

我的目标是使该方法f(In<? super List<? super Q2>>)更灵活.我可以通过 …

java super generic-type-argument

5
推荐指数
1
解决办法
229
查看次数