Clarification about wildcards (Generics) in Java - java

I have recently started reading Core Java. But I am having a hard time grasping the concept of wildcards.
Specifically, I'm confused about the difference between the following:
public class A<T extends {some_class}> {/*...*/}
and
public class A<? extends {some_class}> {/*...*/}
Can anyone help me understand the difference if there is at all?

The difference is that you cannot use the ? elsewhere while you can use T. For example:
public class Foo<T extends Number> {
T value; // you can declare fields of type T here
int foo() {
// Since you said T extends Number, you can call methods of Number on value
return value.intValue();
}
}
So why would you use ? at all? If you don't need the type. It wouldn't make sense to use it in a class definition any way that I can think of. But you could use it in a method like this:
int getListSize(List<?> list) {
return list.size();
}
Any kind of method where you're more interested in the overall class and it has a method that doesn't involve the paramaterized type would work here. Class.getName() is another example.

They are the same, except with the wildcard you can't refer to the type in the code of your class. Using T names the type.

In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific). The wildcard is never used as a type argument for a generic method invocation, a generic class instance creation, or a supertype.
The Type T is a defined type or known type
Hope this helps

? extends some class or T extends some_class
means some_class itself or any of its children and anything that would work with instanceof some_class.
As per conventions T is meant to be a Type and ? is unknown type.

Related

Is it possible to have a Type Parameter that extends 2 other type parameters?

Here is my goal: I want to have an argument that needs to be two separate types at the same time.
The goal here is to extract two different types from a single object using just generics (no casting or instanceof).
My idea is to have a third type parameter that extends the other two.
class DualType<A, B> {
A a;
B b;
<T extends A & B> DualType(T obj) {
a = obj;
b = obj;
}
}
This does not work. Since java does not support multiple inheritance, and there isn't a way the compiler can guarantee that B isn't another class, we get an error.
My question is this: Is there some way to define a type parameter that constrains it to only be used with interfaces? I would assume you would be able to use implements rather than extends but as we all know, only super and extends are valid in type parameter declarations. Is there a workaround for this? Or is it simply not possible?
The thing I am trying to achieve here isn't for some practical purpose, but I rather would just like to know if something like this is possible at all in Java?
Is there some way to define a type parameter that constrains it to only be used with interfaces?
Compiler can't know whether A and B are interfaces or classes, since these type variables are only placeholders and actual types will be provided at runtime.
And since type variable T has multiple bounds <T extends A & B> only A can be a class and B should be an interface. But B can be pretty much anything, and therefore your constructor causes a compilation error.
only "super" and "extends" are valid in type parameter declarations
That's not correct. We can use super only with wild cards, not with bounded types. T super MyInterface will not compile. With bounded type parameters we can use only extends.
And it's not possible to let the compiler know that B is an interface by using extends. Even if bound would be an interface B extends MyInterface it doesn't imply that B expected to be an interface.
There's no way to achieve what you're trying to do.

How to create instance object of a class that contains a generic type (using reflection)?

Using reflection, I need to create instance object of a class that contains a generic type.
To date, I'm struggling to find a solution.
I thank who can help me.
Example:
Class one:
package app;
public class PTRow {
}
Class two:
package app;
public class PTQuery<T extends PTRow> {
}
Class three. Here the problem:
package app;
public class PTConnection {
public PTQuery<? extends PTRow> createQuery() {
//TODO How implement this?
return null;
}
}
It's possible?
No it isn't.
All generic types are converted to java.lang.Object upon compilation by a process called type erasure. So your nice strongly typed generics are all lost at runtime.
You'll need to use good old-fashioned polymorphism and factory pattern idioms.
First note: using wildcard in generic type parameters is not good practice for method return types. You can of course use wildcards for parameter types.
Coming to your question: the return type you have declared makes it difficult to know what dynamic type to generate, if not for the type PTQuery.
As this is runtime, you could make the method generic, take in the class that is to be used as generic parameter:
public <T extends PTRow> PTQuery<T> createQuery(Class<T> ptRowType){
//And in here, all should be intuitive if you know your types...
}

Angelika Langer Enum<E extends Enum<E>> decoding

As per my Previous Question, I am reading the article from Angelika Dissecting Enum. Except for the points that a type can only be instantiated for its subtypes and the subtypes do inherit some common methods, I am not able to understand the article.
What is the meaning of abstract Enum class declared in this way? How is it helpful?
The document in the last part has described three aspects, can someone explain them in easier terms to me?
I do see in the code sketch the Enum class is declaring the compareTo method. When Enum is implicitly implementing Comparable interface. Why do it needs to define its own compareTo method?
Seems like it is a concept of recursive generics. What does recursive generics exactly mean? After doing a bit of R&D and understanding my last question answer, I understand that it forces the class to be parameterized on itself.
Still, a detailed explanation would be useful.
I think the main benefit of declaring generic types as Type<E extends Type<E>> is that such generic classes will make subclasses to inherit methods which return or accept arguments with subtype's type. Such methods in java.lang.Enum are:
public final int compareTo( E o) { ... }
public final Class< E > getDeclaringClass() { ... }
So, if we declare the enum Color, that implicitly means:
public class Color extends Enum<Color>
so in this instantiation of Enum the type paramater E is assigned the type argument Color, so the above methods will look like these:
public final int compareTo(Color o) { ... }
public final Class<Color> getDeclaringClass() { ... }
When saying something like Enum<Color extends Enum<Color>>, that sounds like you are declaring a generic type parameter Color that makes sure that it extends Enum with a type parameter matching Color.
But that isn't where generic type parameters for a class are declared. You must declare them next to the class name; you can only use them later in the extends clause. E.g.
// Use "extends" here ... not here.
public class MyClass<E extends MyClass<E>> extends MySuperClass<E>
In this example, you are declaring the class Color to be the value of the generic type parameter that is already defined on Enum.

what is the difference between ? and T in class and method signatures?

why does
public interface ArrayOfONEITEMInterface <T extends ONEITEMInterface>{
public List<T> getONEITEM();
}
compile, but not
public interface ArrayOfONEITEMInterface <? extends ONEITEMInterface>{
public List<?> getONEITEM();
}
what is the difference between ? and T in class and method signatures?
? is a wildcard and means any subclass of ONEITEMInterface including itself.
T is a specific implementation of ONEITEMInterface in this case.
Since ? is a wildcard, there is no relation between your ? in the class declaration and the ? in your method declaration hence it won't compile. Just List<?> getONEITEM(); will compile though.
The first scenario means the entire class can handle exactly one type of Bar per instance.
interface Foo<T extends Bar> {
List<T> get();
}
The second scenario allows each instance to operate on any subtype of Bar
interface Foo {
List<? extends Bar> get()
}
T is a placeholder for a type that will be provided by an implementing or instantiating class.
? is a placeholder saying "I don't know or care what the generic type is" generally used when the work you'll do on the container object doesn't need to know the type.
The reason you can't use '?' in the class/interface definition is because there's the value is saying defining the name of the placeholder (and the type will be provided elsewhere). Putting a '?' doesn't make sense.
Furthermore, the placeholder doesn't need to be T, it can any standard Java variable. By convention, it is one capital character, but need not be.
? allows you to have a list of Unknown types, where as T requires a definite type.
The clause <T extends ONEITEMInterface> is declaring a type parameter named T. This allows your generic type, ArrayOfONEITEMInterface, to refer to the parameter elsewhere. For example you can declare a method like void add(T t).
Without naming the type parameter, how would you refer to it? If you never refer to the type parameter, why is your type generic in the first place? For example, you don't need a parameterized type to do something like this:
public interface ArrayOfONEITEMInterface {
List<? extends ONEITEMInterface> getONEITEM();
}
It doesn't make sense to declare an anonymous type parameter, so it is syntactically illegal.

Can't be as specific with Java generic field types as with generic method types?

I've got some old command-line argument parsing code I wrote 4 years ago for Java 5, and it won't compile in Java 6 thanks to changes in how generics are handled and/or whether certain library classes are generic. While trying to fix it, I came across the following problem; since it's been 4 years since I've touched Java and I was never an expert at generics to start with, it's sort of stumping me.
The library allows me to specify that certain command-line options correspond to enums. To do this, the ArgumentSpecification object corresponding to this option wants to hold a Class object, which we'll call "enumClass", corresponding to the enum class. Unfortunately, I can't seem to figure out how to properly write the type of that field to constrain it to contain class objects that correspond to actual Enum classes. I think what I want is something like:
protected <E extends Enum<E>> Class<E> enumClass; // compiler error
but the compiler barfs on this. On the other hand, the compiler is completely happy with methods that have return values and/or parameters specified that way:
protected <E extends Enum<E>> Class<E> dummyTest(Class<E> foo) { return foo; } // "works"
I can try using this for the field instead:
protected Class<? extends Enum<?>> enumClass;
but that doesn't really work either...other parts of the code need the "<E extends Enum<E>>" type so they can actually get at E, and this doesn't seem to match up with the "<? extends Enum<?>>", as I get compiler errors like this:
Bound mismatch: The generic method checkedEnumFromString(Class<E>, String) of type EnumUtil is not applicable for the arguments
(Class<capture#1-of ? extends Enum<?>>, String). The inferred type capture#1-of ? extends Enum<?> is not a valid substitute for the bounded
parameter <E extends Enum<E>>
Is there a way to declare the field with the correct type here that I'm missing? If so, what is it? If not, isn't it horribly broken of Java to be able to declare types in methods that you can't for fields? Or am I so horribly confused that my question makes no sense to start with?
If you need to define a field with explicit parameter E like that, then you may have to parameterize the type in which the field is declared in. Something like this compiles:
class MyClass<E extends Enum<E>> {
Class<E> enumClass;
}
You're trying to declare a "generic field" - one which has a type parameter itself. There's no such concept in Java - only methods and types can introduce type parameters.
As polygenelubricants says, you can introduce an extra type parameter in the type itself, and use that as the type of the field.

Categories