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();
}
Related
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.
I'm looking for a functional interface that satisfies the following two requirements:
Should accept and return the same type
The type should be inferred while calling the method on the FunctionalInterface
If the requirement had just been the first, I can create a simple FunctionalInterface as follows:
#FunctionalInterface
public interface MonoFunction<T> {
T apply (T arg);
}
But, this would require the type to be specified while using the interface. But, I want the type to be inferred. Something like the below pseudo-code:
class A {
int a;
}
class B {
int b;
}
public static void main (String[] args) {
A a;
B b;
MonoFunction foo = (obj) -> {
system.out.println (obj)
return obj;
};
a = foo.apply (new A());
b = foo.apply (new B());
}
How do I achieve something like this?
You could use the UnaryOperator<T> but you have to define beforehand what type you're expecting.
UnaryOperator<A> foo = a -> {
system.out.println(a);
return a;
};
Otherwise, just cast your result into the variable type :
a = (A) foo.apply (new A());
b = (B) foo.apply (new B());
Use a generic factory method returning the function:
static <T> UnaryOperator<T> getFooFunction() {
return obj -> {
System.out.println(obj);
return obj;
};
}
public static void main (String[] args) {
A a;
B b;
UnaryOperator<A> fooA = getFooFunction();
a = fooA.apply(new A());
UnaryOperator<B> fooB = getFooFunction();
b = fooB.apply(new B());
System.out.println(fooA==(Object)fooB);
}
Note that getFooFunction() does not only return the same function semantically, given the current implementation (HotSpot/OpenJDK), it will even be the same object, as you can test easily via fooA==(Object)fooB, so there is no reason to sacrifice the Generic’s type safety.
It’s the same thing that happens when you use UnaryOperator.identity().
The other answers already discuss how to use UnaryOperator<T>. While that approach provides the type safety of Java generics, you still have to specify the type upon creating the UnaryOperator. While I would recommend the UnaryOperator approach in most situations, you specifically asked (in the comments) how one might avoid specifying the type <T>, even if you had to give up type safety.
You can make a MonoFunction implementation as follows (unsafe and usually not recommended):
public class MonoFunction {
private UnaryOperator<Object> func;
#SuppressWarnings("unchecked")
public <T> MonoFunction(UnaryOperator<T> func) {
this.func = (UnaryOperator<Object>) func;
}
#SuppressWarnings("unchecked")
public <T> T apply(T obj) {
return (T) func.apply(obj);
}
}
Note that this is not a #FunctionalInterface, so you'll have to put your lambda expression inside a new MonoFunction(...) call, as follows:
public class MonoFunctionTest {
public static void main(String[] args) {
A a;
B b;
MonoFunction foo = new MonoFunction((obj) -> {
System.out.println(obj);
return obj;
});
a = foo.apply(new A()); // toString in A
b = foo.apply(new B()); // toString in B
MonoFunction bad = new MonoFunction((A obj) -> {
System.out.println(obj);
return obj;
});
a = bad.apply(a); // toString in A
b = bad.apply(b); // ClassCastException: B cannot be cast to A
}
}
class A {
public String toString() { return "toString in A"; }
}
class B {
public String toString() { return "toString in B"; }
}
I stress again that this is unsafe, and it is relatively easy to get a ClassCastException as demonstrated.
This is possible using a generic method within a functional interface:
#FunctionalInterface
interface Identity {
< T > T apply( T input );
}
Unfortunately an interface defined like this cannot be implemented using a lambda function. Instead it must be done the old way using a class, and most concisely with an anonymous class:
Identity id = new Identity() {
public < T > T apply( T anyInput ){
// do something
return anyInput;
}
};
This then works for any input:
class A {
int a = 1;
}
String outputString = id.apply( "one" );
int outputInteger = id.apply( 1 );
A outputClass = id.apply( new A() );
If i put object of A class as argument of someMeth(Object o), how can i access to this object methods? I cant change or overrdie someMeth(Object o).
...
void someMeth(Object o) {
o.setS("example"); -- exception : setS() is undefined for type Object
}
...
class A {
private String s;
String getS () {
return s;
}
void setS(String value) {
s = value;
}
}
...
someMeth(new A());
Try casting the object o to they type A like so:
A newObj = (A) o;
Then you can do:
newObj.setS("example");
Or a shorter, one line version:
((A)o).setS("example");
Try to convert type of reference:
void someMeth(Object o) {
if (o instanceof A) {
((A) o).setS("example");
}
}
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;
}
}
I'd like to create a generic enum-based mapper for IBatis. I'm doing this with the below code. This does have compile time errors, which I don't know how to fix. Maybe my solution is just plain wrong (keep in mind the use of IBatis), in such case please suggest something better.
Any help appreciated.
What I want to achieve is to define subsequent mappers as:
public class XEnumTypeHandler extends CommonEnumTypeHandler<X> {
}
The current code:
public class CommonEnumTypeHandler<T extends Enum> implements TypeHandlerCallback {
public void setParameter(ParameterSetter ps, Object o) throws SQLException {
if (o.getClass().isAssignableFrom(**T**)) {
ps.setString(((**T**) o).value().toUpperCase());
} else
throw new SQLException("Excpected ParameterType object than: " + o);
}
public Object getResult(ResultGetter rs) throws SQLException {
Object o = valueOf(rs.getString());
if (o == null)
throw new SQLException("Unknown parameter type: " + rs.getString());
return o;
}
public Object valueOf(String s) {
for (T pt : T.**values()**) {
if (pt.**value()**.equalsIgnoreCase(s))
return pt;
}
return null;
}
}
I've added error markings to the above code, the error messages are in order:
T cannot be resolved
The method value() is undefined for
the type T
The method values() is undefined for
the type T
The method values() is undefined for
the type T
I've solved this issue with the following code:
public class CommonEnumTypeHandler<T extends Enum> implements TypeHandlerCallback {
Class<T> clazz;
public CommonEnumTypeHandler(Class<T> clazz) {
this.clazz = clazz;
}
public void setParameter(ParameterSetter ps, Object o) throws SQLException {
if (o.getClass().isAssignableFrom(clazz)) {
ps.setString(((T) o).name().toUpperCase());
} else
throw new SQLException("Excpected " + clazz + " object than: " + o);
}
public Object getResult(ResultGetter rs) throws SQLException {
Object o = valueOf(rs.getString());
if (o == null)
throw new SQLException("Unknown parameter type: " + rs.getString());
return o;
}
public Object valueOf(String s) {
return Enum.valueOf(clazz, s);
}
}
Inheriting from this class I do:
public class SalesChannelTypeHandler extends CommonEnumTypeHandler<SalesChannel> {
public SalesChannelTypeHandler() {
super(SalesChannel.class);
}
public SalesChannelTypeHandler(Class<SalesChannel> clazz) {
super(clazz);
}
}
I'm not sure what you're doing (a general overview in words would be nice), but:
You can't do isAssignableFrom(T) (you need a Class object), and you can't do instanceof T either (generics are non-reified). You may want to pass Class<T> type tokens instead.
Have you looked at EnumMap?
See also
Java Tutorials/Runtime Type Tokens
Neal Gafter's Blog - Super Type Tokens
Josh Bloch - Typesafe Heterogenous Container (THC) pattern (PDF)
It's still not clear what is desired, but perhaps it's something along the lines of this:
enum Color { BLACK, WHITE; }
public static void main(String[] args) {
Color c = Enum.valueOf(Color.class, "black".toUpperCase());
System.out.println(c); // prints "BLACK"
}
So we use Enum.valueOf that takes a type token Class<T extends Enum<T>>, and ask it for the enum constant with a given name. valueOf is NOT case-insensitive, but by conventions, all constants should be in uppercase, so we simply take the query string and turn it .toUpperCase().
As pointed by Polygenelubricants, you need to pass concrete runtime types around, e.g. Class<?> instead of syntactic compiletime types like generic parameters. Here's a rewrite how you could use it:
public abstract class CommonEnumTypeHandler<E extends Enum<E>> implements TypeHandlerCallback {
private Class<E> enumClass;
public CommonEnumTypeHandler(Class<E> enumClass) {
this.enumClass = enumClass;
}
public void setParameter(ParameterSetter ps, Object o) throws SQLException {
if (enumClass.isInstance(o)) {
ps.setString((enumClass.cast(o)).name().toUpperCase());
} else {
throw new SQLException("Excpected ParameterType object than: " + o);
}
}
public Object getResult(ResultGetter rs) throws SQLException {
try {
return Enum.valueOf(enumClass, rs.getString());
} catch (IllegalArgumentException e) {
throw new SQLException("Unknown parameter type: " + rs.getString(), e);
}
}
}
Which you can then use as follows:
public class XEnumTypeHandler extends CommonEnumTypeHandler<X> {
public XEnumTypeHandler() {
super(X.class);
}
}