If I have this class:
class Foo<T> implements SomeInterface
{
final private List<T> list = new ArrayList<T>();
final private Class<? extends T> runtimeClass;
public Foo(Class<? extends T> cl) { this.runtimeClass = cl; }
// method override from SomeInterface
#Override public boolean addChild(Object o)
{
// Only add to list if the object is an acceptible type.
if (this.runtimeClass.isInstance(o))
{
list.add( /* ??? how do we cast o to type T??? */ );
}
}
public List<T> getList()
{
return this.list;
} // yes, I know, this isn't safe publishing....
}
how would I perform a runtime cast from Object to type T?
Use this:
list.add(this.runtimeClass.cast(o))
See Class.cast() for details
// method override from SomeInterface
#Override public boolean addChild(Object o)
{
// Only add to list if the object is an acceptible type.
if (this.runtimeClass.isInstance(o))
{
list.add((T)o);
}
}
Related
Best way to avoid this warning? Is there any case/example where the (T) cast can fail? (Java language compiled with Eclipse)
Example updated for reference with Lee's answer: cast fail subtly using result.
interface Test {
}
class Test1 implements Test {
void doSomething() {}
}
class Test2 implements Test {}
public class TestIterable<T extends Test> implements Iterable<T> {
final ArrayList<T> result=new ArrayList<>();
public TestIterable(Object obj) {
if (obj instanceof Test) {
Test t = (Test) obj;
result.add((T) obj); // Warning: unchecked cast from Test to T
// Iteresting decompilation result....
// result.add((Test) obj);
}
}
#Override
public Iterator<T> iterator() {
return result.iterator();
}
public static void main(String[] args) {
TestIterable<Test1> x = new TestIterable<>(new Test2());
for (Test1 y :x.result) {
y.doSomething();
// java.lang.ClassCastException
};
}
}
Two alternatives. The natural solution to require a T object probably does not fit your needs. Then the type T has to be explicitly passed because of the type erasure making any other construct senseless.
class TestIterable<T extends Test> implements Iterable<T> {
final List<T> result = new ArrayList<>();
public TestIterable(T obj) {
result.add(obj);
}
public TestIterable(Class<T> type, Object obj) {
if (obj == null || type.isAssignableFrom(obj.getClass())) {
result.add(type.cast(obj));
}
}
#Override
public Iterator<T> iterator() {
return result.iterator();
}
}
I have this compilation problem:
Here is the class in question:
package huru.entity;
import io.vertx.core.json.JsonObject;
import java.util.Date;
public class BaseEntity <T extends BaseModel> extends JsonObject {
private T model;
public BaseEntity(T m){
this.model = m;
}
public void setUpdateInfo(String user){
this.model.updatedBy = user;
this.model.updatedAt = new Date();
}
public JsonObject toJsonObject(){
return JsonObject.mapFrom(this.model);
}
public T getEntityType (){
return this.model.getClass(); // doesn't compile
}
}
I also tried using
public T getEntityType (){
return T; // doesn't compile
}
but that clearly doesn't work either. Anybody know how I can return the class instance of that generic type?
I also tried this:
public Class<T> getEntityType (){
return this.model.getClass();
}
and I get:
and then I tried this:
public Class<? extends T> getEntityType (){
return this.model.getClass();
}
and I have:
You appear to be confused. You're returning the class that represents T, not a T.
Let's replace T with String and show why what you're doing makes no sense:
private String model;
public String getEntityType() {
return model.getClass();
// Of course this does not work; model.getClass() is not a string!
}
public String getEntityType() {
return String;
// This doesn't even compile.
}
To try to explain, this:
public T getEntityType() {
....
}
requires you to return an actual instance of whatever T is. Not whatever type T is representing. Just like 'String' means you should return an actual instance of String, not the concept of String, the type.
Perhaps you meant to do this:
public T getEntityType() {
return model;
}
or more likely, given that you named this method 'getEntityType', what you mean is this:
public Class<? extends T> getEntityType() {
return model.getClass();
}
Yes, ? extends T, because model is a T, or any subtype of T.
What about the following code. I think it works.
public Class<? extends BaseModel> getEntityType (){
return model.getClass();
}
class Foo<T> {
final Class<T> typeParameterClass;
public Foo(Class<T> typeParameterClass) {
this.typeParameterClass = typeParameterClass;
}
public void bar() {
// you can access the typeParameterClass here and do whatever you like
}
}
Part of the problem is that getClass is defined in Object to give you a Class< ? > with a wildcard as the generic parameter. If you want to return Class< ? extends T > you will need to cast to that:
return (Class< ? extends T >) (model.getClass());
Is there any way how to make class type parameter more narrow (add another bound to it) in concrete method?
Let's look at example
public class Value<T>
{
private final T value;
public Value(T value)
{
this.value = value;
}
public <V extends T> boolean eq(V value)
{
return Objects.equals(this.value, value);
}
// here, I want to create bound that T extends Comparable<T>
// error: type parameter cannot be followed by other bounds
public <V extends T & Comparable<T>> boolean gt(V value)
{
return ((V)this.value).compareTo(value) > 0;
}
// here, I want to create bound that T extends String
// error: interface expected here
public <V extends T & String> boolean match(V value)
{
return ((V)this.value).equalsIgnoreCase(value);
}
public static void main(final String[] args)
{
final Value<Integer> integerValue = new Value<>(10);
integerValue.eq(10); // should compile
integerValue.gt(5); // should compile
integerValue.match("hello"); // shouldn't compile because match operates only on String values
final Value<String> stringValue = new Value<>("Foo");
stringValue.eq("Foo"); // should compile
stringValue.gt("bar"); // should compile
stringValue.match("foo"); // should compile
}
}
In this example line
integerValue.match("hello");
doesn't compile, which is correct, but the class can't be compile too due to restriction that type parameter cannot be followed by other bounds
Is there any other way how to achieve this?
An instance method must be available to all instances of the class. You can't declare a method that only exists for some instances of the class, those with certain type parameters.
What you can do is make a generic static method that takes an instance of the class as an argument. Since the generic type parameter is now specific to the method, it can be restricted to what the method wants:
public static <T> boolean eq(Value<T> obj, T value)
{
return Objects.equals(obj.value, value);
}
public static <T extends Comparable<T>> boolean gt(Value<T> obj, T value)
{
return obj.value.compareTo(value) > 0;
}
public static <T extends String> boolean match(Value<T> obj, T value)
{
return obj.value.equalsIgnoreCase(value);
}
Using the & operator assumes that V directly extends T and String, so one of them has to be an interface as a class can not directly extend two other classes. It doesn't work either for Comparable<T> as compilator can not garantee type safety with that typo.
You just have to use a , :
// here, I want to create bound that T extends Comparable<T>
// error: type parameter cannot be followed by other bounds
public <V extends T, T extends Comparable<T>> boolean gt(V value)
{
return ((V)this.value).compareTo(value) > 0;
}
// here, I want to create bound that T extends String
// error: interface expected here
public <V extends T, T extends String> boolean match(V value)
{
return ((V)this.value).equalsIgnoreCase(value);
}
Type bounds aren't the solution you need. What you need are subclasses.
public class Value<T>
{
protected final T value;
public Value(T value)
{
this.value = value;
}
public boolean eq(T value)
{
return Objects.equals(this.value, value);
}
}
public class ComparableValue<T extends Comparable<T>> extends Value<T>
{
public ComparableValue(T value)
{
super(value);
}
public boolean gt(T value)
{
return this.value.compareTo(value) > 0;
}
}
public class StringValue extends ComparableValue<String>
{
public StringValue(String value)
{
super(value);
}
public boolean match(String value)
{
return this.value.equalsIgnoreCase(value);
}
}
Then main becomes
public static void main(final String[] args)
{
final ComparableValue<Integer> integerValue = new ComparableValue<>(10);
integerValue.eq(10); // will compile
integerValue.gt(5); // will compile
integerValue.match("hello"); // will not compile
final StringValue stringValue = new StringValue("Foo");
stringValue.eq("Foo"); // will compile
stringValue.gt("bar"); // will compile
stringValue.match("foo"); // will compile
}
Normally when you implement a generic, you have some type T that you want to generalize. I want to write a class that generalizes a HashSet<T>.
I'm trying to write this the following way, but it's not the correct syntax or maybe it's not supported:
public class PermutationHelper<T> implements Iterable<T> {
private HashSet<T> m_set;
private long numberOfPermutations;
private boolean includeEmptyPermutationAsOutput = false;
public PermutationHelper(HashSet<T> set) {
m_set = set;
numberOfPermutations = 2 ^ set.size();
}
public void setIncludeEmptyPermutationAsOutput(boolean value) {
includeEmptyPermutationAsOutput = value;
}
#Override
public Iterator<T> iterator() {
Iterator<T> it = new Iterator<T>() {
long currentIndex = (includeEmptyPermutationAsOutput ? 0 : 1);
#Override
public boolean hasNext() {
return currentIndex < numberOfPermutations;
}
#Override
public T next() {
HashSet<T> result = new HashSet<T>();
return result; // expects T, but is a HashSet<T>..
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
};
return it;
}
}
I want the Iterator to give me all subsets of the passed-in HashSet<T>.
You can easly do
public class PermutationHelper<T extends HashSet<T>> implements Iterable<T>
in order to 'force' the generic type to be an HashSet or a subtype of a HashSet
What you want is simply
public class PermutationHelper<T> implements Iterable<HashSet<T>>
Your class is generic. You choose to name its generic type T. And it implements Iterable<HashSet<T>>, which means it must have a method
public Iterator<HashSet<T>> iterator()
I have an third-party RPC-API that provides an interface similar to that of java.sql.ResultSet (for reading values) and java.sql.PreparedStatement (for writing values). Assume it looks something like this:
public interface RemoteDeviceProxy {
public void setBoolean(Boolean value);
public void setInteger(Integer value);
// ...
public Boolean getBoolean();
public Integer getInteger();
// ...
}
I want to write a wrapper for this API that uses generics to create instances of specific types:
public class <T> RemoteVariable {
private final RemoteDeviceProxy wrappedDevice;
public RemoteVariable(RemoteDeviceProxy wrappedDevice) {
this.wrappedDevice = wrappedDevice;
}
public T get() {
// should call wrappedDevice.getBoolean() if T is Boolean, etc.
// how to implement?
}
public void set(T newValue) {
// should call wrappedDevice.setBoolean(newValue) if T is Boolean, etc.
// implement using instanceof
}
}
How can I implement the getter in my generic wrapper? I have found this answer which explains a similar scenario in depth, but I am not able to transfer this to my problem. Specifically, when I write this:
public T get() {
Type[] actualTypeArguments = ((ParameterizedType) getClass())
.getActualTypeArguments();
}
I get a compiler error saying I cannot cast to ParameterizedType, and I do not understand why. Can anyone explain how to achieve this?
Here is one way:
public class <T> RemoteVariable {
private final RemoteDeviceProxy wrappedDevice;
private final Class<T> clazz;
public RemoteVariable(RemoteDeviceProxy wrappedDevice, Class<T> clazz) {
this.wrappedDevice = wrappedDevice;
this.clazz = clazz;
}
public T get() {
if(clazz == Boolean.class){return clazz.cast(wrappedDevice.getBoolean());}
else if(clazz == Integer.class){return clazz.cast(wrappedDevice.getInteger());}
// ...
}
// ...
}
I thought over this quite a while and finally came up with a different approach:
First I added a getter to you RemoteVariable class:
protected RemoteDeviceProxy getWrappedProxy() {
return wrappedProxy;
}
Second I created a builder interface that will be used by a factory later:
public interface RemoteVariableBuilder {
public <T> RemoteVariable<T> buildNewVariable(RemoteDeviceProxy wrappedProxy);
}
Then I created non generic sub classes for Boolean...
public class RemoteBooleanVariable extends RemoteVariable<Boolean> implements RemoteVariableBuilder {
public RemoteBooleanVariable(RemoteDeviceProxy wrappedProxy) {
super(wrappedProxy);
}
#SuppressWarnings("unchecked")
#Override
public <T> RemoteVariable<T> buildNewVariable(RemoteDeviceProxy wrappedProxy) {
return (RemoteVariable<T>) new RemoteBooleanVariable(wrappedProxy);
}
#Override
public Boolean get() {
return getWrappedProxy().getBoolean();
}
#Override
public void set(Boolean value) {
getWrappedProxy().setBoolean(value);
}
}
... and Integer ...
public class RemoteIntegerBuilder extends RemoteVariable<Integer> implements RemoteVariableBuilder {
public RemoteIntegerBuilder(RemoteDeviceProxy wrappedProxy) {
super(wrappedProxy);
}
#SuppressWarnings("unchecked")
#Override
public <T> RemoteVariable<T> buildNewVariable(RemoteDeviceProxy wrappedProxy) {
return (RemoteVariable<T>) new RemoteIntegerBuilder(wrappedProxy);
}
#Override
public Integer get() {
return getWrappedProxy().getInteger();
}
#Override
public void set(Integer value) {
getWrappedProxy().setInteger(value);
}
}
actually eclipse created most of the code once it knew base class and interface.
The final step was to create a factory
public class RemoteVariableFactory {
private static final Map<String, RemoteVariableBuilder> BUILDERS = new HashMap<>();
static {
BUILDERS.put(Boolean.class.getName(), new RemoteBooleanVariable(null));
BUILDERS.put(Integer.class.getName(), new RemoteIntegerBuilder(null));
// add more builders here
}
public static <T> RemoteVariable<T> getRemoteVariable(RemoteDeviceProxy wrappedProxy, Class<T> typeClass) {
RemoteVariableBuilder remoteVariableBuilder = BUILDERS.get(typeClass.getName());
if (remoteVariableBuilder == null) {
return null; // or throw an exception whichever is better in your case
}
return remoteVariableBuilder.buildNewVariable(wrappedProxy);
}
}
Now we are ready to create new RemoteVariables...
RemoteVariable<Boolean> var1 = RemoteVariableFactory.getRemoteVariable(new RemoteDevice(), Boolean.class);
RemoteVariable<Integer> var2 = RemoteVariableFactory.getRemoteVariable(new RemoteDevice(), Integer.class);
To conclude this let's do a quick comparison to the answer of Eng.Fouad:
Disadvantage:
you need to create a new class for every datatype you provide
Advantage:
you only have to add one line to the static block of the factory and not two new if blocks to the getter and setter in RemoteVariable
get and set do not have to work through the if-else-blocks every time