Instantiate a Generic Type [duplicate] - java

This question already has answers here:
Instantiating a generic class in Java [duplicate]
(10 answers)
Closed 9 years ago.
My code is:
public class MyClass<T extends MyComponent> {
private T t;
public MyClass(){
t = new T();
}
}
But the compiler don't accept new T(). Is there a way to do this using the constructor MyClass(), without parameters?

You could do
public class MyClass<T extends MyComponent> {
private T t;
MyClass(Class<T> clazz) throws InstantiationException,
IllegalAccessException {
t = clazz.newInstance();
}
}

Because of type erasure, the JVM doesn't know what T is, so it can't instantiate it. The workaround is to provide a Class<T> and use it to create a new instance:
public MyClass(Class<T> clazz)
{
t = clazz.newInstance();
}
You'll have to add catching IllegalAccessException and InstantiationException.

Not without access to T's class object. Think about it, T could be any subclass of MyComponent, how would you even decide which constructors are available on that particular subclass?
Type erasure means that the compiler silently replaces all "real" references to T with MyComponent.
If you have a reference to Class, you may call Class#newInstance, or get a constructor and invoke that.

Related

Cast to generic subclass in Java [duplicate]

This question already has an answer here:
How to check a (unchecked) cast in java?
(1 answer)
Closed 3 years ago.
I want to write universal function, which can make an object of any type by name and return it as its own type, not as Object type.
import java.lang.reflect.Constructor;
public class Test{
static <T extends Object> T makeObject(String className) {
try {
Class<?> c = Class.forName(className);
Constructor<?> constructor = c.getConstructor();
Object object = constructor.newInstance();
return (T)c.cast(object);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
//without casting
String obj = makeObject("java.lang.String");
System.out.println(obj.getClass());
}
}
It works fine, but I get the warning
Type safety: Unchecked cast from capture#4-of ? to T
What to do to fix the problem without adding #SuppressWarnings("unchecked")?
If you want this to be safe you need to pass the class as a parameter, otherwise there is no way you're going to get what you want. Your code will compile whatever I ask the return type to be, but will fail at runtime if the type isn't compatible.
Try it out:
String s = makeObject("java.lang.String"); // compiles and runs
Integer i = makeObject("java.lang.String"); // compiles but fails at runtime with java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
A safe version would look like that
static <T> T makeObject(Class<T> clazz) throws Exception {
return clazz.getConstructor().newInstance();
}
but that suggests you already know what type you want to have instead of just getting a class name from a file or something.

Generic type of superclass property lost in subclass with no type bound [duplicate]

This question already has answers here:
What is a raw type and why shouldn't we use it?
(16 answers)
Closed 4 years ago.
Here is a pathological generics example in Java. What is going on here?
public abstract class Foo<X> {
private List<String> stuff;
public List<String> getStuff() {
return stuff;
}
public void setStuff(List<String> stuff) {
this.stuff = stuff;
}
}
Then I created a subclass, but not I did not specify the type bound, which should make it object.
public class Bar extends Foo {
public Bar() {
setStuff(new ArrayList<>());
}
public void whatIsGoingOnHere() {
for(String thing : getStuff())
System.out.println("Why is this a compiler error???");
}
}
Why is this a compiler error?
You call setStuff(new ArrayList<>());. Here ArrayList<> isn't not bound, it is inferred by the compiler if it can. And it can as setStuff is setStuff(List<String>). So the compiler knows it is a ArrayList<String> and uses (infers) that.
Your loop iterates over an List<String> as returned by the getStuff() method, so defining the thing as a String (or any super class or interface) will be okay for the compiler.
The base class does have an X type, but it doesn't matter as your stuff list is declared with a type. Only if you would define stuff as an List<X> it would matter what the subclass defined for X.

How to use an instance of Class as a generic type? [duplicate]

This question already has answers here:
Specifying a generic type in java from Class object
(7 answers)
Closed 5 years ago.
I would like to do something like this in java 8:
public void example(Class clazz) {
MyClass<clazz> myObj = new MyClass<clazz>();
}
But I'm getting "cannot find symbol: symbol class clazz location: "
Is this possible? Thanks!
Generic type parameters must be type names, not variable names.
Declare a generic type parameter for your method, and use it in your parameter and variable declaration.
public <T> void example(Class<T> clazz) {
MyClass<T> myObj = new MyClass<T>();
}
Generally one uses single capital letters as type variables, e.g. T, to distinguish them easily from normal variables, e.g. clazz.
Since you want clazz to be a type, you must pass it as a type parameter:
public <T> void example() {
MyClass<T> myObject = new MyClass<T>();
}
You can do this :
public void example() {
MyClass<Class> myObj = new MyClass<Class>();
}
You can not put variables inside <>

Passing Child.class as argument [duplicate]

This question already has answers here:
Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?
(19 answers)
Closed 5 years ago.
I have a method that should receives a Class<A>, something like:
protected void method(final Class<A> clazz) {
}
Then when I try to call like method(A.class) it do works, but if I try method(B.class), where B is child of A, I get the message "incompatible types".
The solution is change to Class<B>, but I have another childs that I like to pass as argument to this method(), like C.class.
One solution would be to use a bounded wildcard when defining the parameter:
protected void method(final Class<? extends A> clazz) {
// Code here...
}
With this, you are allowed to pass A's class directly or any class that extends from A.
Or as Pavlo suggested:
protected <T extends A> void method(final Class<T> clazz) {
// Code here...
}
Both will work, but it would help to know what you plan to do with clazz so we can select one over the other.

How do I create an instance of a parameterized interface [duplicate]

This question already has answers here:
Create instance of generic type in Java?
(29 answers)
Closed 7 years ago.
I have this code:
ObjProcessor processor = getProcessor();
MyClass myObj = getObjToProcess();// MyClass extends PersistentObj
and classes:
public class ObjProcessor {
public <OP extends PersistentObj) void process(Class<OP> objClazz, OP object, Modifier<OP> modifier) {
...
}
}
public interface Modifier<T> {
void modify(T obj);
}
I am stuck. How do I create an instance of the Modifier to be able to invoke:
processor.process(myObj.getClass(), myObj, ???);
After Ron C's comment, I created this Modifier:
Modifier<MyClass> mod = new Modifier<MyClass>() {
#Override
public void modify(MyClass obj) {
// empty
}
};
proc.process(myObj.getClass(), myObj, mod); // compilation error!
Eclipse gave this error:
The method process(Class<OP>, OP, Modifier<OP>) in the type ObjProcessor is not applicable for the arguments (Class< capture#1-of ? extends MyClass>, MyClass, Modifier<MyClass>)
You can create an anonymous inner class as an instance of the Modifier interface:
processor.process(myObj.getClass(), myObj, new Modifier<MyClass>() {
#Override
public void modify(MyClass obj) {
//Add implementation here
}
});
If you're using java 8, you can also use lambada expressions. Because your interface is considered as a Functional Interface (interface with only one method), you can use lambada expression instead of creating anonymous class:
processor.process(myObj.getClass(), myObj, obj -> {
//Add implementation here
});
For the second problem, the solution is to change the declaration of process to:
public <OP extends ObjProcessor> void process(Class<? extends OP> objClazz, OP object, Modifier<OP> modifier) {
}
I've replaced Class<OP> with Class<? extends OP>. The older decleration only works with: MyClass.class, but not with: instanceOfMyClass.getClass().
The reason for this is that the Class<OP> type argument can't accept Class<ClassExtendsOP> as an argument, it's only allow one class.
If your'e using MyClass as OP,
when you're using MyClass.class, you're always getting Class<MyClass> object. But when you're using instanceOfMyClass.getClass(), you can get Class<ClassExtendsMyClass>, which not match the argument type.

Categories

Resources