Java using supertype of several enums - java

I want to be able to use a supertype over different enums, the code consists of three parts:
Manager.search:
public final List<B> search(final Order order, final Field field, final AbstractConstraint... c) throws SearchException {
if (c.length == 0) {
throw new IllegalArgumentException("orm.Manager.search: c.length == 0");
}
try {
List<B> beans = new ArrayList<>();
for (AbstractConstraint constraint : c) {
try (PreparedStatement ps = new QueryBuilder(connection, tableName(), getPaths(), searchQuery()).add(constraint).order(order, field).build();ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
beans.add(createBean(rs));
}
}
}
return beans;
} catch (SQLException ex) {
Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex);
throw new SearchException(ex);
}
}
The order and field variables are most important here.
The auto-generated TemplateAttributeField.java:
public enum TemplateAttributeField implements Field {
templateId,
attributeOrder,
attributeName,
x1,
x2;
}
And the calling code:
try (TemplateAttributeManager templateAttributeManager = ManagerFactory.getTemplateAttributeManager()) {
List<TemplateAttributeBean> templateAttributes = null;
try {
templateAttributes = templateAttributeManager.search(Order.ASCENDING, TemplateAttributeField.attributeOrder, new TemplateAttributeConstraint.Builder().templateId(template.getTemplateId()).build());
} catch (SearchException ex) {
Logger.getLogger(OutputProcessor.class.getName()).log(Level.SEVERE, null, ex);
}
for (Word word : words) {
}
}
However at templateAttributes = ... I get the following exception/error:
no suitable method found for search(Order,TemplateAttributeField,TemplateAttributeConstraint)
method Manager.search(Order,Field,AbstractConstraint...) is not applicable
(actual argument TemplateAttributeField cannot be converted to Field by method invocation conversion)
And the Field class is on more than an interface which does not prevent extra functionality.
Am I missing something here, or how should I fix it?

I've tried to create a minimal working example, but it seems to work for me. Could you try if this works for you and is the same as you require?
public class Test {
static interface I {}
static enum E implements I {A}
static void m(I i) {}
public static void main(String[] args) {
m(E.A);
}
}
Also ensure that you implement the same Field interface in your enum as you require in your method. Maybe there's a name clash and you're using interfaces from different packages.

Related

Use Class parameter for generic type (e.g ArrayList)

I am trying to create a generic method to handle different types of ArrayLists in Java. The types are quite different, but all contain one identical parameter, which I want to evaluate in this method.
But I cannot create proper ArrayList<type> with given class information.
What am I doing wrong?
private String test(ArrayList<?> list, Class<?> type) {
for(type i : list){ // for (type i : (ArrayList<type>) list){
// do something
}
return "xxx"
}
private void init() {
ArrayList<Type_1> a1 = new ArrayList<>();
ArrayList<Type_2> a2 = new ArrayList<>();
String s1 = test(a1, Type_1.class);
String s2 = test(a2, Type_2.class);
}
Update
Found a solution
private String test(ArrayList<?> list) {
for (Object i : list){
try {
Method m = i.getClass().getMethod("getName", null);
System.out.println(m.invoke(i));
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
//Handle Exception
}
}
}
I created a mixed answer relating to both solutions:
Implementing Interfaces
The first is done with a simple interface MyType that defines the contract method(s) for the classes Type_1 and Type_2. This is the clean and proper Java way. This way the compiler will already tell you if you can do certain operations or not. This also shows beginners problems with their concept of implementing ideas.
The downside is that all classes have to implement that interface (which may be defined anywhere along their inheritance hierarchy).
But Java is all about the advantage of type safety and compiler warnings. So this is clearly the preferred way.
Using Reflection
Using Reflection for this task is possible, yes. But not necessarily a good idea. With reflection, there are multiple problems:
You will get runtime errors or have to handle those exceptions
The project will start, but if your design, your concept, is flawed, this will be a lot harder to pinpoint
lots of libraries cannot handle reflections well (Aspect Oriented Programming, Application Containers, special Compilers like the GraalVM NativeImage, etc etc)
Using reflection will be slower and consume more memory
So if it's possible and easy to stay away from Reflection, you should steer clear. Especially if this has such a simple proper solution to it.
(I also cleaned up your code with the reflection, there were some minor inconsistencies in there that wouldn't let it compile)
Code:
package stackoverflow;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class SimpleInterfacing {
interface MyType {
String getName();
}
static class Type_1 implements MyType {
#Override public String getName() {
return "This is type 1";
}
}
static class Type_2 implements MyType {
#Override public String getName() {
return "This is type 2";
}
}
private String test(final ArrayList<? extends MyType> list) {
String returnValue = null;
for (final MyType t : list) {
// do something
System.out.println("Got name: " + t.getName());
returnValue = t.getName();
}
return returnValue; // returns last value, null is lists are empty
}
private void init() {
final ArrayList<Type_1> a1 = new ArrayList<>();
a1.add(new Type_1());
final ArrayList<Type_2> a2 = new ArrayList<>();
a2.add(new Type_2());
{
final String s1 = test(a1);
System.out.println("s1 is " + s1);
}
{
final String s2 = test(a2);
System.out.println("s2 is " + s2);
}
{
test_reflection(a1);
test_reflection(a2);
}
}
public static void main(final String[] args) {
new SimpleInterfacing().init();
}
private String test_reflection(final ArrayList<?> list) {
for (final Object i : list) {
try {
final Method m = i.getClass().getMethod("getName");
System.out.println("Invoked: " + m.invoke(i));
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
//Handle Exception
ex.printStackTrace();
}
}
return null;
}
}
You need to declare an explicit type parameter:
private <T> String test(ArrayList<T> list, Class<T> type) {
for (T i : list) {
// do something with 'i'
}
return "xxx"
}
If you don't need Class<T> argument, you can leave it out; e.g.
private <T> String test(ArrayList<T> list) {
for (T i : list) {
// do something
}
return "xxx"
}
You would normally only need to pass a Class<T> type object if you intended to create instances of that class ... or an array of that class.
The commented out version of your code would not compile because it is mixing compile-time and runtime types. In
for (type i : (ArrayList<type>) list) {
the compiler would need to know what type was represented by type at compile time. But it is a runtime variable. But that is invalid even before that because the Java syntax requires the identifier for a type at that point ... not the identifier for a variable.

Mockito: Attach Answer to every method of arbitrary Object instance

I have the following situation:
I want to attach an Answer to every method call of a specific class instance. So for example with the class
public class Example {
public int example1() { /* */ }
public int example2(Object a) { /* */ }
public int example3(Object a, Integer b) { /* */ }
public int example4(int a) { /* */ }
}
I want to do the following
public Example attachToExample(Example ex) {
Example spy = Mockito.spy(ex);
Answer<Object> answer = /* */;
doAnswer(answer).when(spy).example1();
doAnswer(answer).when(spy).example2(any());
doAnswer(answer).when(spy).example3(any(), any());
doAnswer(answer).when(spy).example4(anyInt());
return spy;
}
This works but what I would like to do is generalize this to not just Example instances but arbitrary Objects.
So what I would like to do is
public Object attachToExample(Object o) {
Object spy = Mockito.spy(o);
Answer<Object> answer = /* */;
for(Method m : o.getClass().getMethods()) {
/* skipping methods that cannot be mocked (equals/hashCode/final/..) */
doAnswer(answer).when(spy)./* Method m with according arguments */;
}
return spy;
}
What I would need to do for that is construct argument matchers any/anyInt/.. depending on the amount of parameters of each method and their types (primitive/non primitive). Ideally I would create a list of arguments like this:
Class<?>[] params = m.getParameterTypes();
ArrayList<Object> args = new ArrayList<>();
for (Class<?> param : params) {
if ("int".equals(param.toString())) {
args.add(ArgumentMatchers.anyInt());
} else { // Cases for other primitive types left out.
args.add(ArgumentMatchers.any()); // Found non primitive. We can use 'any()'
}
}
try {
doAnswer(answer).when(spy).getClass().getMethod(m.getName(), m.getParameterTypes())
.invoke(spy, args.toArray());
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
This does not work as using argument matchers outside of stubbing is not supported but I hope that this makes clear what I want to do.
Is there any way to make this work or is there a different way of archiving what I want to do?
Okay, I have found a way to do what I want:
While the array of arguments cannot be constructed before the invoke call we can do so with an external method call like so:
try {
doAnswer(answer).when(spy).getClass().getMethod(m.getName(), m.getParameterTypes())
.invoke(spy, constructArguments(m));
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
where constructArguments is the following:
private static Object[] getArgumentMatcher(Method m) {
Class<?>[] types = m.getParameterTypes();
Object[] res = new Object[types.length];
for(int i = 0; i < types.length; ++i) {
if (types[i].isPrimitive()) {
// For primitives we need to specify the type explicitly ¯\_(ツ)_/¯
res[i] = any(types[i]);
} else {
res[i] = any();
}
}
return res;
}

Avoiding code duplication when checking for default responses

I have a Java program that calls an external API (RealApi in the code below) and sometimes I want to avoid calling this API and instead return pre-constructed responses (generated by FakeApi).
So, I ended up duplicating this kind of construct in most of my methods:
public Type1 m1(String s) {
try {
Type1 r = FakeApi.m1(s);
if (r != null) {
return r;
}
} catch (Exception e) {
// log error
}
return RealApi.m1(s);
}
What are some options to avoid duplicating this try/catch block everywhere? It's important that if FakeApi throws an exception or returns null, the RealApi must be called.
One option would be encapsulate the error checking behaviour into its own method:
public <T> T fakeOrReal(Supplier<T> fake, Supplier<T> real) {
try {
T r = fake.get();
if (r != null) {
return r;
}
}
catch (Exception e) {
// log error
}
return real.get();
}
You can then just call it with
public Type1 m1(String s) {
return fakeOrReal(() -> FakeApi.m1(s), () -> RealApi.m1(s));
}
This is not as simple as Thomas Preißler's answer but it will help you not repeat any method at all. So if you expand the interface, you have to modify only the concrete classes and not the linker which describes the actual behavior you want.
Create an interface that contains all the methods of RealApi:
interface Api {
Type1 m1(String s);
}
Then a class that does the actual call:
class ConcreteApi implements Api {
public Type1 m1(String s) {
return RealApi.m1(s);
}
}
Then create your FakeApi:
class TotallyFakeApi implements Api {
public Type1 m1(String s) {
return FakeApi.m1(s);
}
}
Now, the tricky part to avoid repeating yourself:
private static Object callImplementation(Api api, Method method, Object[] methodArgs) throws Exception {
Method actualMethod = api.getClass().getMethod(actualMethod.getName(), actualMethod.getParameterTypes());
return actualMethod.invoke(api, methodArgs);
}
Api fakeOrReal(Api fakeApi, Api realApi) {
return (Api) Proxy.newProxyInstance(
FakeApi.class.getClassLoader(),
new Class[]{Api.class},
(proxy, method, methodArgs) -> {
try {
Object r = callImplementation(fakeApi, method, methodArgs);
if (r != null) {
return r;
}
} catch (Exception e) {
// logError(e);
}
return callImplementation(realApi, method, methodArgs);
}
);
}
Get the actual implementation like this:
Api apiToUse = fakeOrReal(new TotallyFakeApi(), new ConcreteApi());

Getting method regardless of parameters

I am trying to get method regardless of what parameters that method takes (as of now there is no method overloading and there wouldn't be in future). The only possible solution that i could come up with was
private Method getMethod(Class<?> clas, String methodName) {
try {
Method[] methods = clas.getMethods();
for (Method method : methods) {
if (method.getName().equalsIgnoreCase(methodName)) {
return method;
}
}
} catch (SecurityException e) {
e.printStackTrace();
}
return null;
}
What i want to ask that is there a way to fetch a method regardless of its parameters ? I was looking at clas.getMethod ("methodName", parameters) and if i provide null in there it will try to fetch a method which has no parameters. Which wouldn't be no case.
Any ideas ?
EDIT
Thanks guys for input. In my case, i know that there would be only one method regardless of its case. The reason i am using ignoreCase is because the input will be coming from a developer (in other team) and he will be providing the name as a hard-coded string. So to keep things from spilling out of our hands, I am using a safe approach.
No. The way you've done it is the way to go. A method is identified by its signature and the signature includes the name and the parameter types.
Here is a solution that retrieves all methods with the specified class and method name regardless of the method's parameters:
public class Test
{
private class Foo
{
public void bar()
{
}
public void bar(String s)
{
}
public void goo()
{
}
}
private static Method[] getMethods(Class<?> clazz, String methodName)
{
List<Method> methods = new ArrayList<Method>();
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod: declaredMethods)
{
if (declaredMethod.getName().equals(methodName))
{
methods.add(declaredMethod);
}
}
return methods.toArray(new Method[methods.size()]);
}
public static void main(String[] args)
{
Method[] methods = getMethods(Foo.class, "bar");
System.out.println(Arrays.toString(methods));
}
}
This generates the following output:
[public void com.example.Test$Foo.bar(java.lang.String), public void com.example.Test$Foo.bar()]
You've done just fine. This is basically the same as the solution to a similar problem I dealt with four years ago, creating a means to create callback methods in Java. The constructors for my Callback class were:
public Callback(Class<?> clazz, String methodName, Object parentObj) {
// Find a method with the matching name
Method[] allMethods;
try { allMethods = clazz.getMethods(); }
catch(SecurityException se) { allMethods = new Method[0]; }
int count = 0;
Method single = null;
for(Method m : allMethods) {
if(m.getName().equals(methodName)) {
single = m;
count++;
}
// Can't have more than one instance
if(count > 1)
throw new IllegalArgumentException(clazz.getName()
+ " has more than one method named " + methodName);
}
if(count == 0) // No instances found
throw new IllegalArgumentException(clazz.getName()
+ " has no method named " + methodName);
this.parentObj = parentObj;
this.method = single;
this.parameters = single.getParameterTypes();
}
public Callback(
Class<?> clazz,
String methodName,
Object parentObj,
Class<?>...parameters)
{
try { this.method = clazz.getMethod(methodName, parameters); }
catch(NoSuchMethodException nsme) { nsme.printStackTrace(); }
catch(SecurityException se) { se.printStackTrace(); }
this.parentObj = parentObj;
this.parameters = parameters;
}
My Callback class isn't really useful any more in the era of Java 8, but at the time the only real means for a "callback" in java was anonymous interface implementations, which wasn't sufficient for my use-case.
As you can see in the first constructor, it throws an exception if it finds multiple methods with the same name.
Using java streams there is a really short method of finding a method, the first match, by its name only:
Stream.of(type.getMethods())
.filter((m) -> m.getName().equals(searchedName))
.findFirst()
.get();
I think this is a short and readable possibility in this case.

How do I pass a class as a parameter in Java?

Is there any way to pass class as a parameter in Java and fire some methods from that class?
void main()
{
callClass(that.class)
}
void callClass(???? classObject)
{
classObject.somefunction
// or
new classObject()
//something like that ?
}
I am using Google Web Toolkit and it does not support reflection.
public void foo(Class c){
try {
Object ob = c.newInstance();
} catch (InstantiationException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
}
}
Here are some good examples on Reflection API
How to invoke method using reflection
import java.lang.reflect.*;
public class method2 {
public int add(int a, int b)
{
return a + b;
}
public static void main(String args[])
{
try {
Class cls = Class.forName("method2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Method meth = cls.getMethod(
"add", partypes);
method2 methobj = new method2();
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj
= meth.invoke(methobj, arglist);
Integer retval = (Integer)retobj;
System.out.println(retval.intValue());
}
catch (Throwable e) {
System.err.println(e);
}
}
}
Also See
Java Reflection
public void callingMethod(Class neededClass) {
//Cast the class to the class you need
//and call your method in the class
((ClassBeingCalled)neededClass).methodOfClass();
}
To call the method, you call it this way:
callingMethod(ClassBeingCalled.class);
Construct your method to accept it-
public <T> void printClassNameAndCreateList(Class<T> className){
//example access 1
System.out.print(className.getName());
//example access 2
ArrayList<T> list = new ArrayList<T>();
//note that if you create a list this way, you will have to cast input
list.add((T)nameOfObject);
}
Call the method-
printClassNameAndCreateList(SomeClass.class);
You can also restrict the type of class, for example, this is one of the methods from a library I made-
protected Class postExceptionActivityIn;
protected <T extends PostExceptionActivity> void setPostExceptionActivityIn(Class <T> postExceptionActivityIn) {
this.postExceptionActivityIn = postExceptionActivityIn;
}
For more information, search Reflection and Generics.
Use
void callClass(Class classObject)
{
//do something with class
}
A Class is also a Java object, so you can refer to it by using its type.
Read more about it from official documentation.
This kind of thing is not easy. Here is a method that calls a static method:
public static Object callStaticMethod(
// class that contains the static method
final Class<?> clazz,
// method name
final String methodName,
// optional method parameters
final Object... parameters) throws Exception{
for(final Method method : clazz.getMethods()){
if(method.getName().equals(methodName)){
final Class<?>[] paramTypes = method.getParameterTypes();
if(parameters.length != paramTypes.length){
continue;
}
boolean compatible = true;
for(int i = 0; i < paramTypes.length; i++){
final Class<?> paramType = paramTypes[i];
final Object param = parameters[i];
if(param != null && !paramType.isInstance(param)){
compatible = false;
break;
}
}
if(compatible){
return method.invoke(/* static invocation */null,
parameters);
}
}
}
throw new NoSuchMethodException(methodName);
}
Update:
Wait, I just saw the gwt tag on the question. You can't use reflection in GWT
Adding <T> T as return type worked for me. Ex with json deserialize
public static <T> T fromJson(String json, Class<T> classOfT){
return gson().fromJson(json, classOfT);
}
I am not sure what you are trying to accomplish, but you may want to consider that passing a class may not be what you really need to be doing. In many cases, dealing with Class like this is easily encapsulated within a factory pattern of some type and the use of that is done through an interface. here's one of dozens of articles on that pattern: http://today.java.net/pub/a/today/2005/03/09/factory.html
using a class within a factory can be accomplished in a variety of ways, most notably by having a config file that contains the name of the class that implements the required interface. Then the factory can find that class from within the class path and construct it as an object of the specified interface.
As you said GWT does not support reflection. You should use deferred binding instead of reflection, or third party library such as gwt-ent for reflection suppport at gwt layer.
Se these:
http://download.oracle.com/javase/tutorial/extra/generics/methods.html
here is the explaniation for the template methods.
Have a look at the reflection tutorial and reflection API of Java:
https://community.oracle.com/docs/DOC-983192enter link description here
and
http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html
Class as paramater. Example.
Three classes:
class TestCar {
private int UnlockCode = 111;
protected boolean hasAirCondition = true;
String brand = "Ford";
public String licensePlate = "Arizona 111";
}
--
class Terminal {
public void hackCar(TestCar car) {
System.out.println(car.hasAirCondition);
System.out.println(car.licensePlate);
System.out.println(car.brand);
}
}
--
class Story {
public static void main(String args[]) {
TestCar testCar = new TestCar();
Terminal terminal = new Terminal();
terminal.hackCar(testCar);
}
}
In class Terminal method hackCar() take class TestCar as parameter.

Categories