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???