Type mismatch for Class Generics - java

I have the following code that won't compile and although there is a way to make it compile I want to understand why it isn't compiling. Can someone enlighten me as to specifically why I get the error message I will post at the end please?
public class Test {
public static void main(String args[]) {
Test t = new Test();
t.testT(null);
}
public <T extends Test> void testT(Class<T> type) {
Class<T> testType = type == null ? Test.class : type; //Error here
System.out.println(testType);
}
}
Type mismatch: cannot convert from Class<capture#1-of ? extends Test> to Class<T>
By casting Test.class to Class<T> this compiles with an Unchecked cast warning and runs perfectly.

The reason is that Test.class is of the type Class<Test>. You cannot assign a reference of type Class<Test> to a variable of type Class<T> as they are not the same thing. This, however, works:
Class<? extends Test> testType = type == null ? Test.class : type;
The wildcard allows both Class<T> and Class<Test> references to be assigned to testType.
There is a ton of information about Java generics behavior at Angelika Langer Java Generics FAQ. I'll provide an example based on some of the information there that uses the Number class heirarchy Java's core API.
Consider the following method:
public <T extends Number> void testNumber(final Class<T> type)
This is to allow for the following statements to be successfully compile:
testNumber(Integer.class);
testNumber(Number.class);
But the following won't compile:
testNumber(String.class);
Now consider these statements:
Class<Number> numberClass = Number.class;
Class<Integer> integerClass = numberClass;
The second line fails to compile and produces this error Type mismatch: cannot convert from Class<Number> to Class<Integer>. But Integer extends Number, so why does it fail? Look at these next two statements to see why:
Number anumber = new Long(0);
Integer another = anumber;
It is pretty easy to see why the 2nd line doesn't compile here. You can't assign an instance of Number to a variable of type Integer because there is no way to guarantee that the Number instance is of a compatible type. In this example the Number is actually a Long, which certainly can't be assigned to an Integer. In fact, the error is also a type mismatch: Type mismatch: cannot convert from Number to Integer.
The rule is that an instance cannot be assigned to a variable that is a subclass of the type of the instance as there is no guarantee that is is compatible.
Generics behave in a similar manner. In the generic method signature, T is just a placeholder to indicate what the method allows to the compiler. When the compiler encounters testNumber(Integer.class) it essentially replaces T with Integer.
Wildcards add additional flexibility, as the following will compile:
Class<? extends Number> wildcard = numberClass;
Since Class<? extends Number> indicates any type that is a Number or a subclass of Number this is perfectly legal and potentially useful in many circumstances.

Suppose I extend Test:
public class SubTest extends Test {
public static void main(String args[]) {
Test t = new Test();
t.testT(new SubTest());
}
}
Now, when I invoked testT, the type parameter <T> is SubTest, which means the variable testType is a Class<SubTest>. Test.class is of type Class<Test>, which is not assignable to a variable of type Class<SubTest>.
Declaring the variable testType as a Class<? extends Test> is the right solution; casting to Class<T> is hiding a real problem.

Remove the conditional and the error is a little nicer...
public class Test {
public static void main(String args[]) {
Test t = new Test();
t.testT(null);
}
public <T extends Test> void testT(Class<T> type) {
Class<T> testClass = Test.class;
System.out.println(testClass);
}
}
Test.java:10: incompatible types
found : java.lang.Class<Test>
required: java.lang.Class<T>
Class<T> testClass = Test.class;

Related

Why is javac not able to typecheck the call site of a static method with a bounded type parameter as return type? [duplicate]

This question already has an answer here:
Why can this generic method with a bound return any type?
(1 answer)
Closed 4 years ago.
Why does javac not abort with a type error on this code example
import java.util.List;
public class StaticMethodWithBoundedReturnType {
static class Foo {
}
static class Bar extends Foo {
}
static <F extends Foo> F getFoo(String string) {
…
}
public static void main(String[] args) {
// Compiles without error, even though List does not extend Foo.
List<Integer> list = getFoo("baz");
}
}
Obviously List can never be a subtype of Foo. And even if there would exists a subtype of List which would somehow extend Foo, then the assigning of list at the call site of getFoo() should be invalid. I'm aware of the existence of type erasure. But shouldn't javac be able see that the type of list does not satisfy the bounded type constraint extends Foo and thus fail compilation with a type error?
Why is javac not able to typecheck the call site of a static method with a bounded type parameter as return type?
It appears I could get type safety with the following slight modification:
import java.util.List;
public class StaticMethodWithBoundedReturnType {
static class Foo {
}
static class Bar extends Foo {
}
static <F extends Foo> F getFoo(String string, Class<F> clazz) {
…
}
public static void main(String[] args) {
// Does not compile \o/
List<Integer> list = getFoo("baz", List.class);
}
}
But this requires adding the Class parameter to getFoo() which isn't used in the method's body at all. Is there a better way to achieve type safety?
To understand this, we need to understand what the following actually means:
static <F extends Foo> F getFoo(String string) {
return null;
}
That says that getFoo returns a value of some type that must be inferred from the context in which the call is made. Furthermore, it makes the constraint, that the inferred type must be a subtype of Foo.
Since null is assignable to all possible reference types, it is suitable as a return value. In fact, it is the only possible that may be returned.
To illustrate, try the following variation:
import java.util.List;
public class StaticMethodWithBoundedReturnType {
static class Foo {
}
static class Bar extends Foo {
}
static <F extends Foo> F getFoo(String string) {
return new Bar();
}
public static void main(String[] args) {
// Compiles without error, even though List does not extend Foo.
List<Integer> list = getFoo("baz");
}
}
This gives a compilation error
StaticMethodWithBoundedReturnType.java:11: error: incompatible types:
Bar cannot be converted to F
return new Bar();
^
You may ask: Why isn't Bar compatible with F?.
Answer: because the F stands for ( R & ? extends Foo ) where R is the type that the result of getFoo is assigned to. And, within getFoo re cannot know what R will be. (Indeed, it can be lots of different types!)
In short, the type signature
<F extends Foo> F getFoo(String string)
is problematic. However, consider this:
static <F extends Foo> F getFoo(Class<F> clazz) {
return class.newInstance();
}
That is legal, and will return a value that satisfies runtime type safety (locally). But you will then get the expected compilation error if you try to assign it to a List<Integer>:
StaticMethodWithBoundedReturnType.java:16: error: incompatible types:
inference variable F has incompatible bounds
List<Integer> list = getFoo(Bar.class);
^
equality constraints: Bar
upper bounds: List<Integer>,Foo
where F is a type-variable:
F extends Foo declared in method <F>getFoo(Class<F>)
1 error
Returning to the example, consider the call:
List<Integer> list = getFoo("baz");
That is legal because the inferred type for the result is the intersection type (List<Integer> & ? extends Foo). Indeed, that intersection type is implementable; e.g. as
class Baz extends Bar implements List<Integer> { /* list methods */ }
(The fact that there is no implementation in this Baz class in our program is immaterial. There could be one.)
So, we can compile the program. And when we execute it, list will be assigned null, which is not a runtime type violation.

Generic method triggers type safety error - why?

Whilst playing around with solutions for this question, I came up with the following code, which has some compiler warnings. One warning is:
Type safety: The expression of type Test.EntityCollection needs unchecked conversion to conform to Test.EntityCollection<Test.Entity>
I don't entirely understand why this warning appears. By passing in a Class<M> type and declaring the method returns EntityCollection<M>, why am I not doing enough to convince the (Java 7) compiler that the correct type is being returned?
static class Entity {
}
static class EntityCollection<E extends Entity> {
private EntityCollection(HashMap<?, E> map) {
}
public static <T extends HashMap<?, M>, M extends Entity> EntityCollection<M> getInstance(
Class<T> mapType, Class<M> entityType)
throws ReflectiveOperationException {
T map = mapType.getConstructor().newInstance();
return new EntityCollection<M>(map);
}
}
public static void main(String[] args) throws Exception {
// both compiler warnings are on the line below:
EntityCollection<Entity> collection = EntityCollection.getInstance(
LinkedHashMap.class, Entity.class);
}
Bonus points if anyone can improve the code to avoid warnings entirely. I've been staring at it for a while and haven't dreamt up any ways to lessen the warnings.
The problem is that getInstance is a generic method but you don't pass generic type parameters to it. You can get around it by passing them like this:
public static void main(String[] args) throws Exception {
EntityCollection<Entity> collection = EntityCollection.<LinkedHashMap, Entity>getInstance(
LinkedHashMap.class, Entity.class);
}
You will still have to deal a rawtypes warning because LinkedHashMap is a generic type. This is problematic in your case since there is a wildcard in the key type.
You face several problems here:
You can't pass parameterized class objects like this: LinkedHashMap<Object, Entity>.class so you pretty much stuck with the rawtypes warning.
The problem there is T. You are adding a constraint to your method saying that T should extends HashMap<?, M>. However, the way you are later referencing to T is like a generic parameter of the type Class (Class<T>). LinkedHashMap.class is of type Class<LinkedHashMap> not Class<LinkedHashmap<?, Entity>> (which is what you needed)
A Class object always references a non-parameterized type, and that makes sense. Because the generic binding exists in compile-time, and you are going to use that Class to dynamically reflect the state and behaviour of an instance in runtime. Long story short, you can use a Class<HashMap> to build a new instance, not bounded to any type.
So, I guess what you need to do to your code to modify that constraint in the way it looks like:
public static <T extends HashMap, M extends Entity> EntityCollection<M> getInstance(
Class<T> mapType, Class<M> entityType)
throws ReflectiveOperationException {
T map = mapType.getConstructor().newInstance();
return new EntityCollection<M>(map);
}

Java generics with wildcard compile in Eclipse, but not in javac

As a follow up to Java generics compile in Eclipse, but not in javac, I post another snippet which compiles and runs fine in Eclipse, but raises a compilation error in javac. (This prevents the project the snippet is extracted from, from being build with Maven.)
The self-contained snippet:
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Set<Foo<?>> setOfFoos = new HashSet<Foo<?>>();
List<Foo<?>> sortedListOfFoos = asSortedList(setOfFoos);
}
public static <T extends Comparable<T>> List<T> asSortedList(Collection<T> c) {
List<T> list = new ArrayList<T>(c);
java.util.Collections.sort(list);
return list;
}
public static class Foo<T> implements Comparable<Foo<T>> {
#Override
public int compareTo(Foo<T> o) {
return 0;
}
}
}
Compilation in javac returns:
Main.java:11: <T>asSortedList(java.util.Collection<T>) in Main cannot be applied to (java.util.Set<Main.Foo<?>>)
List<Foo<?>> sortedListOfFoos = asSortedList(setOfFoos);
^
On substitution of Foo<?> with Foo<String> the above snippet will compile in javac, which means the problem is related to the used wildcard. As the Eclipse compiler is supposed to be more tolerant, is it possible the snippet is no valid Java?
(I use javac 1.6.0_37 and Eclipse Indigo with compiler compliance level 1.6)
(EDIT1: Included another example which got removed in EDIT2.)
EDIT2: Hinted by irreputable, that comparing Foo<A> and Foo<B> may be conceptually wrong, and inspired by the answer of seh, a working asSortedFooList can be written as follows:
public static <T extends Foo<?>> List<T> asSortedFooList(Collection<T> c) {
List<T> list = new ArrayList<T>(c);
java.util.Collections.sort(list);
return list;
}
(Simple substitution of Comparable<T> with Foo<?> in the method definition above.)
So it seems to be safe for javac and imho conceptually right to compare any Foo<A> and Foo<B>. But it is still not possible to write a generic method asSortedList which returns a sorted list representation for a generic collection, if its type argument is parametrized with a wildcard. I tried to "trick" javac by substituting Foo<?> by S extends Comparable<S> in asSortedFooList, but this didn't work.
EDIT3: Later Rafaelle pointed out, that there is a flaw in the design, since implementing Comparable<Foo<T>> is not necessary, and implementing Comparable<Foo<?>> provides the same functionality, solving the initial problem by refined design.
(The initial reason and benefit was, that a Foo<T> may not care in some purposes about its concrete type but still use an instance of a concrete type T, it is instantiated with, for other purposes. That instance does not have to be used for determining the order among other Foos, as it may be used in other parts of the API.
Concrete example: Assume each Foo is instantiated with a different type argument for T. Every instance of Foo<T> has an incrementing id of type int which is used in the implementation of the compareTo-method. We can now sort a list of these differently typed Foo and don't care about the concrete type T (expressing it with Foo<?>) and still have an instance of a concrete type T accessible for later processing.)
To me this is another javac bug. When you try to send a Collection<Foo<?>> to a method with the signature:
public static <T extends Comparable<T>> List<T> asSortedList(Collection<T> c)
the compiler notes that the formal parameter T has an upper bound, so checks if the constrained is honored by the caller. The type argument is a (wildcard) instantiation of the parameterized type Foo<T>, so the test will pass if Foo<?> is-a Comparable<Foo<?>>. Based upon the generic definition:
class Foo<T> implements Comparable<Foo<T>>
I'd say that it's true, so again Eclipse is right and javac has a bug. This Angelika Langer's entry is never linked enough. Also see the relevant JLS.
You asked if it is type-safe or not. My answer is that it is type safe, and it shows you have a flaw in your design. Consider your fictitious implementation of the Comparable<T> interface, where I added two more fields:
public static class Foo<T> implements Comparable<Foo<T>> {
private T pState;
private String state;
#Override
public int compareTo(Foo<T> other) {
return 0;
}
}
You always return 0, so the problem is not spotted. But when you try to make it useful, you have two options:
Comparing on the String field
Comparing on the T member
The String field is always a String, so you don't really benefit from the type variable T. On the other hand, T has no other type information available, so in compareTo() you can only deal with a plain object, and again the type parameter is useless. You can achieve the same exact functionality by implementing Comparable<Foo<?>>
In this case, javac is correct. Conceptually, your code can't work, since the set may contain Foo<A> and Foo<B>, which can't be compared to each other.
You probably want the set to be a Set<Foo<X>> for some type variable X; unfortunately we can't introduce type variable inside method body; only in method signature
<X> void test(){
Set<Foo<X>> setOfFoos = new HashSet<Foo<X>>();
List<Foo<X>> sortedListOfFoos = asSortedList(setOfFoos);
}
You may make it work by something like
<T extends Comparable<? super T>> List<T> asSortedList(Collection<T> c)
class Foo<T> implements Comparable<Foo<?>>
I don't know if this is a question, but here is a (not very nice) answer:
If you sacrifice some type safety you can write
#SuppressWarnings({ "unchecked", "rawtypes" })
public static <T extends Comparable> List<T> asSortedList(Collection<T> c) {
List<T> list = new ArrayList<T>(c);
java.util.Collections.sort(list);
return list;
}
And it works in both eclipse and javac. The only risk that I'm aware of is that if someone creates a class Foo extends Comparable<Bazz> you won't detect that in compile time.
But if someone creates Foo extends Comparable<Bazz>, just kill him/her.
I found a solution that compiles with javac, though I am not happy that I am unable to explain exactly why it works. It requires introducing an intermediary function:
public final class Main {
public static class Foo<T> implements Comparable<Foo<T>> {
#Override
public int compareTo(Foo<T> o) {
return 0;
}
}
public static <T extends Comparable<? super T>>
List<T> asSortedList(Collection<T> c) {
final List<T> list = new ArrayList<T>(c);
java.util.Collections.sort(list);
return list;
}
private static <T extends Foo<?>> List<T> asSortedFooList(Collection<T> c) {
return asSortedList(c);
}
public static void main(String[] args) {
final Set<Foo<?>> setOfFoos = new HashSet<Foo<?>>();
final List<Foo<?>> listOfFoos = asSortedFooList(setOfFoos);
}
}
I think that this works by virtue of taking the wildcard resolution step-by-step; asSortedFooList() captures one type known to be a Foo, irrespective of Foo's type parameter. With that type parameter bound in asSortedFooList(), we can then call on your original asSortedList() (well, with one modification—note the lower bound on the type parameter for Comparable) requiring binding Foo as a type descended from Comparable.
Again, that's a weak, haphazard explanation. My main point in answering here is just to provide one more way to get to your destination.
If you can replace your wildcard usage with an exact type (which may be a super-type) your code will work. Replace
List<Foo<?>> sortedListOfFoos = asSortedList(setOfFoos);
with
List<Foo<String>> sortedListOfFoos = Main.<Foo<String>>asSortedList(setOfFoos);

Java Generics: Multiple Inheritance in Bounded Type Parameters <T extends A & I>

I am about to create a factory which creates objects of a certain type T which extends a certain class A and another interface I. However, T must not be known. Here are the minimum declarations:
public class A { }
public interface I { }
This is the factory method:
public class F {
public static <T extends A & I> T newThing() { /*...*/ }
}
This compiles all fine.
When I try to use the method the following works fine:
A $a = F.newThing();
...while this does not:
I $i = F.newThing();
The compiler complains:
Bound mismatch: The generic method newThing() of type F is not applicable for the arguments (). The inferred type I&A is not a valid substitute for the bounded parameter
I can't understand why. It is clearly stated that "newThing returns something of a certain type T which does extend the class A and implement the interface I". When assigning to A everything works (since T extends A) but assigning to I does not (because of what?, clearly the thing returned is both an A and an I)
Also: When returning an object, say B of the type class B extends A implements I, I need to cast it to the return type T, although B matches the bounds:
<T extends A & I> T newThing() {
return (T) new B();
}
However, the compiler does not throw any warnings like UncheckedCast or the like.
Thus my question:
What is going wrong here?
Is there an easy away to achieve the desired behavior (i.e. assigning to a variable of static type A or I), like there is in solving the return-type-problem by casting, in the factory method?
Why does the assignment to A work, while to I does not?
--
EDIT: Here the complete code snippet which totally works using Eclipse 3.7, project set up for JDK 6:
public class F {
public static class A { }
public static interface I { }
private static class B extends A implements I { }
public static <T extends A & I> T newThing() {
return (T) new B();
}
public static void main(String... _) {
A $a = F.newThing();
// I $i = F.newThing();
}
}
EDIT: Here is a complete example with methods and invocation which does work at runtime:
public class F {
public static class A {
int methodA() {
return 7;
}
}
public static interface I {
int methodI();
}
private static class B extends A implements I {
public int methodI() {
return 12;
}
}
public static <T extends A & I> T newThing() {
return (T) new B();
}
public static void main(String... _) {
A $a = F.newThing();
// I $i = F.newThing();
System.out.println($a.methodA());
}
}
As for the second question:
Consider this case:
class B extends A implements I {}
class C extends A implements I {}
Now, the following uses type inference:
<T extends A & I> T newThing() {
return (T) new B();
}
So you could call this:
C c = F.newThing(); //T would be C here
You see that T could be anything that extends A and I you can't just return an instance of B. In the case above the cast could be written as (C)new B(). This would clearly result in an exception and thus the compiler issues a warning: Unchecked cast from B to T - unless you're supressing those warnings.
This doesn't do what you expect it to. T extends A & I indicates that the caller can specify any type that extends A and I, and you'll return it.
I think that one way to explain it is by replacing the type parameter with the actual type.
The parameterized signature of the methods is:
public static <T extends A & B> T newThing(){
return ...;
}
The <T extends A & B> is what is called a type parameter. The compiler would expect that this value is actually substituted with the actual type (called type argument) when you actually use it.
In the case of your method the actual type is decided by means of type inference. That is, <T extends A & B> should be replaced by a real existing type that extends A and implements B.
So, let's say that classes C and D both extends A and implements B, then if your signature were like this:
public static <T extends A & B> T newThing(T obj){
return obj;
}
Then, by type inference, your method would be evaluated as follows:
public static C newThing(C obj){
return obj;
}
if you invoke with newThing(new C()).
And would be as follows
public static D newThing(D obj){
return obj;
}
if you invoke with newThing(new D()).
This would compile just fine!
However, since you are not actually providing any kind of type to validate type inference in your method declaration, then the compiler could never be sure what is the actual type (type argument) of your type parameter <T extends A & B>.
You might expect that the actual type is C, but there may be thousands of different classes that satisfy that criteria. Which of those should the compiler use as the actual type of your type argument?
Let's say that C and D are two classes that extend A and implements B. Which of these two actual types should the compiler use as type argument for your method?
You could have even declared a type argument for which there is not even an existing type that you can use, like saying something that extends Serializable and Closable and Comparable and Appendable.
And perhaps there is not a class in the whole world that satisfies that.
As such, you must understand that the type parameter here is just a requirement for the compiler to validate the actual type that you use, a placeholder for the actual type; and this actual type must exist at the end and the compiler will use it to replace appearances of T. Therefore the actual type (type argument) must be inferable from the context.
Since the compiler cannot tell with certainty which is the actual type that you mean, basically because there is no way to determine that by type inference in this case, then you are forced to cast your type, to ensure the compiler that you know what you are doing.
As such, you could implement your method using type inference like this:
public static <T extends A & B> T newThing(Class<T> t) throws Exception{
return t.newInstance();
}
This way, you would be actually telling the compiler what is the actual type argument to be used.
Take into account that when the bytecodes are generated, the compiler must substitute T for a real type. There is no way to write method in Java like this
public static A & B newThing(){ return ... }
Right?
I hope I have explained myself! This is not simple to explain.
Simplest solution is create an abstract base class that extends and implements whatever class and interfaces you want and return that type. It doesn't matter that you're constraining your return type to extend this base class as you were already constraining the return type to its superclass.
eg.
class C {}
interface I {}
abstract class BaseClass extends C implements I {}
// ^-- this line should never change. All it is telling us that we have created a
// class that combines the methods of C and I, and that concrete sub classes will
// implement the abstract methods of C and I
class X extends BaseClass {}
class Y extends BaseClass {}
public class F {
public static BaseClass newThing() {
return new X();
}
public static void main(String[] args) {
C c = F.newThing();
I i = F.newThing();
}
}

Java generics compilation error - The method method(Class<capture#1-of ? extends Interface>) in the type <type> is not applicable for the arguments

Last Thursday someone at work showed me a compile error that I wasn't able to fix in a clean way and it has been bothering me ever since.
The problem is generics related and I've reconstructed a simplified version of the code that generates the compile error. The error occurs in the very last line of code shown below.
I've been looking all over the interwebs but can't seem to find a decent explanation why the Java compiler doesn't accept the code. I guess that if it were to allow the code, it would be possible the create a class cast issue in Bar.operationOnBar(), but I don't see how.
Could someone please enlighten me why this doesn't compile?
public interface Interface {
}
public class Type implements Interface {
}
public class Bar<T> {
public Bar(Class<T> clazz) {
}
public void operationOnBar(Class<T> arg){
}
}
public class Foo {
public <T> Bar<T> bar(Class<T> clazz){
return new Bar<T>(clazz);
}
public static void main(String[] args) {
Class<? extends Interface> extendsInterfaceClazz = Type.class;
new Foo().bar(extendsInterfaceClazz).operationOnBar(Type.class);
}
}
Compile Error on the second line of Foo.main():
The method operationOnBar(Class<capture#1-of ? extends Interface>) in the type Bar<capture#1-of ? extends Interface> is not applicable for the arguments (Class<Type>)
Btw. I've solved it by downcasting Type.class to Class, this way the compiler is unable to see that the generic type of Class is "Type" instead of "? extends Interface".
A little advice: when you are not sure why compiler prohibits some generic-related conversion, replace generic classes in question with List<T>. Then it would be easy to find an example that breaks type safety.
This replacement is correct since currently Java doesn't provide a way to conduct any a priory knowledge about possible behaviours of generic classes (i.e. it lacks a way to specify covariance and contravariance of generic classes in their declarations, as in C# 4 and Scala). Therefore Class<T> and List<T> are equivalent for the compiler with respect to their possible behaviours, and compiler has to prohibit conversions that can cause problems with List<T> for other generic classes as well.
In your case:
public class Bar<T> {
private List<T> l;
public Bar(List<T> l) {
this.l = l;
}
public void operationOnBar(List<T> arg) {
l.addAll(arg);
}
}
List<Type1> l1 = new ArrayList<Type1>();
List<? extends Interface> l2 = l1;
List<Type2> l3 = Arrays.asList(new Type2());
new Foo().bar(l2).operationOnBar(l3);
Type1 t = l1.get(0); // Oops!
You also can change the signature of the method operationOnBar to:
public void operationOnBar(Class<? extends Interface> arg){
You would agree that this shouldn't compile:
1 Class<? extends Interface> clazz = AnotherType.class;
2 new Foo().bar(clazz).operationOnBar(Type.class);
The problem is javac is a little dumb; when compiling line#2, all it knows about variable clazz is its declared type; it forgets the concrete type it was assigned to. So what is assigned to clazz at line#1 doesn't matter, compiler must reject line#2.
We can imagine a smarter compiler that can track the concrete types, then your code can be compiled, as it is obviously safe and correct.
Since that's not the case, sometimes programmers know more about types than the compiler, it is necessary that programmers do casts to convince the compiler.
The general way to deal with these sorts of problems is to introduce a generic argument for the repeated type, which generally means introducing a new generic method (a class would do as well, but isn't necessary).
public static void main(String[] args) {
fn(Type.class);
}
private static <T extends Interface> void fn(Class<T> extendsInterfaceClazz) {
new Foo().bar(extendsInterfaceClazz).operationOnBar(extendsInterfaceClazz);
}
Not really related to the question, but I would suggest using reflection sparingly. It is very, very rarely a good solution.

Categories

Resources