class Aliphatic<F> extends Organic<F>{}
class Hexane<G> extends Aliphatic<G>{}
public class Organic<E>{
void react(E e){}
static void main(String[] args){
Organic<? extends Organic> compound = new Aliphatic<Organic>();
compound.react(new Organic());
}
}
Why can't I call react method with Organic argument?
The generic type ot the reference <? extends Organic> says that the generic type of the instantiation canb either a Organic, or a subtype of Organic.
Is because the compiler doesn't know this instantiation generic type until runtime type an so, it does not bind any value to its generic criteria?
Why is this case working? Is this case the same?
public class WildcardCollection {
public static void main (String[] args){
WildcardCollection w = new WildcardCollection();
w.myMethod(new Items("hola",1)); //Compile
w.myMethod(new SubItems("nuevo",3)); //Compile
}
public <T extends Items> void myMethod(T a){ //Same as above
System.out.println("hi: "+a);
}
}
class SubItems extends Items {
SubItems(){};
SubItems(String s, int i){ super(s,i);}
}
class Items implements Comparable<Items> {
private String name;
private int value;
public Items() {}
public Items(String n, int i){ this.name = n; this.value = i;}
public String getName(){ return this.name;}
public int getValue(){ return this.value;}
public String toString(){ return "(" + this.name + "-" + this.value + ")";}
public int compareTo(Items i){
return this.value - i.getValue();
}
}
Quite simply, if you have an object of some generic type with a type parameter T instantiated with a ? extends X wildcard then you can't call methods on the object that take parameters of type T because the compiler can't guarantee type safety. However you can call methods that return T (and assign the return value to a variable of type X). In your specific example it looks like this should be safe
Organic<? extends Organic> compound = new Aliphatic<Organic>();
compound.react(new Organic());
but remember that the compiler has to match the react call based on the declaration type (? extends Organic), it can't rely on what you've assigned on the RHS. If the compiler allowed this then it would also have to allow
Organic<? extends Organic> compound = new Aliphatic<Hexane<?>>();
compound.react(new Organic());
which is clearly not correct - it's exactly the same situation as
Collection<? extends Number> nums = new ArrayList<Float>();
nums.add(Integer.valueOf(1));
(all this is aside from the fact that since Organic is generic you need to say Organic<? extends Organic<?>> or similar rather than just Organic<? extends Organic>)
Related
Coming across a problem that I could not make a function to allow a generic return type for all the child class of a parent class.
Is there a way to create a function that allows me to return any of these children class type base on an argument?
I have the following parent class:
abstract class Number {
int res = 1;
abstract static class Builder<T extends Builder<T>> {
int res = 100;
public T setNum(int num) {
this.res = num;
return self();
}
abstract Number build();
abstract T self();
}
Number(Builder<?> builder) {
res = builder.res;
}
}
and some children class:
class One extends Number{
private int size = 1;
static class Builder extends Number.Builder<Builder> {
private int size = -1;
public Builder setSize(int size) {
this.size = size;
return self();
}
#Override
public One build() {
return new One(this);
}
#Override
protected Builder self() {
return this;
}
}
private One(Builder builder) {
super(builder);
size = builder.size;
}
}
class Two extends Number {
private String size = String.valueOf(1);
static class Builder extends Number.Builder<Builder> {
private String size;
public Builder setSize(String size) {
this.size = size;
return self();
}
#Override
public Two build() {
return new Two(this);
}
#Override
protected Builder self() {
return this;
}
}
private Two(Builder builder) {
super(builder);
size = builder.size;
}
}
Note the parent class and child classes are not done yet, but it is going to have a similar format with just more fields so this would still apply
This is something that I want to achieve:
public <T> T loadNumber(String id) {
if (id.equals('1')) {
return new ONE.Builder.build(); // this will report error right now
}
elif (id.equals('2')) {
return new TWO.Builder.build(); // this will report error right now
}
return null;
}
The problem is that type arguments are specified by the caller. Your method
public <T> T loadNumber(String id) {
can be called like
Two two = loadNumber("One");
causing the compiler to infer
Two two = loadNumber<Two>("One");
which is why the compiler expects your method implementation to conjure a T out of thin air, and is not satisfied with a One. After all, T could stand for Two, as in the example above, and One isn't Two.
Put differently, the method signature
public <T> T loadNumber(String id) {
doesn't make sense, because the method must return a T, but has no way to determine, at runtime, what T is (due to type erasure, methods can't reflect on their type parameters).
So you have two choices:
Either you return the base type
public Number loadNumber(String id) {
and have the caller, who presumably knows which type the id he passed corresponds to, cast it to that type,
or you use an ID that whose type is itself generic and describes the type it maps to:
interface Builder<P extends Number, B extends Builder<P>> {
P build();
B self();
}
interface ID<P extends Number> {
Builder<P, ?> builder();
static ID<One> one = One.Builder::new;
static ID<Two> two = Two.Builder::new;
}
and then you can declare
public <N extends Number> N loadNumber(ID<N> id) {
return id.builder().build();
}
and use it like
One one = loadNumber(ID.one);
Two two = loadNumber(ID.two);
but not
One one = loadNumber(ID.two); // compilation error
You should be able to return any child class by simply using the parent class as a return type, in your case:
public Number loadNumber(String id) {
// your code implementation
}
Now, to save this into a variable you can use the same logic and declare the variable as the parent type. After the method returns, the variable will be casted into the whatever child class instance it returned, for example in your case:
Number obj = loadNumber("1");
The obj object will cast to an instance of One class. You can test this by printing out the object class after the above line:
System.out.println(obj.getClass());
This should print out class One or the name of whatever child class you saved into the variable.
I'm working on code where I have to cast base class onto derived one where I have an array of generic types that are derived by the base on.
For example, I have Base and Derived1, Derived2 and I put them into Class[]{Derived1.class, Derived2.class} and I pass this array to the constructor of the class.
In this constructor, I have to create instances of these derived classes and I don't know how to do that because I get the info that Class and Base are incompatible.
Here is my code example
public abstract class Base {
public abstract Base create(String s);
}
public class Derived extends Base {
java.lang.Integer value;
private static Derived integer = new Derived();
public static Derived getInstance(){
return integer;
}
public Base create(String s) {
value = java.lang.Integer.parseInt(s);
return this;
}
}
public class Clazz {
Class<? extends Base> type;
ArrayList<Base> arrayList;
public Class<? extends Base> getType() {
return type;
}
}
public class AnotherClazz{
ArrayList<Clazz> clazzArrayList;
Class<? extends Base>[] types;
AnotherClazz(Class<? extends Base>[] args){
clazzArrayList = new ArrayList<>();
types = args; // assuming I pass 2 elements in array
String[] strings = new String[]{"1","2"};
for (int i=0; i<args.length; ++i){
if (types[i] instanceof Base){
// here i want to check validity of class
}
}
for (int i=0; i<strings.length; ++i){
clazzArrayList.get(i).arrayList.add(((types[i]) Base).getInstance().create(strings[i]));
//here i want to create instance of object from type assigned to specific column
}
}
Thanks for the help.
To check the validity, try this
if (types[i].getClass().isAssignableFrom(Base.class))
If I read the question correctly, you want to create a few instances of derived classes that all have the same constructor arguments. If that is the case, then you need to give each derived class the same constructor (it does not need to be in the base class) and use Constructor.newInstance(parameters) to create the instances. Further, since you want to ensure that each derived class extents the base class then you will want to use Class.isAssignableFrom(class). For example,
import java.lang.reflect.Constructor;
public class SO52930530 {
public abstract static class Base {
public abstract <T> T getValue();
}
public static class Derived1 extends Base {
String value;
public Derived1(String value) {
this.value = value;
}
public <T> T getValue() {
return (T) value;
}
}
public static class Derived2 extends Base {
Integer value;
public Derived2(String value) {
this.value = new Integer(value);
}
public <T> T getValue() {
return (T) value;
}
}
public static void main(String... args) throws Exception {
Class<? extends Base>[] extensions = new Class[]{Derived1.class, Derived2.class};
String[] values = new String[]{"a", "1"};
Base[] instances = new Base[values.length];
for (int i = 0; i < instances.length; i++) {
Class extension = extensions[i];
if (Base.class.isAssignableFrom(extension)) {
Constructor constructor = extension.getConstructor(String.class);
instances[i] = (Base) constructor.newInstance(values[i]);
}
}
for (int i = 0; i < instances.length; i++) {
System.out.printf("%d %s %s\n", i, instances[i].getClass(), instances[i].getValue());
}
}
}
I hope this helps.
Thanks for helping with checking validity (it works!) but I still don't get this newInstance creation because I have to read data from .csv file and my derived classes are in fact "wrappers" for primitive types like int, float, etc. and I am supposed to create new object using methods getInstance() and create(string s), so it looks like this:
public static class Derived1 extends Base { //Integer wrapper
Integer value;
public Derived1(Integer value) {
this.value = value;
}
private static Integer integer = new Integer();
public static Integer getInstance(){
return integer;
}
private Integer(){};
public Base create(String s) {
value = java.lang.Integer.parseInt(s);
return this;
}
}
and I don't know how to use Class to cast to appriopriate type.
This question already has answers here:
Get generic type of class at runtime
(30 answers)
Closed 7 years ago.
I'd like to find a hack to infer the actual generic instance of another instance's var in runtime, without:
Changing my needed method signature (adding the helper parameter Class<T>, the obvious way)
Having to instanceof all possible subtypes in a hardcoded way
MyInterface<? extends Number> myInterface = whateverReturnsWildcardDoubleInterface();
Class<?> type = inferInstanceType(myInterface);
assert type == Double.class;
/** This is the method that represents the code I am looking for with the conrete signature**/
public <T extends Number> Class<T> inferInstanceType(MyInterface<T> myInterface){
return T.class; //Concrete T (can or cannot be the very Number)
}
Ideally, it should return Double when T is particular subtype Integer,Double.. and Number when T is Number
I checked reflection, several "TypeResolver"/"GenericResolver" libs (as the one in Spring or others in Github), but I cannot fin a way to hack it.
EDIT: I reached the conclusion that he only feasible way to do that would be some kind of very complex reflection through the stack trace up to the acutal line that passes the type in the very instantiation
EDIT2: I know it's stupid... but I solved it by simply adding a T getT() method to my interface, so I could return myInterface.getT().getClass()
Disclaimer: This solution is provided as a hack tailored to my understanding of your setup, i.e. one generic interface with a single type parameter, multiple classes, which are not themselves generic, directly implementing this one interface alone, and implementing no other generic interfaces, directly or indirectly.
Assuming that all of the above is true, there is a relatively straightforward way of hacking a solution: calling getClass().getGenericInterfaces() returns a Type object that provides the actual type with which your generic interface has been instantiated.
interface MyInterface<T extends Number> {
T getVal();
}
class DoubleImpl implements MyInterface<Double> {
public Double getVal() {return 42.42; }
}
...
public static void main (String[] args) throws java.lang.Exception {
MyInterface<? extends Number> x = new DoubleImpl();
Type[] ifs = x.getClass().getGenericInterfaces();
System.out.println(ifs.length);
for (Type c : ifs) {
System.out.println(c);
Type[] tps = ((ParameterizedType)c).getActualTypeArguments();
for (Object tp : tps) {
System.out.println("===="+tp); // <<== This produces class java.lang.Double
}
}
}
Demo.
As assylias pointed out, Java's erasure will make that information unavailable at runtime - and thus a need for a hack.
On the assumption that myInterface has a getter for T, as in, MyInterface.getValue():T (or the hack would be to add it) you could do something like this (ignoring the possibility that getValue() could return null):
public <T extends Number> Class<T> inferInstanceType(MyInterface<T> myInterface){
return myInterface.getValue().getClass()
}
Below is the full implementation
public class Q34271256 {
public static interface MyInterface<T> {
T getValue();
}
public static class MyDoubleClass implements MyInterface<Double> {
private final Double value;
public MyDoubleClass(Double value) {
this.value = value;
}
#Override
public Double getValue() {
return value;
}
}
public static class MyIntegerClass implements MyInterface<Integer> {
private final Integer value;
public MyIntegerClass(Integer value) {
this.value = value;
}
#Override
public Integer getValue() {
return value;
}
}
#SuppressWarnings("unchecked")
public static <T extends Number> Class<T> inferInstanceType(MyInterface<T> myInterface){
Number value = myInterface.getValue();
if (value == null) return null;
return (Class<T>)value.getClass();
}
public static void main(String...args) {
List<MyInterface<? extends Number>> list = Arrays.asList(
new MyDoubleClass(1.1),
new MyIntegerClass(5)
);
for (MyInterface<? extends Number> myInterface : list) {
Class<?> type = inferInstanceType(myInterface);
System.out.printf("%s inferred type is %s\n",
myInterface.getClass().getName(),
type.getName());
}
}
}
And the output should look something like this:
MyDoubleClass inferred type is java.lang.Double
MyIntegerClass inferred type is java.lang.Integer
I have the following two classes:
public class GenericNumberOperation {
public GenericNumberOperation() {}
public <T extends Number> T getSomeValue (boolean tf) {
T number;
if(tf) {
number = new Double(1.0);
}
else {
number = new Integer(11);
}
return (T) number;
}
}
And:
public class GenericNumberTest {
public GenericNumberTest() {}
public static void main(String[] args) {
GenericNumberOperation gno = new GenericNumberOperation();
Double d = gno.getSomeValue(true);
Integer i = gno.getSomeValue(false);
}
}
When I run the test, everything is hunky-dory. If I change the type parameterization to:
public <T> T getSomeValue(boolean tf)
The compiler complains, reporting:
error: incompatible types Integer cannot be converted to T
number = new Integer(11);
where T is a type variable
T extends Object declared in method getSomeValue(boolean)
It complains similarly about the Double. Why?
EDIT:
I made a mistake. This is actually the code that works.
public class GenericNumberOperation {
public GenericNumberOperation() {}
public <T extends Number> T getSomeValue (boolean tf) {
Number number;
if(tf) {
number = new Double(1.0);
}
else {
number = new Integer(11);
}
return (T) number;
}
}
And now I understand what #Sotirios was getting at.
Forget about what you're trying to use this for. We're only going to look at this from a language perspective.
The declaration
public <T extends Number> T getSomeValue (boolean tf) {
defines a new type T that is bounded by Number. That means that a caller can only bind Number or any subtype of Number to T when invoking the method. Within the method, you don't know what that type might be.
You therefore can't do
T number = new Double(1.0);
because you don't know that T is Double. If I invoked the method as
Float f = genOp.getSomeValue(true);
T should have been Float. The compiler can't guarantee type safety and therefore rejects it (the assignment within the method, if it had been allowed, a ClassCastException would have been thrown at runtime). If you use a cast, you're telling the compiler that you're sure about what you're doing. It'll warn you, but it will trust you.
Similarly, the declaration
public <T> T getSomeValue(boolean tf)
defines a new type T that is unbounded. That means that you can bind any type to T, which makes the problem even greater. I can now do
String f = genOp.getSomeValue(true);
As #Sotirios Delimanolis wrote, you cannot even run that code.
Try this one:
#SuppressWarnings("unchecked")
public <T extends Number> T getSomeValue(boolean tf) {
T number;
if (tf) {
number = (T) new Double(1.0);
} else {
number = (T) new Integer(11);
}
return number;
}
Can we create a Type class object in Java generics like T t = new T();
Here is my code,
public class Graph<T extends NeighbourInt<T>> {
Map<String, List<T>> adjecencyList;
public Graph() {
adjecencyList = new HashMap<>();
}
public void addEdge(String vertex1, String vertex2, int weight) {
if (adjecencyList.containsKey(vertex1)) {
List<T> neg = adjecencyList.get(vertex1);
neg.add(new T (vertex2, weight));
} else {
List<T> neg = new ArrayList<>();
neg.add(new T(vertex2, weight));
adjecencyList.put(vertex1, neg);
}
}
}
My NeighbourInt interface
public interface NeighbourInt<T> extends Comparable<T> {
public String getVertex();
public void setVertex(String vertex);
public int getWeight();
public void setWeight(int weight);
}
Is there possible way to initiate an object like new T(); in Java Generics?
Nope, not yet (because of erasure, again)
But, the constructor of Graph could take in a generator that creates a T from (String,int); call this generator when you need to create a new T.
In java 8, you can do
public Graph( BiFunction<String,Integer,T> generator )
and when you need to create a T, do generator.apply(string,integer)
Say you have a constructor in a subtype of NeighbourInt
public Foo(String, int)
you can do
new Graph<>( Foo::new )
No. Actually, T is the parameter for the generic type, not a class.
For example:
public interface NeighbourInt extends Comparable<NeighbourInt> {
// ...
}
The code above is declaring the NeighbourInt as a Comparable with parameter NeighbourInt.
As the Comparable interface is defined as:
public interface Comparable<T> {
int compareTo(T o);
}
the parametrized Comparable<NeighbourInt> would be equivalent to an interface having the method:
int compareTo(NeighbourInt o);
So the NeighbourInt declared above is inheriting that method.
EDIT: Think of a generic class as a class that is a "factory of classes", as a class that manufactures other classes. So only create a generic class when you need to have many "manufactured" classes with different types as a parameter.
So declaring:
public class Graph<T extends NeighbourInt> {
// ...
}
only makes sense if you're having many "types of graphs", like:
Graph<Node> graph;
Graph<WeightedNode> weightedGraph;
// and so on...
If you're only having a graph of NeighbourInts, then your first option is to write:
public class Graph {
// this is where you set the generic parameter
Map<String, List<NeighbourInt>> adjecencyList;
// ...
}