相关疑难解决方法(0)

为什么这个通用代码在java 8中编译?

我偶然发现了一段代码,让我想知道为什么它成功编译:

public class Main {
    public static void main(String[] args) {
        String s =  newList(); // why does this line compile?
        System.out.println(s);
    }

    private static <T extends List<Integer>> T newList() {
        return (T) new ArrayList<Integer>();
    }
}
Run Code Online (Sandbox Code Playgroud)

有趣的是,如果我修改方法的签名newList<T extends ArrayList<Integer>>它不工作了.

注释和响应后更新: 如果我将泛型类型从方法移动到类,则代码不再编译:

public class SomeClass<T extends List<Integer>> {
    public  void main(String[] args) {
        String s = newList(); // this doesn't compile anymore
        System.out.println(s);
    }

    private T newList() {
        return (T) new ArrayList<Integer>();
    }
}
Run Code Online (Sandbox Code Playgroud)

java generics compiler-errors java-8

42
推荐指数
3
解决办法
4254
查看次数

Java类型推断:Java 8中的引用不明确,但Java 7则不然

假设我们有2节课.一个空类Base,以及该类的子类Derived.

public class Base {}

public class Derived extends Base {}
Run Code Online (Sandbox Code Playgroud)

然后我们在另一个类中有几个方法:

import java.util.Collection

public class Consumer {

    public void test() {
        set(new Derived(), new Consumer().get());
    }

    public <T extends Base> T get() {
        return (T) new Derived();
    }

    public void set(Base i, Derived b) {
        System.out.println("base");
    }

    public void set(Derived d, Collection<? extends Consumer> o) {
        System.out.println("object");
    }

}
Run Code Online (Sandbox Code Playgroud)

这在Java 7中成功编译并运行,但不能在Java 8中编译.错误:

Error:(8, 9) java: reference to set is ambiguous
  both method set(Base,Derived) in Consumer …
Run Code Online (Sandbox Code Playgroud)

java generics type-inference compiler-errors java-8

26
推荐指数
2
解决办法
5277
查看次数

使用addAll()编译器的ArrayList显示泛型的不同行为

有人可以向我解释以下行为吗?

我有一个列表X并使用该addAll()方法添加元素.这些元素由使用泛型类型的方法返回.方法getA()返回< T extends A >A作为一类.方法getI()返回< T extends I >I作为一个接口(见下面的代码).

差异:listX.addAll(getA())我得到编译错误(如预期的那样),但是listX.addAll(getI())编译(当元素被强制转换时抛出运行时错误X).

简化代码:

interface I {}
class A implements I {}

class X {}

public void test() {   
    List<X> listX = new ArrayList<>();
    listX.addAll(getA());

    listX.addAll(getI());
    for (X x : listX) {}
}
public <T extends A> List<T> getA() {
    return new ArrayList<>();
}
public <T extends I> List<T> getI() …
Run Code Online (Sandbox Code Playgroud)

java generics java-8

17
推荐指数
2
解决办法
827
查看次数

表观类型违规,但编译

为什么下面的代码片段会编译?OtherInterface没有扩展,Concrete所以我打赌肾脏,这将无法编译.但确实如此.

public class Test {

    public static interface SomeInterface {}

    public static interface OtherInterface{}

    public static class Concrete implements SomeInterface {

       public <T extends Concrete> T getConcrete() {
            return null;
       }
    }

    public static void doStuff() {
        Concrete c = new Concrete();
        OtherInterface iCompile = c.getConcrete();
    }
}
Run Code Online (Sandbox Code Playgroud)

另一方面,下一个片段不能编译,这是我所期望的.

public class Test {

    public static interface SomeInterface {}

    public static class UnrelatedClass{}

    public static class Concrete implements SomeInterface {

       public <T extends Concrete> T getConcrete() { …
Run Code Online (Sandbox Code Playgroud)

java generics

14
推荐指数
1
解决办法
149
查看次数

Java 8类型的推理错误?

我知道之前已经发布了类似的类型推断问题(Java编译器选择了错误的重载为什么Java 8泛型类型推断选择了这个重载?)但我认为我们在这里选择了一个更有趣的案例.

public class TemplateMethod {

    public static void main(String[] args) {
        System.out.println(System.getProperty("java.version"));
        method("a", "b");
        method("a", 5);
        method("a", new B().get());
    }


    public static void method(String s, String cause) {
        System.out.println("String");        
    }

    public static void method(String s, Object parameters) {
        System.out.println("Object");
    }

    public static interface Base {
        String methodToImplement();
    }

    public static class Impl implements Base {
        public String methodToImplement() {
            return "Impl.methodToImplement";
        }
    }

    public static class B {
        public <T extends Base> T get() { …
Run Code Online (Sandbox Code Playgroud)

java generics java-8

8
推荐指数
0
解决办法
179
查看次数

Java 8泛型函数应该是模糊的,但在运行时失败

我正在尝试将Java 7代码迁移到Java 8,所以我的代码类似于:

package tests;

import java.util.Arrays;
import java.util.Map;

public class Tests {
    private static interface ComparableMap<K,V> extends Map<K,V>, Comparable {}

    public static void main(String[] args) {
        func(getString());
    }

    private static void func(Comparable...input){
        System.out.println(Arrays.toString(input));
    }

    private static void func(ComparableMap <?,?> m){
        System.out.println(m);
    }

    private static <T extends Comparable> T getString(){
        return (T) "aaa";
    }
}
Run Code Online (Sandbox Code Playgroud)

在java 7中它正常工作,在Java 8中我得到:

java.lang.ClassCastException:java.lang.String无法强制转换为tests.Tests $ ComparableMap

如果我将一个函数定义更改为:

    private static <T> T getString(){
        return (T) "aaa";
    }
Run Code Online (Sandbox Code Playgroud)

编译将失败:错误:

对func的引用含糊不清

为什么Java 8编译器在第一种情况下没有失败?(看起来对我来说是错误的)是否可以更改第二个重载函数,以便在不更改调用本身的情况下使用varargs参数调用第一个函数?

java generics variadic-functions overload-resolution java-8

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

List和ArrayList在泛型中的特殊行为

以下代码工作正常,而不应该compile.

我不知道为什么一个分配ListString被允许的.

它只发生在List接口上.Array List按预期更改为工作正常,不再编译.

public class Test {
        public static <T extends List<Number>> T newList() {
            return null;
        }

        public static void main(String[] args) {
            String s = newList();
        }
    }
Run Code Online (Sandbox Code Playgroud)

请帮我理解这个行为.

java list

7
推荐指数
0
解决办法
80
查看次数

如何推断泛型方法调用的类型参数?

有这样的方法吗?

public <P, T extends List<P>> T getAwesomeList() {
    // ...
} 
Run Code Online (Sandbox Code Playgroud)

怎么编译没有任何警告?

Set<String> test = getAwesomeList();
Run Code Online (Sandbox Code Playgroud)

我认为这与通用擦除有关,但不确定编译器是怎么回事.这种情况发生在Java 7上,8时你会收到编译错误.

J8上有什么变化让这个不能编译?

更新:

经过仔细检查后,它还可以在Java 8上编译.

java generics type-inference java-7 java-8

6
推荐指数
0
解决办法
238
查看次数

为什么 Java 允许使用泛型编译这段代码?

我最近被以下 Java 代码惊呆了:

interface Common {}

interface A extends Common {}

static class B implements Common {}

static class Impl {
  private A a;

  public <T extends A> T translate() {
    return (T) a;
  }
}

static class Usage {
  public void use() {
    Impl impl = new Impl();
    B b = impl.translate(); // Why does this compile?
  }
}
Run Code Online (Sandbox Code Playgroud)

我本来期望的是在类型约束Impl.translate不会允许将结果存储在类型B由编译器所接受,考虑到B不延长A。代码UncheckedCastException在运行时抛出一个,而不是编译器错误。

这仅在方法返回类型时发生T;如果它是方法参数:

  public <T extends A> …
Run Code Online (Sandbox Code Playgroud)

java generics

6
推荐指数
2
解决办法
181
查看次数

使用JDK 8编译泛型方法时损坏

我有一些遗留代码Box用于将Serializable数据放入并获取数据Map,Oracle JRE 1.8 Update 102在编译时运行正常Oracle JDK 1.7 Update 80.但是当我编译它时,它无法正常运行Oracle JDK 1.8 Updater 102.我在泛型get函数方面遇到了一些问题.

SSCCE Box使用有问题的通用get函数从实例输出格式化日期:

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;

public class Box implements Serializable{

   private HashMap<String, Serializable> values = new HashMap<String, Serializable>();

   public <T extends Serializable> T get(String key){

      return (T) this.values.get(key);
   }

   public void put(String key,
                   Serializable value){

      this.values.put(key,
                      value);
   }

   public static void main(String[] args){

      Box box = new …
Run Code Online (Sandbox Code Playgroud)

java generics java-8

4
推荐指数
1
解决办法
595
查看次数

填写清单<?延伸Foo>

拥有一组抽象对象: Set<Foo> foes;

我想要一个像这样的方法:

List<? extends Foo> getFoesByType(TypeEnum type);
Run Code Online (Sandbox Code Playgroud)

我试过了:

List<? extends Foo> result = new ArrayList<>();
for(Foo f : foes) {
        if(f.getType() == type) {
            switch(type) {
            case TYPE1:
                f = (FooType1) f;
                break;
            case TYPE2:
                /*...*/
            }

            result.add(f);  
            /*The method add(capture#1-of ?) in the type 
            List<capture#1-of ?> is not applicable for the arguments (Foo)*/
        } 
}  

return result;
Run Code Online (Sandbox Code Playgroud)

但是我收到了一个错误.

我希望能够做到这一点:List<FooType1> foesType1 = getFooesByType(TypeEnum.TYPE1);哪种方法是正确的?

java java-8 bounded-wildcard

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