Java: how to "instanceof argument" - java

I have tried:
package ro.ex;
import java.io.IOException;
import java.lang.reflect.Type;
class Ex {
public boolean isIns(Object o, Class t) {
o instanceof t;
}
public static void main(String[] args) throws IOException {}
}
above code will raise unknown class "t"
My question is: How to pass above code.
update:
following code can't pass intellij idea syntax checker
public boolean isIns(Object o, Class<?> t) {
return o instanceof t;
}
so the right code in idea is:
public boolean isIns(Object o, Class<?> t) {
return t.isAssignableFrom(o.getClass());
}
the more simple way is:
package ro.ex;
import java.io.IOException;
import java.lang.reflect.Type;
class Ex {
public boolean isIns(Object o, Class t) {
return t.isInstance(o);
}
public static void main(String[] args) throws IOException {
Object r = new Ex().isIns("", String.class);
System.out.println(r + "\t\t" + new Exception().getStackTrace()[0].getFileName() + ":" + new Exception().getStackTrace()[0].getLineNumber());
}
}

If you write x instanceof t, then t must be a class. In your isIns method, t is not a class, it is a variable of type Class.
The class Class, however, does offer methods with which you can decide whether some other class is a subclass of it: Class.isAssignableFrom(Class). So you can change you method to:
public boolean isIns(Object o, Class t)
{
return t.isAssignableFrom(o.getClass());
}
(I also changed your code so that the result of is returned to the caller.)

I have no idea what you are trying to do with your method, but the instanceof syntax is wrong.
public boolean isIns(Object o, Class t) {
return o instanceof t;
}
instanceof keyword checks with a Valid class name not with variable name. That's the compiler error.
For ex : o instanceof String, if you write like below, it won't compile
public boolean isIns(Object o, String str) {
return o instanceof str; //err, o instance of String is correct way to check.
}
And I slightly changed your method signature to match the statement.

You should use the dinamic equivalent of instanceof from Class class.
http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#isInstance(java.lang.Object)
public void isIns(Object o, Class t) {
t.isInstance(o);
}
Check for nulls if needed.

In your code below, t should be the name of a Java class (e.g. String). In your code, you've passed a variable name which is not appropriate:
public void isIns(Object o, Class t) {
o instanceof t;
}
Since an instanceof check is a one-liner, I'm not sure why you are wrapping it in a method. But if you insist on doing so, perhaps this is what you want:
public static boolean isIns(Object o, Class<?> t) {
return c.isInstance(o);
}
But two notes:
Lots of instanceof checks generally indicate bad design.
A Java programmer will be much more comfortable seeing instanceof rather than isIns(...).

maybe you want something like this?
public class test2 {
class c {
}
public test2() {
c obj = new c();
System.out.println(isIns(obj));
}
public boolean isIns(Object o) {
return (o instanceof c);
}
public static void main(String argv[]) {
new test2();
}
}
EDIT: Removed senceless Class parameters.

Related

Why getting compilation error while calling overloaded method and deciding argument type using if-else as parameter

I am trying to call the overloaded method using if-else statement to decide which type of argument to pass so that appropriate method can be invoked. I am getting compilation error.
any idea why I am getting compilation error ? If call method separately using if-else check outside , it works fine.
public class A {
}
public class B {
}
public class RuleCheck {
public void check(A a) {
}
public void check(B b) {
}
}
public class Test {
public static void main(String[] args) {
A a = new A();
B b = new B();
testRule(a);
testRule(b);
}
private static void testRule(Object o) {
RuleCheck ruleCheck = new RuleCheck();
ruleCheck.check(o instanceof A ? (A) o : (B) o);//Compilation problem here : Cannot resolve method 'check(java.lang.Object)'
//Following code works fine
if (o instanceof A)
ruleCheck.check((A) o);
else if (o instanceof B)
ruleCheck.check((B) o);
}
}

Is there a way to know if a method return type is a List<Integer>? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
Let's say I have a class,
public class Dummy {
public List<Integer> foo() {...}
public Abc<Integer> bar() {...}
}
For method foo, I can check the return type using ParameterizedType, but for method bar, is there a way to know if Ab<Integer> is actually a List<Integer>?
Edit to add some background:
We have dozens of 3rd party POJO classes, and we need to extract the field information of these classes, and create a schema based on it.
For the regular primitive fields, it's straight forward, but in those classes, they also have field with type like List<Integer>, or ArrayList<Integer>, or Abc<Integer> (Abc<T> may or may not implements List<T>).
So we need a way to determine if it's a repeated field or not, if it's a repeated one, what is the type argument, is it an Integer or some other things?
You can use Class.isAssignableFrom to determine whether a particular class IS-A another class, and you can look at the type arguments given to the return type:
public class App {
static class AbcWhichIsAList<E> extends ArrayList<E> {
}
static class AbcWhichIsNotAList<E> {
}
public List<Integer> foo() { return null; }
public AbcWhichIsAList<Integer> bar() { return null; }
public AbcWhichIsNotAList<Integer> baz() { return null; }
public AbcWhichIsAList<String> xyzzy() { return null; }
public static boolean returnsList(Class clazz, String methodName) throws NoSuchMethodException {
Method m = clazz.getMethod(methodName);
return List.class.isAssignableFrom(m.getReturnType());
}
public static boolean returnsIntegerList(Class clazz, String methodName) throws NoSuchMethodException {
Method m = clazz.getMethod(methodName);
Type returnType = m.getGenericReturnType();
if (returnType instanceof ParameterizedType parameterisedReturnType) {
return List.class.isAssignableFrom(m.getReturnType()) &&
parameterisedReturnType.getActualTypeArguments()[0].getTypeName().equals(Integer.class.getTypeName());
} else {
return false;
}
}
public static void main(String[] args) throws NoSuchMethodException {
for (String s: Arrays.asList("foo", "bar", "baz", "xyzzy") ){
System.out.println(s + ": " + returnsIntegerList(App.class, s));
}
}
}
The above code assumes that the methods of interest take no parameters.
I feel that there should be a better way of comparing the type parameters than comparing the names of the types.
It's possible to handle more complicated cases. I don't have time to write a full solution, but the code below does half the job: It traverses the inheritance hierarchy until it finds List. However it does not keep track of the actual type parameters on the way.
package org.example;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class App {
static class AbcWhichIsAList<E> extends ArrayList<E> {}
static class AList extends AbcWhichIsAList<Integer> {}
static class AbcWhichIsNotAList<E> {}
public List<Integer> foo() { return null; }
public AbcWhichIsAList<Integer> bar() { return null; }
public AbcWhichIsNotAList<Integer> baz() { return null; }
public AbcWhichIsAList<String> xyzzy() { return null; }
public AList blech() { return null; }
public static boolean returnsIntegerList(Class clazz, String methodName) throws NoSuchMethodException {
Method m = clazz.getMethod(methodName);
Type returnType = findListType(m.getGenericReturnType());
if (returnType != null && returnType instanceof ParameterizedType parameterisedReturnType) {
return List.class.isAssignableFrom(m.getReturnType()) &&
parameterisedReturnType.getActualTypeArguments()[0].getTypeName().equals(Integer.class.getTypeName());
} else {
return false;
}
}
private static Type findListType(Type type) {
if (type.getTypeName().startsWith("java.util.List")) {
return type;
}
Type listType = null;
if (type instanceof ParameterizedType parameterizedType) {
listType = findListType(parameterizedType.getRawType());
}
if (type instanceof Class clazz) {
if (clazz.getGenericSuperclass() != null) {
listType = findListType(clazz.getGenericSuperclass());
}
if (listType == null) {
for (Type t : clazz.getGenericInterfaces()) {
listType = findListType(t);
if (listType != null)
break;
}
}
}
return listType;
}
public static void main(String[] args) throws NoSuchMethodException {
for (String s: Arrays.asList("foo", "bar", "baz", "xyzzy", "blech") ){
System.out.println(s + ": " + returnsIntegerList(App.class, s));
}
}
}
Read about the object.instanceof(someType) method, it might be what you are looking for.
The java instanceof operator is used to test whether the object is an instance of the specified type (class or subclass or interface).
If not - the typeof method is worth trying as well.

How to use Java generics method?

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.

Execute a specific parametrized class method

I have this (simplified) java interface
public interface MyInterface<T> {
public String run( T arg );
}
and some classes that implement that interface, i.e.
public final class SomeImplementation1 implements MyInterface<String> {
#Override
public String run( String arg) {
// do something with arg and return a string
}
}
and
public final class SomeImplementation2 implements MyInterface<CustomClass> {
#Override
public String run( CustomClass arg) {
// do something with arg and return a string
}
}
Now, I have a global resource manager for all of those implementations, which instantiates all of them in a List for latter usage. What I would like to achieve is something like this, which obviously gives me an error
public final class MyInterfaceManager {
private List<MyInterface<?>> elements = new List<MyInterface<?>>();
public MyInterfaceManager() {
elements.put( new SomeImplementation1() );
elements.put( new SomeImplementation2() );
// more implementations added
}
// this is what I would like to achieve
public <T> void run( T arg ) {
for( MyInterface<?> element: elements ) {
String res = element.run( arg ); // ERROR
}
}
}
because "arg cannot be converted to capture#1 of ? by method invocation conversion".
A possible solution could be to perform an instanceof test inside the loop, and cast the element to its real type, along with the argument as well, like that
public <T> void run( T arg ) {
for( MyInterface<T> element: elements ) {
if (element instanceof SomeImplementation2) {
String res = ((SomeImplementation2)element).run( (CustomClass)arg );
} else if // other tests here ...
}
}
But i don't like it, it's not elegant at all, and it forces me to do lots of instanceof and casts.
So, I'm wondering if there is a better way to achieve this.
Thanks for your help :)
You are running into type erasure. You need to add another method to the interface that returns the Class instance that relates to the type parameter <T>, this will allow you to do runtime checks on that Class.
I would accomplish this thus:
public interface MyInterface<T> {
String run( T arg );
Class<T> type();
}
So the interface returns its type. N.B. all interface members are public by default - no need for the extra public.
public final class SomeImplementation1 implements MyInterface<String> {
#Override
public String run(final String arg) {
return arg;
}
#Override
public Class<String> type() {
return String.class;
}
}
#SuppressWarnings({"unchecked"})
public static <T> String run(final T arg) {
for (final MyInterface<?> element : elements) {
if (element.type().isAssignableFrom(arg.getClass())) {
return ((MyInterface<T>) element).run(arg);
}
}
throw new IllegalArgumentException("No element found.");
}
The logic is that for each MyInterface you check whether the argument provided is safely castable to that MyInterface's type(). If it is then you can cast the whole MyInterface to the arg's type. This is unchecked as the compiler cannot verify this as compile time, but as you are manually doing a check this warning can be ignored.
public static void main(String[] args) throws Exception {
elements = new LinkedList<>();
elements.add(new SomeImplementation1());
System.out.println(run("test"));
System.out.println(run(1));
}
Output:
test
Exception in thread "main" java.lang.IllegalArgumentException: No element found.
at com.XXX.App.run(App.java:33)
at com.XXX.App.main(App.java:55)
As expected.

Java enums in generic type

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);
}
}

Categories

Resources