I have this code:
public class Test<T extends Number>{
public static void main(String[] args){
Test<Short> test = new Test(Short.class);
System.out.println(test.get());
}
private Class<T> clazz;
public Test(Class<T> clazz){
this.clazz=clazz;
}
public T get(){
if(clazz == Short.class)
return new Short(13); //type missmatch cannot convert from Short to T
else return null;
}
}
but it does not compile... Any Idea how I repair this?
You cannot construct a Short with an int (there is no such constructor), and you could cast to T like
public T get() {
if (clazz == Short.class)
return (T) Short.valueOf((short) 13);
else
return null;
}
Because your return type is generic T not Short. so you will get type mismatch.
The kind of construction in your code looks more suitable for a non-generics implementation:
Instead of:
public T get() {
Declare it as:
public Number get () {
Even if you write below, compiler will complain
Short s = new Short(13); //The constructor Short(int) is undefined
workaround
Short s = new Short((short) 13);
your case
return (T) new Short((short) 13);
public T get() {
if (clazz == Short.class) {
Short s = 13;
return (T) s;
} else {
return null;
}
}
Related
I'm not sure how to classify what I'm trying to achieve
I think that I can define it like that:
I'm trying to create a method that will return a generic type with his wrapper class
I'll just show what I'm trying to do
I have a string that represents a JSON that I got from calling an endpoint
String httpBody = "{...}";
I have a class name EndPointResponse
public class EndPointResponse<T> {
private T responseObj = null;
...
public EndPointResponse(T responseObj, ...) {
this.responseObj = responseObj;
...
}
}
in another part of the code, I'm trying to create this object by calling another function
EndPointResponse<SomeObject> o1 = getEndPointResponse(httpBody, SomeObject.class);
I want to be able to get this object in more ways:
EndPointResponse<List<SomeObject>> o2 = getEndPointResponse(httpBody, SomeObject.class, List.class);
or
EndPointResponse<SomeWrapperObject<SomeObject>> o3 = getEndPointResponse(httpBody, SomeObject.class, SomeWrapperObject.class);
what I've done so far:
public static <T> EndPointResponse<T> getEndPointResponse(String httpBody, Class<T> classOfT){
T result = getResultObject(httpBody, classOfT);
if(result == null){
return createEndPointResponse(httpBody, ...with some data);
}
return createEndPointResponse(result, ...with some other data);
}
public static <T> EndPointResponse<List<T>> getEndPointResponse(String httpBody, Class<T> classOfT, Class<?> wrapperClass){
List<T> result = getResultObject(httpBody, classOfT, wrapperClass);
if(result == null){
return createEndPointResponse(httpBody, ...with some data);
}
return createEndPointResponse(result, ...with some other data);
}
private static <T> T getResultObject(String resultString, Class<T> classOfT){
T resultObj = null;
try{
resultObj = gson.fromJson(resultString, classOfT);
}
catch (JsonSyntaxException e){
...some log
}
return resultObj;
}
private static <T> List<T> getResultObject(String resultString, Class<T> classOfT, Class<?> wrapperClass){
List<T> resultObj = null;
try{
resultObj = gson.fromJson(resultString, getType(classOfT, wrapperClass));
}
catch (JsonSyntaxException e){
... some log
}
return resultObj;
}
private static <T> EndPointResponse<T> createEndPointResponse(T resultObj, ...){
return new EndPointResponse<T>(resultObj, ...);
}
private static <T> EndPointResponse<List<T>> createEndPointResponse(List<T> resultObj, ...){
return new EndPointResponse<List<T>>(resultObj, ...);
}
private static <T> Type getType(Class<T> classOfT, Class<?> wrapperClass){
return new ParameterizedType() {
private Type type;
#Override
public Type[] getActualTypeArguments() {
return new Type[] {classOfT};
}
#Override
public Type getRawType() {
return wrapperClass;
}
#Override
public Type getOwnerType() {
return null;
}
};
}
so basically I'm trying to create another overloaded method that instead of a List class it will be any wrapper class that I want or even better is to generalize the List class overload method so it will support any wrapper class
something like this: (just an example it's not going to have the right syntax)
public static <T> EndPointResponse<W<T>> getEndPointResponse(String httpBody, Class<T> classOfT, Class<W> wrapperClass){
W<T> result = getResultObject(httpBody, classOfT, wrapperClass);
if(result == null){
return createEndPointResponse(httpBody, ...with some data);
}
return createEndPointResponse(result, ...with some other data);
}
------------------------------------
private static <T> W<T> getResultObject(String resultString, Class<T> classOfT, Class<W> wrapperClass){
W<T> resultObj = null;
try{
resultObj = gson.fromJson(resultString, getType(classOfT, wrapperClass));
}
catch (JsonSyntaxException e){
... some log
}
return resultObj;
}
------------------------------------
private static <T> EndPointResponse<W<T>> createEndPointResponse(W<T> resultObj, ...){
return new EndPointResponse<W<T>>(resultObj, ...);
}
does anyone have an idea of how I can achieve that?
any help or constructive review will be appreciated :)
thanks
I am moving from C++ to Java. Now I am trying a generics method. But the compiler always complains below error
The method getValue() is undefined for the type T HelloTemplate.java /helloTemplate/src/helloTemplate
The error was pointing to t.getValue() line
As I understand, T is class MyValue, which has the method getValue
What is wrong? How Can I fixed this. I am using Java1.8
public class MyValue {
public int getValue() {
return 0;
}
}
public class HelloTemplate {
static <T> int getValue(T t) {
return t.getValue();
}
public static void main(String[] args) {
MyValue mv = new MyValue();
System.out.println(getValue(mv));
}
}
The compiler doesn't know that you are going to pass to getValue() an instance of a class that has a getValue() method, which is why t.getValue() doesn't pass compilation.
It will only know about it if you add a type bound to the generic type parameter T:
static <T extends MyValue> int getValue(T t) {
return t.getValue();
}
Of course, in such a simple example you can simply remove the generic type parameter and write:
static int getValue(MyValue t) {
return t.getValue();
}
Just you need casting before calling the method. return ((MyValue) t).getValue();
, so that compiler can know that it's calling the MyValue's method.
static <T> int getValue(T t) {
return ((MyValue) t).getValue();
}
in case of multiple classes, you can check for instances using instanceofoperator, and the call the method.. like below
static <T> int getValue(T t) {
//check for instances
if (t instanceof MyValue) {
return ((MyValue) t).getValue();
}
//check for your other instance
return 0; // whatever for your else case.
BACKGROUND:
I am trying to implement a tiny template, i.e. generic class, which would allow me to achieve a pass-by-reference functionality as follows.
public static class Ref<T> {
T value;
public Ref(T InitValue) { this.set(InitValue); }
public void set(T Value) { this.value = Value; }
public T get() { return this.value; }
}
So, I could define a function that takes a 'Ref' where the value can actually be changed, e.g.
public static void function(Ref<Byte> x)
{
x.set((byte)0x7E);
}
The initialization of the variable to be passed by reference looks not so elegant.
Ref<Byte> to_be_changed = new Ref<Byte>((byte)0);
...
function(to_be_changed);
...
Byte result = to_be_changed.get()
QUESTION:
Is there a way in Java to do it better? Can the constructor initialize directly a '0' according to the primitive type related to the wrapper type which is passed as template type? I.e something like
...
public Ref() { this.value = (T.relatedPrimitiveClass())0; }
...
where Integer.relatedPrimitiveClass() shall deliver int; Byte.relatedPrimitiveClass() delivers byte.
First and the most important thing to understand is that java generics are not templates. Generics are classes/interfaces that are parameterized over types. I recommend reading generics tutorial from oracle: https://docs.oracle.com/javase/tutorial/java/generics/types.html
It is possible to use reflection to get the parametrized type T of your Ref class and use that to determinate the initial value for default construtor, but I would not recommend doing so.
Instead of reflection you can create subclasses for types, that require default constructors (e.g. object versions of primitives):
public static class ByteRef extends Ref<Byte> {
public ByteRef() {
super((byte)0);
}
public ByteRef(byte value) {
super(value);
}
// I'm not sure, if I like this one :-)
public void set(int value) {
super.set((byte)value);
}
}
Instead of subclassing, you can also add new methods to Ref class:
public static class Ref<T> {
T value;
public Ref(T initValue) {
this.set(initValue);
}
public void set(T Value) {
this.value = Value;
}
public T get() {
return this.value;
}
public static Ref<Byte> createByteRef() {
return new Ref<Byte>((byte)0);
}
public static Ref<Byte> createByteRef(byte value) {
return new Ref<Byte>(value);
}
}
Or you could create separate factory classes:
public class Refs {
public static Ref createByteRef() {
return new Ref((byte)0);
}
public static Ref<Byte> createByteRef(byte value) {
return new Ref<Byte>(value);
}
}
The last option is to use reflection to get the parameterized type. I personally would not use this solution, because number of primitive classes is finite and you have option to create much neater interfaces with subclassing
public abstract static class PrimitiveNumberRef<T extends Number> extends
Ref<T> {
private Class<T> type;
public PrimitiveNumberRef() {
// This requires default constructor for Ref class
type = getGenericType(getClass());
super.set((T) getInitialValue(type));
}
#Override
public void set(T value) {
if (value == null) {
throw new IllegalArgumentException(
"Null value is not allowed for PrimitiveNumerRef type: "
+ type);
}
if (!type.isInstance(value)) {
throw new IllegalArgumentException("Unsupported value type: "
+ value.getClass());
}
super.set(value);
}
#SuppressWarnings("unchecked")
private static <T> Class<T> getGenericType(Class<?> clz) {
return (Class<T>) ((ParameterizedType) clz.getGenericSuperclass())
.getActualTypeArguments()[0];
}
private static <T> T getInitialValue(Class<T> clz) {
if (clz == Byte.class) {
return clz.cast((byte) 0);
} else if (clz == Short.class) {
return clz.cast((short) 0);
} else if (clz == Integer.class) {
return clz.cast((int) 0);
} else if (clz == Double.class) {
return clz.cast((double) 0);
} else if (clz == Float.class) {
return clz.cast((float) 0);
} else if (clz == Long.class) {
return clz.cast((long) 0);
} else {
throw new IllegalArgumentException("Unsupported type: "
+ clz.getName());
}
}
}
PrimitiveNumberRef is instantiated as follows:
Ref<Long> val1 = new PrimitiveNumberRef<Long>() { };
The error:
CAP#1 is not a fresh type
The code:
public Boolean isAssigned(HttpServletRequest request, String name, Foo foo) {
Boolean isAssigned = false;
if ((foo.getClass()) request.getSession().getAttribute(name) != null) {
isAssigned = true;
}
return isAssigned;
}
What is the solution?
May not be what you are looking for but it answers the question in the title.
The Class<T> class has a cast method which can cast any object to its own type T. Obviously it will throw a ClassCastException if the object cannot be cast to that type.
public <T> T castTo(Class<T> t, Object o) {
return t.cast(o);
}
public <T> T castTo(T t, Object o) {
return (T) castTo(t.getClass(), o);
}
public void test() {
String s = "Hello";
Object b = s;
String c = castTo(String.class, b);
String d = castTo("Some String", b);
}
If you want to test whether
request.getSession().getAttribute(name)
is of type Foo and execute a method method on it afterwards you could simply try using instanceof and cast:
if (request.getSession().getAttribute(name) instanceof Foo) {
((Foo) request.getSession().getAttribute(name)).method();
}
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