0

I am trying to extend “Intersection of interfaces”. So: the example that I am following is trying to find superinterfaces for RandomAccessFile (Implemented Interfaces: Closeable, DataInput, DataOutput, AutoCloseable ) and DataInputStream(Implemented Interfaces: Closeable, DataInput, AutoCloseable ) and therefore we at least have an intersection on Closeable and DataInput (of course I can make an intersection with AutoCloseable ): So the code goes something like this:

private static <I extends DataInput & Closeable> Person read(I source) {
    try (I input = source) {
        return new Person(input.readLine(), Integer.valueOf(input.readLine()));         
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

And it works just great when I do:

public static void main(String[] args) throws IOException {  
    RandomAccessFile input = new RandomAccessFile("src\\main\\resorces\\person.txt", "rw");
    Person person2 = read(input);
    System.out.println(person2.toString());

}

BUT when I do:

public static void main(String[] args) throws IOException {     
    DataInputStream stream = new DataInputStream(new
        FileInputStream("src\\main\\resorces\\person.txt")); 
    Person person = read(stream); 
    System.out.println(person.toString());       

}

It throws me an execption:

Exception in thread "main" java.lang.NoSuchMethodError: `java.io.DataInput.close()V
at com.test.java8.l03.generics.Person.read(Person.java:34)
at com.test.java8.l03.generics.Person.main(Person.java:20)

Here is all of the code:

public class Person {

    public static void main(String[] args) throws IOException {

        /*DataInputStream stream = new DataInputStream(new FileInputStream("src\\main\\resorces\\person.txt"));
        Person person = read(stream);
        System.out.println(person.toString());*/


        RandomAccessFile input = new
          RandomAccessFile("src\\main\\resorces\\person.txt", "rw"); 
        Person person2 = read(input); System.out.println(person2.toString());
    }

    private static <I extends DataInput & Closeable> Person read(I source) {
        try (I input = source) {
            return new Person(input.readLine(), Integer.valueOf(input.readLine()));
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

    }

    private static Person read(RandomAccessFile source) {
        try (RandomAccessFile input = source) {
            return new Person(input.readLine(), Integer.valueOf(input.readLine()));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }

    }

    private final String name;
    private final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;

    }
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}

I would not expect this error since intersect interface I extends Closeable. Can anyone help me with this?

However having interfaces permute an exception is not thrown:

private static <I extends Closeable & DataInput> Person read(I source) {
try (I input = source) {
    return new Person(input.readLine(), Integer.valueOf(input.readLine()));
} catch (IOException e) {
    e.printStackTrace();
    return null;
}

}

Is it possible that intersection of interfaces is not an equivalence relation (to be more precise that intersection on this operands is not reflexive) and that compiler is taking the left side interface as a return value?

Related to this: DataInputStream implements DataInput and extends abstract class InputStream which implements Closeable. RandomAccessFile implements DataInput and Closeable directly therefore RandomAccessFile has to have method close() implemented and DataInputStream does not(it can use method from superclass that is implementing Closeable interface)? So maybe a compiler gets confused here when using dynamic method dispatch???

trinity
  • 571
  • 8
  • 14
  • 1
    Check (and provide us the information) 1. JDK version you used to build 2. JDK/JRE version you used to execute. However, I kind of recall that when performing type erasure to type param with multiple bounds, it is erasing to the leftmost type. However it shouldn't affect your case as compiler should have added appropriate casting. I guess it is the version of JDK you are using is having a bug on this – Adrian Shum Sep 20 '16 at 01:59
  • 1
    Was closed as duplicate of http://stackoverflow.com/questions/32180358/java-lang-nosuchmethoderror-com-google-common-io-closeables-closequietlyljava but after looking at the question, there seems to be no relationship between the 2 questions, so I repoened it – Adrian Shum Sep 20 '16 at 02:10
  • I have just tried this on another computer with same java version: `java version "1.8.0_40" Java(TM) SE Runtime Environment (build 1.8.0_40-b26) Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)` And again I got: `Exception in thread "main" java.lang.NoSuchMethodError: java.io.DataInput.close()V at com.test.java8.l03.generics.Person.read(Person.java:34) at com.test.java8.l03.generics.Person.main(Person.java:24)` – trinity Sep 20 '16 at 09:35
  • In Bounded Type Parameter with Multiple Bounds if one of the bounds is a class, it must be specified first(most left) or compile-time error arises. So I guess that listing order of bounds counts, even if containing just interfaces, therefore even if not completely unexpected behavior is most certainly excessive, especially coming from such a divine thing. Is this a bug or I am missing something importanat? – trinity Sep 20 '16 at 09:37
  • Here is the example I created based on your example, and it worked fine https://gist.github.com/adrianshum/6a4a8617c548c876571bf673cf434f25 Can you verify if it is working on your side too? (I am using JDK 1.8.0_25-b18 for build and running) . By the way, for the "left-most bound" what I said is "when type-erasure happen", which is actually irrelevant from what you mentioned :) – Adrian Shum Sep 20 '16 at 09:52
  • and, from the stack trace, it seems to be more related to be the compilation issue, so make sure you have compiled using different version of JDK – Adrian Shum Sep 20 '16 at 09:56
  • Your code works just fine when I do `` but still the sam error with ``. I will try another version of JDK after work. Thank you. – trinity Sep 20 '16 at 10:29
  • Kind of further prove it is related to JDK version (which may also imply it is a bug in JDK). Will be great if you can share your test result on other JDK – Adrian Shum Sep 21 '16 at 01:59

0 Answers0