Apparent type violation, but compiles [duplicate] - java

This question already has answers here:
String gets assigned to a List without a compilation error [duplicate]
(1 answer)
Why can this generic method with a bound return any type?
(1 answer)
Generic return type upper bound - interface vs. class - surprisingly valid code
(2 answers)
Closed 5 years ago.
Why does the below snippet compile ? OtherInterface does not extends Concrete so I would have bet a kidney that this wouldn't compile. But it does.
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();
}
}
On the other hand, the next snippet does not compile, which is what I expect.
public class Test {
public static interface SomeInterface {}
public static class UnrelatedClass{}
public static class Concrete implements SomeInterface {
public <T extends Concrete> T getConcrete() {
return null;
}
}
public static void doStuff() {
Concrete c = new Concrete();
UnrelatedClass iCompile = c.getConcrete();
}
}

The difference is here:
public static interface OtherInterface{} ...
OtherInterface iCompile = c.getConcrete();
vs.
public static class UnrelatedClass{} ...
UnrelatedClass iCompile = c.getConcrete();
Meaning: in the first case, you call the method to return an instance of some interface. Interfaces can be any class.
In the second example, you instruct that returned type is of be a specific class! A class which is known, and that does not implement that other interface!
And the error message:
reason: no unique maximal instance exists for type variable T with upper bounds UnrelatedClass,Concrete
is pretty specific here.
In other words: the compiler factors in the left hand side of that assignment - to determine the valid types. And UnrelatedClass can never be a Concrete - because the class UnrelatedClass does not extend Concrete!
Whereas something that is SomeInterface can as well implement OtherInterface.

Related

Java Incompatible equality constraint in list

I have a multi level class structure and want to pass their implementation to a function that can call functions on them, but I get an Incompatible equality constraint: Test.SubDTO2 and Test.SubDTO error.
Here is the code:
public class Test {
abstract class DTO { }
class SubDTO extends DTO implements Interf{ }
class SubDTO2 extends DTO implements Interf{ }
class DAO<T extends DTO> { }
interface Interf { }
static DAO<SubDTO> daoImpl1;
static DAO<SubDTO2> daoImpl2;
public static void main(String... args) {
func(Arrays.asList(daoImpl1, daoImpl2)); // <- error is in this line
}
static <T extends DTO & Interf> void func(List<DAO<T>> arg) {
}
}
A more detailed example on what I try to achieve:
public class Test {
abstract class DTO {
abstract void func1();
}
class SubDTO extends DTO implements Interf{
#Override
public void func2() {
// comes from Interf
}
#Override
public void func1() {
// comes from DTO
}
}
class SubDTO2 extends DTO implements Interf{
#Override
public void func2() {
// comes from Interf
}
#Override
public void func1() {
// comes from DTO
}
}
class DAO<T extends DTO> {
public T dto() {
return null;
}
}
interface Interf {
void func2();
}
static DAO<SubDTO> daoImpl1;
static DAO<SubDTO2> daoImpl2;
public static void main(String... args) {
func(Arrays.asList(daoImpl1, daoImpl2));
}
static <T extends DTO & Interf> void func(List<? extends DAO<? extends DTO>> arg) {
arg.get(0).dto().func1(); // <- I can't call func2() here
}
}
exact error message:
[ERROR] required: java.util.List<Test.DAO<T>>
[ERROR] found: java.util.List<Test.DAO<? extends Test.DTO>>
[ERROR] reason: inference variable T has incompatible equality constraints Test.SubDTO2,Test.SubDTO
I need the list in the function func to extend DTO and also implement Interf as well, because I call certain functions on them.
Why is this happening? It works fine if I change the signature of the func and pass only one DAO, but I need it to work with multiple.
What are my options here?
I tried it with multiple java versions (1.8+), all the same.
Your function should be declared like this:
static <T extends DTO & Interf> void func(List<DAO<? extends T>> arg) {
Notice that I changed List<DAO<T>> to List<DAO<? extends T>>. This is because the expression Arrays.asList(daoImpl1, daoImpl2) produces a value of type
List<DAO<? extends DTO & Interf>>
(Of course, this isn't real syntax for a type in Java. There's no syntax for intersection types in Java but Java does know about them when doing type inference, and you could have these types in your code if you use var. I use this notation here just for illustrative purposes.)
If you know PECS, you'll know that this is a list of DAOs that produces DTO & Interfs/Ts, but does not consume DTO & Interfs/Ts. If you are lost at this point, please go read the PECS post - it's great. See also: Difference between <? super T> and <? extends T> in Java
The reason why it does this is quite intuitive. Imagine if DAO is just a container for a T.
static class DAO<T extends DTO> {
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
If Arrays.asList(daoImpl1, daoImpl2) had produced a list of DAO<DTO & Interf> (with no extends or super), you'd be able to call getT and setT on elements of the list! And being able to call setT is especially dangerous you see - you'd be able to do this:
// suppose arg is a List<DAO<DTO & Interf>>
arg.get(someRandomNumber).setT(new SubDTO());
What if someRandomNumber happens to be 1, and we get the second element, which is a DAO<SubDTO2>? Putting a SubDTO inside that destroys the whole type-safety of generics.
The only type-safe thing to do on elements of such a list like [daoImpl1, daoImpl2] is to use them as producers of DTO & Interfs, hence the type is marked ? extends DTO & Interf. This means that if you have any methods on DAO that takes in a T, you won't be able to call them on elements of this list*.
Also note that, just in case I was not clear, it is not the list that is only a producer - the list is both a producer and consumer of DAOs. It's just that the DAOs in the list are producers of their Ts.
* except by passing nulls.

java generics: Bound mismatch for string

my code is as below, and I got the error message Bound Mismatch Error: The type String is not a valid substitute for the bounded parameter <K extends myComparable<K>> of the type myInterface<K,V>:
interface myComparable<T> {
public int compareTo(T o);
}
interface myInterface<K extends myComparable<K>, V> {
}
public class myClass implements myInterface<String,String>{
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
However, if I changed K extends myComparable<K> to K extends Comparable<K> (without changing the first line; i.e. to use Comparable instead of myComparable), the error will be solved.
Why? And how can I use my own myComparable?
I finally got a solution (i.e. to use myString instead of String):
interface myComparable<T> {
public int compareTo(T o);
}
interface myInterface<K extends myComparable<K>, V> {
}
class myString implements myComparable<myString>{
#Override
public int compareTo(myString o) {
return 0;
}
}
public class myClass implements myInterface<myString,myString>{
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
When you write implements myInterface<String, String>, you're 'binding' the K type variable to String and the V type variable to String.
The declaration of the K type variable in particular has a bound on it: You've declared it as myInterface<K extends myComparable<K>, V> which means that any bound you pick for K must at least 'fit' this restriction.
And it doesn't, which is why the compiler won't let you.
The java.lang.String class actually implements Comparable<String> - it's right there in the javadoc as well as the source if you care to look; you can also just cast it:
Comparable<String> test = "hello"; // this compiles and runs fine.
The reason is that string was written by sun/oracle as: public final class String implements Comparable<String>.
It was not written with implements myComparable<String>.
It is not possible to make java.lang.String implement your interface.
That is not how interfaces work; java is nominally and not structurally typed: You can't decree that all Strings are myComparables, just because they so happen to have a compareTo method.
Imagine it worked that way and I wrote this class:
public class Gun {
public void shoot(Person person) { ... }
}
quite a dangerous class!
Let's say it worked the way you appear things are. Then I could do:
public interface Camera {
public void shoot(Person p);
}
Camera c = new Gun();
c.shoot(somebody);
and good grief, now we have an extremely dangerous situation going on. Fortunately, java does not work this way; A Gun is not a Camera. Eventhough it so happens to have all the methods that the Camera interface declared.
You can make your own types that implement your own interfaces, of course. That's no problem. However, in general, it doesn't seem useful to make an interface named myComparable.

Subclasses with generics of subclasses

I have some issues with generics. I have a BaseObject with multiple sub-classes as well as a BaseContainer<T extends BaseObject> with sub-classes that correspond with BaseObject sub-classes.
public class TestClass extends BaseClass<BaseContainer<BaseObject>> {
// method signature tied to BaseClass generic
#Override
private BaseContainer<BaseObject> createContainer() {
BaseContainer<BaseObject> container;
// example logic here to determine which container to use
if (Math.random() < 0.5) {
container = new Parent1Container(); // incompatible types
} else {
container = new Parent2Container(); // incompatible types
}
return container;
}
abstract static class BaseObject {}
static class Parent1Object extends BaseObject {}
static class Parent2Object extends BaseObject {}
abstract static class BaseContainer<T extends BaseObject> {
public abstract void foo(T object);
}
static class Parent1Container extends BaseContainer<Parent1Object> {
public void foo(Parent1Object object) {}
}
static class Parent2Container extends BaseContainer<Parent2Object> {
public void foo(Parent2Object object) {}
}
}
public class BaseClass<T extends BaseContainer> {
public abstract T createContainer();
}
I have a method that returns BaseContainer<BaseObject>. Unfortunately, instantiating sub-classes of BaseContainer results in incompatible types error.
I have tried adding casts to the container instantiation, but it leaves ugly unchecked warnings that make me feel like I'm just missing something. I'd like to avoid those and suppress warnings.
If possible, how can I re-write the any of the classes to make the createContainer() method work?
As written here,
Neither List<Number> nor List<Integer> is a subtype of the other, even though Integer is a subtype of Number. So, any method that takes List<Number> as a parameter does not accept an argument of List<Integer>. If it did, it would be possible to insert a Number that is not an Integer into it, which violates type safety.
Since BaseClass is in a library and you cannot modify it, this case cannot be handled cleanly, i.e. as you expected.
Since Parent1Container and Parent2Container are not exactly BaseContainer<BaseObject> but BaseContainer<? extends BaseObject>
you need to change the signatures accordingly:
public class TestClass extends BaseClass<BaseContainer<? extends BaseObject>> {
...
public BaseContainer<? extends BaseObject> createConstructor() {
if (Math.random() < 0.5) {
return new Parent1Container();
} else {
return new Parent2Container();
}
}
...
}
BaseContainer<BaseObject> makes reference to all those BaseContainer (including extending classes) instances that are able to "handle" any BaseObject, where handle is a blanket-term for all the operations it may do with that type-argument.
In contrast BaseContainer<? extends BaseObject> refer to those BaseContainer instances that are meant to handle a subset of all BaseObject where the top parent class is unknown (thus the ?). It that ? happens to be BaseObject then these two sets would be equivalent.
If your case ? can be either Parent1Object or Parent2Object and so you cannot do better than just leave it as ?.

Using generic interfaces [duplicate]

This question already has answers here:
What is a raw type and why shouldn't we use it?
(16 answers)
Closed 8 years ago.
Is there any differences between those two class declarations
1:
class MyClass <T extends Number & Comparable>
2:
class MyClass <T extends Number & Comparable<T>>
I think that there are differences. But I cannot find an example which would show differences because I don't understand it exact.
Can you show me this example?
There is a difference. The first one is using raw types, and thus, is less type-safe. For example:
This works, but should not work
class MyClass<T extends Number & Comparable>
{
void use(T t)
{
String s = null;
t.compareTo(s); // Works, but will cause a runtime error
}
}
Whereas this does not work (because it should not work)
class MyClass<T extends Number & Comparable<T>>
{
void use(T t)
{
String s = null;
t.compareTo(s); // Compile-time error
}
}
EDIT: Full code, as requested:
class MyClass<T extends Number & Comparable>
{
void use(T t)
{
String s = "Laziness";
t.compareTo(s); // Works, but will cause a runtime error
}
}
public class MyClassTest
{
public static void main(String[] args)
{
MyClass<Integer> m = new MyClass<Integer>();
Integer integer = new Integer(42);
m.use(integer);
}
}

java Generic Type vs Abstract class for parameter

I'm studying Java Generic type.
I have the abstract class AbstractInputdata.
public abstract class AbstractInputData {
....
}
Some class that extend AbstractInputData
public class Email extends AbstractInputData{
...
}
public class Mobile extends AbstractInputData{
...
}
......
A.
public class ProcessorA {
public static boolean isCustomData(AbstractInputData abstractInputData) {
....
}
}
B.
public class ProcessorB {
public static <T extends AbstractInputData> boolean isCustomData(T t) {
...
}
}
Is there any difference between A and B?
The only difference is that the second method with appear as a generic typed method via Reflections. It's behaviour will be the same except in odd cases like this
processorB.<MyType>isCustomData(t); // won't compile unless t is a MyType
You would have to tell it what type you expect it to match, which isn't that useful IMHO.
Since your methods only produce a boolean, there is no difference. But in case you want to return the input you can use B to preserve the generic type:
public class ProcessorB {
public static <T extends AbstractInputData> boolean isCustomData(T t) {
...
}
public static <T extends AbstractInputData> T copyCustomData(T t) {
...
}
}
ProcessorA could only return an object of type AbstractInputData while processorB returns Email or Mobile depending on the parameter type.

Categories