I'm trying to create a Handler interface, which is able to handle different types of events based on their types. I'm having trouble with the following warning:
Unchecked call to 'handle(T)' as a member of raw type 'Handler'
Here are my classes.
public interface Handler<T> {
void handle(T event); }
public class IntegerHandler implements Handler<Integer> {
#Override
public void handle(Integer event) {
System.out.println("Integer: " + event);
}
}
public class ObjectHandler implements Handler<Object> {
#Override
public void handle(Object event) {
System.out.println("Object: " + event);
}
}
public class StringHandler implements Handler<String> {
#Override
public void handle(String event) {
System.out.println("String: " + event);
}
}
public class TestHandlers {
public static void main(String[] args) {
String a = "hello";
Integer b = 12;
Long c = 23L;
dispatch(a).handle(a);
dispatch(b).handle(b);
dispatch(c).handle(c);
}
private static Handler dispatch(Object o) {
if (o instanceof String) {
return new StringHandler();
} else if (o instanceof Integer) {
return new IntegerHandler();
} else {
return new ObjectHandler();
}
}
}
The output looks correct:
String: hello
Integer: 12
Object: 23
I guess the problem is that my dispatch method is returning a unchecked version of Handler.
Not sure what the proper way is to do this right.
Create a factory (credit to Generic Factory With Unknown Implementation Classes)
public class HandlerFactory<H extends Handler> {
final Class<H> handlerClass;
protected HandlerFactory(final Class<H> clazz) {
handlerClass = clazz;
}
protected H create() throws InstantiationException, IllegalAccessException {
H handler = handlerClass.newInstance();
return handler;
}
public static <H extends Handler> HandlerFactory<H> createFactory(final Class<H> clazz) throws InstantiationException, IllegalAccessException {
return new HandlerFactory(clazz);
}
public static Handler dispatch(Object obj) throws InstantiationException, IllegalAccessException {
Class c;
if (obj instanceof String) {
c = StringHandler.class;
} else if (obj instanceof Integer) {
c = IntegerHandler.class;
} else {
c = ObjectHandler.class;
}
HandlerFactory factory = HandlerFactory.createFactory(c);
return factory.create();
}
}
Exception handlers not shown:
...
String a = "hello";
Integer b = 12;
Long c = 23L;
HandlerFactory.dispatch(a).handle(a);
HandlerFactory.dispatch(b).handle(b);
HandlerFactory.dispatch(c).handle(c);
Related
New to this topic and right now I'm stuck at a brick wall. I have 2 classes, parent class: Controller.java and subclass: GreenhouseControls.java. I need to serialize a GreenhouseControls object but also an instance variable (eventList) from its superclass Controller.java.
My serialization happens when an inner class of GreenhouseControls.java throws a custom ControllerException, which is caught in the main method. Before terminating the program, the GreenhouseControls object should be saved (including the field from its superclass).
Why is a NotSerializableException thrown by the inner class WindowMalfunction of GreenhouseControls? Anyone have any ideas, as I am seriously stuck?
What I tried is the following:
Implement serializable on Controller.java. This is because if the superclass is serializable, then subclass is automatically serializable, however this throws java.io.NotSerializableException: GreenhouseControls$WindowMalfunction, (WindowMalfunction is the inner class that throws the initial exception to begin the serialization processs).
Implement serializable on GreenhouseControls.java and implement custom serialization by overriding writeObject() and readObject() to save the field from the superclass. This approach yet again throws the same exception as the approach 1.
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(super.eventList);
}
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
Object obj = in.readObject();
List<Event> x = cast(obj);
super.eventList = x;
}
Controller.java
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
public class Controller {
// THIS IS THE VARIABLE I NEED TO SAVE
protected List<Event> eventList = new ArrayList<Event>();
public void addEvent(Event c) {
eventList.add(c);
}
public void run() throws ControllerException {
while (eventList.size() > 0)
// Make a copy so you're not modifying the list
// while you're selecting the elements in it:
for (Event e : new ArrayList<Event>(eventList))
if (e.ready()) {
System.out.println(e);
e.action();
eventList.remove(e);
}
}
public static void shutDown() { }
}
GreenhouseControls.java class (note I have removed the inner classes and other code from it and only left related info)
public class GreenhouseControls extends Controller implements Serializable {
private int errorcode = 0;
public class WindowMalfunction extends Event {
public WindowMalfunction(long delayTime) {
super(delayTime);
}
public void action() throws ControllerException {
windowok = false;
throw new ControllerException("Window malfunction");
}
public String toString() {
return "Window malfunction";
}
}
public class PowerOut extends Event {
public PowerOut(long delayTime) {
super(delayTime);
}
public void action() throws ControllerException {
poweron = false;
throw new ControllerException("Power out");
}
public String toString() {
return "Power out";
}
}
// Various other inner classes that extend event exist
public static void serializeObject(GreenhouseControls gc) {
FileOutputStream fileOut;
ObjectOutputStream out;
try {
fileOut = new FileOutputStream("dump.out");
out = new ObjectOutputStream(fileOut);
out.writeObject(gc);
System.out.println("WERRROR code: " + gc.getError());
out.close();
fileOut.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(super.eventList);
}
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
Object obj = in.readObject();
List<Event> x = cast(obj);
super.eventList = x;
}
#SuppressWarnings("unchecked")
public static <T extends List<?>> T cast(Object obj) {
return (T) obj;
}
public int getError() {
return errorcode;
}
public Fixable getFixable(int errorcode) {
switch (errorcode) {
case 1:
return new FixWindow();
case 2:
return new PowerOn();
default:
return null;
}
}
public static void main(String[] args) {
GreenhouseControls gc = null;
try {
String option = args[0];
String filename = args[1];
if (!(option.equals("-f")) && !(option.equals("-d"))) {
System.out.println("Invalid option");
printUsage();
}
// gc = new GreenhouseControls();
if (option.equals("-f")) {
gc = new GreenhouseControls();
gc.addEvent(gc.new Restart(0, filename));
}
gc.run();
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Invalid number of parameters");
printUsage();
} catch (ControllerException e) {
String errormsg;
if (e.getMessage().equals("Window malfunction")) {
gc.errorcode = 1;
errormsg = "Window malfunction event occurred Error code: " + gc.errorcode;
} else {
gc.errorcode = 2;
errormsg = "Power out event occurred Error code: " + gc.errorcode;
}
logError(errormsg);
serializeObject(gc);
gc.displayEventList();
shutDown();
}
}
}
Event.java
public abstract class Event {
private long eventTime;
protected final long delayTime;
public Event(long delayTime) {
this.delayTime = delayTime;
start();
}
public void start() { // Allows restarting
eventTime = System.currentTimeMillis() + delayTime;
}
public boolean ready() {
return System.currentTimeMillis() >= eventTime;
}
public abstract void action() throws ControllerException;
Event has to be Serializable too.
Change
public abstract class Event {
to
public abstract class Event implements Serializable {
I am trying to write a method that can take in a String classname and a String value, and return the value represented as that String.
Example inputs:
parse("java.lang.String", "abc") -> String "ABC"
parse("java.lang.Boolean", "FALSE") -> Boolean FALSE
parse("java.lang.Integer", "123") -> Integer 123
parse("com.me.Color", "RED") -> enum Color.RED
I have found that if I use an if block containing assignableFrom calls, I can achieve this. But would prefer writing something more extendable, so it isn't as difficult to add a new parser tomorrow.
This is what I have now:
String stringClassName = //stringified full class name
String value = //value to parse
Class<?> fieldType = Class.forName(stringClassName)
if (fieldType.isAssignableFrom(String.class)) {
return value;
} else if (fieldType.isAssignableFrom(Boolean.class)) {
return Util.toBoolean(value);
} else if (fieldType.isEnum()) {
return Util.toEnum(fieldType, value);
} else {
// throw exception
}
There are multiple ways to do this. For example:
You could have an interface called Parser
package example;
public interface Parser {
boolean canParse(String fullQualifiedClassName);
Object parse(String fullQualifiedClassName, String value) throws ParseException;
class ParseException extends Exception {
public ParseException(String msg) {
super(msg);
}
public ParseException(Exception cause) {
super(cause);
}
}
}
And all your Default-Implementations in an Enum or statically defined in another way:
package example;
public enum DefaultParser implements Parser {
STRING {
#Override
public boolean canParse(String fullQualifiedClassName) {
return isClassAssignableFromClassName(fullQualifiedClassName, String.class);
}
#Override
public Object parse(String fullQualifiedClassName, String value) throws ParseException {
return value;
}
},
ENUM {
#Override
public boolean canParse(String fullQualifiedClassName) {
return isClassAssignableFromClassName(fullQualifiedClassName, Enum.class);
}
#Override
public Object parse(String fullQualifiedClassName, String value) throws ParseException {
final Class<? extends Enum> clazz;
try {
clazz = (Class<? extends Enum>) Class.forName(fullQualifiedClassName);
} catch (ClassNotFoundException e) {
throw new ParseException(e);
}
return Enum.valueOf(clazz, value);
}
},
BOOLEAN {
#Override
public boolean canParse(String fullQualifiedClassName) {
return isClassAssignableFromClassName(fullQualifiedClassName, Boolean.class);
}
#Override
public Object parse(String fullQualifiedClassName, String value) throws ParseException {
return value.toLowerCase().equals("true");
}
};
private static boolean isClassAssignableFromClassName(String fullQualifiedClassName, Class<?> clazz) {
try {
return clazz.isAssignableFrom(Class.forName(fullQualifiedClassName));
} catch (ClassNotFoundException e) {
return false;
}
}
}
And a ParentParser Implementation that combines multiple Parsers into one:
package example;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class ParentParser implements Parser {
private final List<Parser> parsers;
public ParentParser() {
this.parsers = new ArrayList<>();
this.parsers.addAll(Arrays.asList(DefaultParser.values()));
}
public void register(Parser parser) {
this.parsers.add(parser);
}
#Override
public boolean canParse(String fullQualifiedClassName) {
return findParser(fullQualifiedClassName).isPresent();
}
#Override
public Object parse(String fullQualifiedClassName, String value) throws ParseException {
return findParser(fullQualifiedClassName)
.orElseThrow(() -> new ParseException("no registered parser found for class=" + fullQualifiedClassName))
.parse(fullQualifiedClassName, value);
}
private Optional<Parser> findParser(String fullQualifiedClassName) {
return this.parsers.stream().filter(parser -> parser.canParse(fullQualifiedClassName)).findAny();
}
}
Which you can then use like this:
package example;
import example.Parser.ParseException;
public class Example {
public static void main(String[] args) throws ParseException {
final ParentParser parser = new ParentParser();
System.out.println(parser.parse("java.lang.String", "hello world"));
System.out.println(parser.parse("java.lang.Boolean", "true"));
System.out.println(parser.parse("java.time.DayOfWeek", "TUESDAY"));
}
}
And you could add more parsers, for example a parser using Jackson (JSON):
package example;
import com.fasterxml.jackson.databind.ObjectMapper;
import example.Parser.ParseException;
import java.io.IOException;
public class Example {
public static void main(String[] args) throws ParseException {
final ParentParser parser = new ParentParser();
System.out.println(parser.parse("java.lang.String", "hello world"));
System.out.println(parser.parse("java.lang.Boolean", "true"));
System.out.println(parser.parse("java.time.DayOfWeek", "TUESDAY"));
parser.register(new JacksonParser());
System.out.println(parser.parse("java.util.Map", "{\"key\":\"value\"}"));
}
private static class JacksonParser implements Parser {
private static final ObjectMapper MAPPER = new ObjectMapper();
#Override
public boolean canParse(String fullQualifiedClassName) {
final Class<?> clazz;
try {
clazz = Class.forName(fullQualifiedClassName);
} catch (ClassNotFoundException e) {
return false;
}
return MAPPER.canDeserialize(MAPPER.constructType(clazz));
}
#Override
public Object parse(String fullQualifiedClassName, String value) throws ParseException {
try {
return MAPPER.readValue(value, Class.forName(fullQualifiedClassName));
} catch (ClassNotFoundException | IOException e) {
throw new ParseException(e);
}
}
}
}
Note that this can of course be optimized depending on your needs.
If your Parser-Implementations can only parse a static List of Types and there is only one Parser-Implementation per Class, you should change the List<Parser> to Map<Class<?>, Parser> and change the register-Method to register(Class<?> clazz, Parser parser) for example
You can write a generic solution using reflection apis in java.
That would reduce a lot amount of code and would be more extensible.
Also not there is a separate processing required for enum types.
I have covered the basic cases in the code shown below.
public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException {
Object instance1 = parse("java.lang.String", "abc", false);
Object instance2 = parse("java.lang.Boolean", "FALSE", false);
Object instance3 = parse("java.lang.Integer", "123", false);
Object instance4 = parse("com.me.Color", "RED", true);
}
private static Object parse(String className, String argument, boolean isEnum) throws NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
if (isEnum) {
Object value = Enum.valueOf((Class<? extends Enum>) Class.forName(className), argument);
//System.out.println(value);
return value;
} else {
return parse(className, new Object[]{argument}, isEnum);
}
}
private static Object parse(String className, Object[] arguments, boolean isEnum) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> clazz = Class.forName(className);
Constructor<?> ctor = clazz.getConstructor(String.class);
Object object = ctor.newInstance(arguments);
//System.out.println(object);
return object;
}
This is my project structure. I'm trying to use a static factory function to check for an object and then perform some operations. I followed the this process.
Parent Class:
public abstract class Parent {
protected static Child1DTO ch1;
protected static Child2DTO ch2;
public Parent(Child1DTO ch1) {
this.ch1 = ch1;
}
public Parent(Child2DTO ch2) {
this.ch2 = ch2;
}
protected Parent() {
}
public static Child1DTO getCh1() {
return ch1;
}
public static Child2DTO getCh2() {
return ch2;
}
public static Class<?> childType(Object obj) {
if (obj instanceof Child1DTO) {
//do something
return Child1DTO.class;
} else if (obj instanceof Child2DTO) {
//do something
return Child2DTO.class;
}
return null;
}
}
Child1DTO Class:
public class Child1DTO extends Parent {
private String fName1;
private String lName1;
public String getfName1() {
return fName1;
}
public void setfName1(String fName1) {
this.fName1 = fName1;
}
public String getlName1() {
return lName1;
}
public void setlName1(String lName1) {
this.lName1 = lName1;
}
}
Child2DTO Class:
public class Child2DTO extends Parent{
private String fName2;
private String lName2;
public String getfName2() {
return fName2;
}
public void setfName2(String fName2) {
this.fName2 = fName2;
}
public String getlName2() {
return lName2;
}
public void setlName2(String lName2) {
this.lName2 = lName2;
}
}
Child Class:
public class Child extends Parent {
public Child(Child1DTO ch1) {
super(ch1);
}
public Child(Child2DTO ch2) {
super(ch2);
}
public static Child test(Object obj) {
if (obj instanceof Child1DTO) { //is this the correct way to check?
//do something
return new Child((Child1DTO) obj);
} else if (obj instanceof Child2DTO) {//is this the correct way to check?
//do something
return new Child((Child2DTO) obj);
}
return null;
}
public static void main(String args[]) {
if(childType(ch1).equals(ch1)){
//do something
}else if(childType(ch2).equals(ch2)){
//do something
}else{
System.out.println("Failed!");
}
}
}
EDIT:
Parent class has one Child class and two DTOs Child1DTO and Child2DTO.
Do I need to implement conditional check in Parent class or Child class?
How to achieve conditional check with constructors?
I would like to marshall and unmarshall objects whose fields are of their class's inner class (synthetic class if I'm not wrong).
class A {
private B field_b=null;
public static class B {
public static B B1 = new B("b1");
public static B B2 = new B("b2");
private final String name;
private B(String name) {
this.name=name;
}
}
public B getBforName(String name) {
if (B1.name.equals(name) return B1;
else if (B2.name.equals(name) return B2;
else return null;
}
And produce and read from an XML:
<A>
<field_B>b1</field_B>
</A>
The writing part is easy.
The reading part is more complicated.
I would like to write a converter:
public class BConverter implements Converter {
public boolean canConvert(Class type) {
return B.class.isAssignableFrom(type) ;
}
public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
// ...
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
A parent_v1 = (A) context.getCurrentObject(); // !!! always empty
A parent_v2 = (A) context.get("current_unmarshalled_A");
return parent_v2.getBforName((String)reader.getValue());
}
}
The context.getCurrentObject() returns null and seems to be obsolete (from forums I read).
The context.get("current_unmarshalled_A")would require that I put in this unMarshallingContext that key and the A object being unmarshalled. I don't find to do that without writing an AConverter. And that is not neat as I would loose the default unmarshalling behaviour for the class A.
Anyone has an idea ?
I'm not sure this is cleanest way to that but it works.
I use a static method in the B class ...
class A {
private B field_b=null;
public static class B {
public static B B1 = new B("b1");
public static B B2 = new B("b2");
public static B getForName(String name) {
if (B1.name.equals(name) return B1;
else if (B2.name.equals(name) return B2;
else return null;
}
private final String name;
private B(String name) {
this.name=name;
}
}
... and reflection in the Converter
public class BConverter implements Converter {
public boolean canConvert(Class type) {
return B.class.isAssignableFrom(type) ;
}
public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
writer.setValue(((B)source).getName())
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
try {
Method method = context.getRequiredType().getMethod("getForName", String.class);
final String v = reader.getValue();
Object b= method.invoke(null, v);
if (b== null)
throw new ConversionException("Could not retrieve a B object for \"" + v + "\"");
return b;
} catch (Exception ex) {
throw new ConversionException("Error while retrieving a B object", ex);
}
}
}
I'm not sure if this is possible with Java, but I'm trying to implement an interface that's unavailable at compile time** and pass it to another class as an object of that interface. Let's say I have an interface like:
public interface MyInterface {
void onReceive(int i);
}
and another class like:
public void MyClass {
ArrayList<MyInterface> listenerList = new ArrayList<MyInterface>();
public void add(MyInterface m) {
listenerList.add(m);
}
}
If they were available at compile time, I would be using them like:
blah = new MyInterface() {
public void onReceive(int i) {
System.out.println("BLAH");
}
}
MyClass mc = new MyClass();
myClass.add(blah);
I'm wondering if there is a way to write code that does the same as above if the first two classes are only available at runtime.
Thanks in advance!
**I'm trying to use a framework library from Android's ROM, but it is in dalvik bytecode so I can't use it for compilation.
UPDATE: Here's some sample code I used to test the solution:
File a/IIMSListener.java
// Excerpt from decompiled class
public interface IIMSListener
{
void onReceive(int p0, int p1/*, IMSParameter p2*/);
}
File a/IMSRemoteListenerStub.java
// Excerpt from decompiled class
import java.util.concurrent.*;
import java.util.*;
public class IMSRemoteListenerStub
{
public List<IIMSListener> mListenerList = new CopyOnWriteArrayList<IIMSListener>();
public boolean addListener(final IIMSListener iimsListener) {
if (iimsListener != null && !this.mListenerList.contains(iimsListener)) {
this.mListenerList.add(iimsListener);
return true;
}
return false;
}
public boolean removeListener(final IIMSListener iimsListener) {
if (iimsListener != null && this.mListenerList.contains(iimsListener)) {
this.mListenerList.remove(iimsListener);
return true;
}
return false;
}
}
File b/test.java
import java.lang.reflect.;
import java.util.;
public class test {
public static void main(String[] args) throws IllegalAccessException,
IllegalArgumentException,
InvocationTargetException,
NoSuchMethodException,
SecurityException,
ClassNotFoundException {
// Implement interface
Class<?> IIMSListener = Class.forName("IIMSListener");
Object listenerInstance = Proxy.newProxyInstance(IIMSListener.getClassLoader(), new Class<?>[]{IIMSListener}, new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("onReceive")){
System.out.println("ARGS: " + (Integer)args[0] + ", " + (Integer)args[1]);
return 1;
}
else return -1;
}
});
// Test
Method onReceive = listenerInstance.getClass().getDeclaredMethod("onReceive", new Class[] { int.class, int.class });
onReceive.invoke(listenerInstance, new Object[] { 1, 2 });
try {
// Pass to another class
Class IMSRemoteListenerStub = Class.forName("IMSRemoteListenerStub");
Constructor ctor = IMSRemoteListenerStub.getConstructor();
Object stubInstance = ctor.newInstance(new Object[] {});
Method addListener = stubInstance.getClass().getDeclaredMethod("addListener", new Class[] { IIMSListener });
addListener.invoke(stubInstance, new Object[] { listenerInstance });
// Test
Field mListenerList = IMSRemoteListenerStub.getField("mListenerList");
List<?> list = (List<?>)mListenerList.get(stubInstance);
onReceive.invoke(list.get(0), new Object[] { 3, 4 });
}
catch (InstantiationException e) {}
catch (NoSuchFieldException e) {}
}
}
Execution:
$ cd b
$ CLASSPATH=".:../a" java test
ARGS: 1, 2
ARGS: 3, 4
If it is going to be same interface then use Dynamic Proxies
//Loading the class at runtime
public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException {
Class<?> someInterface = Class.forName("SomeInterface");
Object instance = Proxy.newProxyInstance(someInterface.getClassLoader(), new Class<?>[]{someInterface}, new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//Handle the invocations
if(method.getName().equals("someMethod")){
return 1;
}
else return -1;
}
});
System.out.println(instance.getClass().getDeclaredMethod("someMethod", (Class<?>[])null).invoke(instance, new Object[]{}));
}