I have multiple classes whose properties need to be written to a text file. Since each class has different properties each requires a different algorithm to write. I'm trying to use a strategy pattern for this but it doesn't seem to be working out - don't know if this is even the correct pattern to use?
class A
{
void one;
void two;
void three;
}
class B
{
void four;
void five;
void six;
void seven;
}
class C
{
void eight;
void nine;
}
This is where im having trouble with my design, how would I pass the object into the concrete strategy?
class DataParser
{
Object object;
void DataParser(Object object)
{
this.object = object;
parsers.put(new ClassA(), new ClassAParser());
parsers.put(new ClassB(), new ClassBParser());
parsers.put(new ClassC(), new ClassCParser());
}
void writeData()
{
ParserInterface parser = parsers.get(this.object);
/*
* classAParser.setClassA(object);
* classBParser.setClassB(object);
* classCParser.setClassC(object):
*/
parser.write();
}
}
.
interface ParserInterface
{
void write();
void read();
}
.
class ClassAParser()
{
ClassA classA;
void setClassA(ClassA classA)
{
this.classA = classA;
}
void write()
{
PrinterWriter writer = new PrintWriter("ClassA.txt");
writer.printLn(this.classA.getOne() + "|" + this.classA.getTwo() + "|" + this.classA.getThree());
writer.close();
}
void read()
{
}
}
.
class ClassBParser()
{
ClassB classB;
void setClassB (ClassB classB )
{
this.classB = classB ;
}
void write()
{
PrinterWriter writer = new PrintWriter("ClassB.txt");
writer.printLn(this.classB.getFour() + "|" + this.classB.getFive() + "|" + this.classB.getSix() + "|" + this.classB.getSeven());
writer.close();
}
void read()
{
}
}
So then I can just simply do something like this:
class Test()
{
void testClassA()
{
ClassA classA = new ClassA();
classA.setOne("One");
classA.setTwo("Two");
classA.setThree("Three");
DataParser parser = new DataParser(classA);
parser.writeData();
}
}
Then the ClassA.txt should have the following: "one|two|three"
I think the strategy interface might be a little overkill for what you are trying to achieve. An interface will probably get you what you want:
public interface Writable {
void writeTo(PrintWriter writer);
}
class A implements Writable {
String one;
String two;
String three;
public void writeTo(PrintWriter writer) {
// do the writing here
}
}
Repeat for ClassB and ClassC...
Here is a long shot ,
i have seen in your code the following:
parsers.put(new ClassA(), new ClassAParser());
but i cannot find where you declare this variable (i guess is wrong copy-paste)
Anyway, i assume that you use a HashMap because of the method put().
If this is the case you need to implement both equals() and hashCode() in the classes A, B, C.
see here why
Understanding the workings of equals and hashCode in a HashMap
http://www.ibm.com/developerworks/java/library/j-jtp05273/index.html
(in short words if you don't override these methods then the object you pass in the
parsers.get(this.object);
should be the exact same instance with the one of the objects you have putted in your map but in your case it is not)
You can use the same mode as described in Java: If-else instanceof extended classes if you don't want to let your class implements an interface. To factory class you have to pass object to write and where to write.
Another way can be to use a template method pattern in this way:
abstract class ParserReaderWriter implements ParserInterface {
protected abstract String[] getDataToWrite();
protected abstract PrintWriter createWriter();
void write() {
Writer writer = createWriter();
writer.println(StringUtils.join(getDataToWrite(),"|");
writer.close();
}
}
then create a writer for all writer
class AParserReaderWriter extends ParserReaderWriter {
ClassA object;
AParserReaderWriter(ClassA object) {
this.object = object;
}
protected String[] getDataToWrite() {
return new String[]{this.object.getOne(),...};
}
protected PrintWriter createWriter() {
return new PrintWriter("a.txt");
}
}
I don't see the need for a "strategy", here (at least that sounds too heavy-weight for me in this case). Also, I wouldn't "map" anything explicitly here.
So basically I've understood that you'll have objects of the given classes at some time in your application, and then want to create text files in a format defined freely by yourself. This is perfectly valid as a requirement, so I won't point you to any conventions or tools, here. However I also understand that you don't want to do the "serialization" individually within each of the classes, but rather use one (custom) "serializer", probably application-wide. This is where my suggestion differs from other answers.
The method which will actually create the text files needs at least these pieces of information:
the object(s) actually containing the property values
what properties there are (or even: which ones are actually to be considered)
the (base) name of the file to write to - and the character encoding to use, or, more generally, a Writer, or whatever fits your specific requirements on this aspect.
My personal approch would thus be to implement a Util method being as specific as allowed in your case, and as generic as needed to avoid duplicate code.
Within that method, I'd iterate (using reflection) over either:
all accessible (or even all declared) fields
all annotated fields
For the latter variant you'll need to implement your own Annotation to mark the desired properties, or just use the existing "#Transient" annotation to sort out the non-wanted ones. Wait, you'll certainly want the annotation to have RetentionPolicy.RUNTIME:
//...
#Retention( RetentionPolicy.RUNTIME )
public #interface MyAnnotation
//...
But maybe you don't even need to explicitly mark or select properties, particularly if your classes are purely value-holding.
Once you've accessed a given property within the suggested loop, simply make use of String.valueOf (ex- or implicitly) to send the "contents" of that property to a writer, or append to a file directly.
Java serialization generally aims to descend further in object "trees", since any of your properties may be a complex object of its own, requiring more or less sophisticated serialization again.
But I've understood that you rather need a simple, "flat" solution here.
You could use a generic interface for the parser.
public interface ParserInterface<T> {
void setObject(T object);
void read();
void write();
}
public class ClassAParser implements ParserInterface<ClassA> { ... }
As Pitelk mentioned, the map of object and parser seems wrong. Instead you'll want to use a map of class to parser:
parsers.add(ClassA.class, new ClassAParser());
// etc.
Besides: creating instances of all parser implementations in the constructor of DataParser is unnecessary overhead. You could create only the needed instance using an if / else if chain and Object.getClass or instanceof in the constructor or make the map a static member of your class.
writeData then becomes:
void <T> writeData()
{
ParserInterface<T> parser = (ParserInterface<T>) parsers.get(this.object.getClass());
parser.setObject((T) this.object); // <-- same method for all of supported types
parser.write();
}
The compiler will generate a warning about unchecked casts. But if used correctly, i.e. parsers.get(c) returns a compatible parser, it can be ignored or suppressed.
Related
I have a list called itemsData of object of class EtcStruct, but the class can differ depending on the file i want to use (the class is full of variables setters and getters):
ObservableList<EtcStruct> itemsData = FXCollections.observableArrayList();
Im passing it to the method thats supposed to work for any object type i choose and run invoked method from the file.
public static void parseToFile(ObservableList itemsData){
EtcStruct itemObject = (EtcStruct) itemsData.get(0);
System.out.print((int)reflectedmethod.invoke(itemObject);
}
Code above works , but what i want to achieve is make the method work without editing it's object type to make it more flexible for whatever structclass i plan to use.
I tried something with passing Struct Class name and .getClass() it returns the original type but i dont know what to do with it to make the new object of itemsData original type and cast the itemsData object.
public static void parseToFile(ObservableList itemsData,Class c){
Object itemObject = c.newInstance();
Object newobject = curClass.newInstance();
newobject = c.cast(itemsList.get(0));
}
Above seemed dumb to me and obviously didnt work.
After reading your comment I understand better why one would use reflection in your case. A GUI builder/editor is an example where reflection is used to provide an interface to set/get the values of components. Still, IMHO, reflection isn't a tool you would design for when you own the classes and are the primary designer. If possible you should strive for something more like this:
interface Parsable {
default int parse() {
System.out.println("Here I do something basic");
return 0;
}
}
class BasicStruct implements Parsable { }
class EtcStruct implements Parsable {
#Override
public int parse() {
System.out.println("Here I do something specific to an EtcStruct");
return 1;
}
}
// If some structs have a parent-child relationship
// you can alternatively `extend EtcStruct` for example.
class OtherStruct extends EtcStruct {
#Override
public int parse() {
super.parse();
System.out.println("Here I do something specific to an OtherStruct");
return 2;
}
}
void parseToFile(Parsable parsable) {
System.out.println(parsable.parse());
}
// If you use a generic with a specific class you don't
// have to guess or care which kind it is!
void parseToFile(ObservableList<Parsable> parsables) {
for (Parsable p : parsables) {
parseToFile(p);
}
}
public static void main(String[] args) {
ObservableList<Parsable> parsables = FXCollections.observableArrayList();
parsables.add(new BasicStruct());
parsables.add(new EtcStruct());
parsables.add(new OtherStruct());
parseToFile(parsables);
}
Output:
Here I do something basic
0
Here I do something specific to an EtcStruct
1
Here I do something specific to an EtcStruct
Here I do something specific to an OtherStruct
2
Of course, this is just an example that needs to be altered to meet your needs.
But what I still don't get is if you're able to parse from a file why you can't parse to one. Nonetheless, I slapped some code together to show you how I might parse an object to a file, manually, when dealing with Objects only.
The idea is to satisfy a bean-like contract. That is, each structure should provide a parameter-less constructor, all fields you want managed by reflection will follow Java naming convention and will have both a public setter and getter.
Don't get caught up in the file writing; that will be determined by your needs. Just notice that by following this convention I can treat any Object as a parsable structure. A less refined version here for reference:
public void parseToFile(Object object) throws IOException, InvocationTargetException, IllegalAccessException {
fos = new FileOutputStream("example" + object.getClass().getSimpleName());
List<Method> getters = Arrays.stream(object.getClass().getMethods())
.filter(method -> method.getName().startsWith("get") && !method.getName().endsWith("Class"))
.collect(Collectors.toList());
for (Method getter : getters) {
String methodName = getter.getName();
String key = String.valueOf(Character.toLowerCase(methodName.charAt(3))) +
methodName.substring(4, methodName.length());
fos.write((key + " : " + String.valueOf(getter.invoke(object)) + "\n").getBytes());
}
fos.close();
}
I think that you can just still use Generics to keep static objects typing. Try to parametrize your function parseToFile. Here is an example:
public static void parseToFile(ObservableList<EtcStruct> itemsData){
EtcStruct itemObject = itemsData.get(0);
System.out.print((int)reflectedmethod.invoke(itemObject);
}
Take, for example, immutability. How could I modify an object to indicate that it has been made immutable already and need not be wrapped again?
Let us assume we do not want to use reflection to scan for setters as that would be inefficient and insufficient.
Example:
// Deliberately chosing lowercase because it is a system attribute.
interface immutable {
// Nothing in here I can think of.
}
// immute - have I invented a new word?
// What can I do with the return type to indicate immutability?
public static <T> List<T> immute(List<T> list) {
// If it's not an immutable
if (!(list instanceof immutable)) {
// Make it so - how can I stamp it so?
return Collections.<T>unmodifiableList(list);
}
// It is immutable already.
return list;
}
Further playing with the idea produced this foul solution - it is horrible and almost any other trick would be better but I felt I should post. Please please find a better solution:
public class Test {
// Deliberately chosing lowercase because it is a system attribute.
interface immutable {
// Nothing in here I can think of.
}
// immute - have I invented a new word?
// What can I do with the return type to indicate immutability?
public static <T> List<T> immute(List<T> list) {
// If it's not an immutable
if (!(list instanceof immutable)) {
// Make it so - how can I stamp it so?
return Hacker.hack(Collections.<T>unmodifiableList(list),
List.class,
immutable.class);
}
// It is immutable already - code DOES get here.
return list;
}
public void test() {
System.out.println("Hello");
List<String> test = new ArrayList<>();
test.add("Test");
test("Test", test);
List<String> immutableTest = immute(test);
test("Immutable Test", immutableTest);
List<String> immutableImmutableTest = immute(immutableTest);
test("Immutable Immutable Test", immutableImmutableTest);
}
private void test(String name, Object o) {
System.out.println(name + ":" + o.getClass().getSimpleName() + "=" + o);
}
public static void main(String args[]) {
new Test().test();
}
}
class Hacker {
// Hack an object to seem to implement a new interface.
// New interface should be instanceof testable.
// Suggest the additional type is an empty interface.
public static <T> T hack(final Object hack,
final Class<T> baseType,
final Class additionalType) {
return (T) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class[]{baseType, additionalType},
new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Always invoke the method in the hacked object.
return method.invoke(hack, args);
}
});
}
}
If the check will be done on the same location, you could use a set or map, where you put all your wrapped objects, and check them later on in almost constant time. To avoid memory leaks, you could wrap them using weak references .
If the introduction of AOP is a (rather heavyweight) option, you could solve your problem using inter type declarations via AspectJ. This way, you could just add a private member with the reference to the corresponding wrapped instance to the Collection interface, if I remember correctly something like this:
aspect Unmodifieable {
private Collection java.util.Collection.unmofifieableWrapper = null;
public Collection java.util.Collection.getUnmodifieable() {
if (unmofifieableWrapper == null) {
unmofifieableWrapper = somehowRetrieveUnmodifieableCollection(this);
}
return unmofifieableWrapper;
}
}
You can do this with naming conventions in your classes.
interface MyObject;
class MyMutableObject implements MyObject;
class MyImmutableObject implements MyObject;
In my current project, I do something similar. I have an interface that needs to have a setter, but one of the implementing classes is immutable. When you call its setter it throws an Exception (it's setter should never be called, but it's there just to be safe).
The "information" you're looking for is more for the programmer than the compiler, so you don't need a language implemented "stamp".
The Collections.unmodifiable* methods return subtypes of UnmodifiableCollection so you could check UnmodifiableCollection.class.isAssignableFrom(list) then test the concrete types.
Without using instrumentation, I think you're stuck checking types.
Is it possible to generically parameterize a method accepting EITHER ClassA OR InterfaceB ?
Does Not Compile Due to | Pseudocode
public <T extends Number | CharSequence> void orDoer(T someData){ // ... }
i.e. instead of writing multiple method signatures, I would like this one method to accept either a Number or CharSequence as an argument
Should Pass with a Number OR CharSequence argument
orDoer(new Integer(6));
int somePrimitive = 4;
orDoer(somePrimitive);
orDoer("a string of chars");
If you really want to do that, you'll need to wrap youur accepted classes inside a custom class of your own. In your example case, probably something like:
public class OrDoerElement {
private final Number numberValue;
private final CharSequence charSequenceValue;
private OrDoerElement(Number number, CharSequence charSequence) {
this.numberValue = number;
this.charSequenceValue = charSequence;
}
public static OrDoerElement fromCharSequence(CharSequence value) {
return new OrDoerElement(null, value);
}
public static OrDoerElement fromNumber(Number value) {
return new OrDoerElement(value, null);
}
}
And your orDoer method becomes:
public void orDoer(OrDoerElement someData) { .... }
Then you can build one of those and use in your method using either:
orDoer(OrDoerElement.fromCharSequence("a string of chars"));
orDoer(OrDoerElement.fromNumber(new Integer(6)));
But honestly, that sounds a bit too complex and too much work just to be able to call a method with different parameter types. Are you sure you can't achieve the same using two methods, and a third method for the common logic?
Is using an anonymous abstract class an option for you? When I need type safe parameters or return types, I use some variant of the code below. That being said, I agree with the other comments here, and am curious what benefit you really derive when you're enforcing a type safety for a group of objects that don't have all that much in common.
public abstract class Doer<T> {
public void do(T obj) {
// do some stuff.
}
}
// calling method
new Doer<Number>(){}.do(new Integer(5));
For the original question:
public void orDoer(Object someData){
assert someData instanceof Number || someData instanceof CharSequence;
// ...
}
In your more specific case, the assert statement should just use introspection to clarify if the object has the specifics you want, i.e. check for a constructor from String, probe to create a new instance of the object from the toString() result of the incoming object, and compare both for equality:
public void orDoer(Object someData) {
assert isUniconstructable(someData);
}
public static boolean isUniconstructable(Object object) {
try {
return object.equals(object.getClass().getConstructor(String.class)
.newInstance(object.toString()));
} catch (InstantiationException | IllegalAccessException | InvocationTargetException
| NoSuchMethodException| RuntimeException e) {
return false;
}
}
(Because of the exceptions that may be thrown, we need to wrap the assert test into its own function.)
Be aware that introspection may break due to Android’s ProGuard code compression which rewrites the class names, and instead of YourClass just a Class, i.e. Q, is stored in the database, and when you want to restore it with a later version of your app which has more classes, class Q is something different then. See the ProGuard website for more information on this; I just wanted to notify that you should be aware of this when using introspection on Android.
Having a chain of "instanceof" operations is considered a "code smell". The standard answer is "use polymorphism". How would I do it in this case?
There are a number of subclasses of a base class; none of them are under my control. An analogous situation would be with the Java classes Integer, Double, BigDecimal etc.
if (obj instanceof Integer) {NumberStuff.handle((Integer)obj);}
else if (obj instanceof BigDecimal) {BigDecimalStuff.handle((BigDecimal)obj);}
else if (obj instanceof Double) {DoubleStuff.handle((Double)obj);}
I do have control over NumberStuff and so on.
I don't want to use many lines of code where a few lines would do. (Sometimes I make a HashMap mapping Integer.class to an instance of IntegerStuff, BigDecimal.class to an instance of BigDecimalStuff etc. But today I want something simpler.)
I'd like something as simple as this:
public static handle(Integer num) { ... }
public static handle(BigDecimal num) { ... }
But Java just doesn't work that way.
I'd like to use static methods when formatting. The things I'm formatting are composite, where a Thing1 can contain an array Thing2s and a Thing2 can contain an array of Thing1s. I had a problem when I implemented my formatters like this:
class Thing1Formatter {
private static Thing2Formatter thing2Formatter = new Thing2Formatter();
public format(Thing thing) {
thing2Formatter.format(thing.innerThing2);
}
}
class Thing2Formatter {
private static Thing1Formatter thing1Formatter = new Thing1Formatter();
public format(Thing2 thing) {
thing1Formatter.format(thing.innerThing1);
}
}
Yes, I know the HashMap and a bit more code can fix that too. But the "instanceof" seems so readable and maintainable by comparison. Is there anything simple but not smelly?
Note added 5/10/2010:
It turns out that new subclasses will probably be added in the future, and my existing code will have to handle them gracefully. The HashMap on Class won't work in that case because the Class won't be found. A chain of if statements, starting with the most specific and ending with the most general, is probably the best after all:
if (obj instanceof SubClass1) {
// Handle all the methods and properties of SubClass1
} else if (obj instanceof SubClass2) {
// Handle all the methods and properties of SubClass2
} else if (obj instanceof Interface3) {
// Unknown class but it implements Interface3
// so handle those methods and properties
} else if (obj instanceof Interface4) {
// likewise. May want to also handle case of
// object that implements both interfaces.
} else {
// New (unknown) subclass; do what I can with the base class
}
You might be interested in this entry from Steve Yegge's Amazon blog: "when polymorphism fails". Essentially he's addressing cases like this, when polymorphism causes more trouble than it solves.
The issue is that to use polymorphism you have to make the logic of "handle" part of each 'switching' class - i.e. Integer etc. in this case. Clearly this is not practical. Sometimes it isn't even logically the right place to put the code. He recommends the 'instanceof' approach as being the lesser of several evils.
As with all cases where you are forced to write smelly code, keep it buttoned up in one method (or at most one class) so that the smell doesn't leak out.
As highlighted in the comments, the visitor pattern would be a good choice. But without direct control over the target/acceptor/visitee you can't implement that pattern. Here's one way the visitor pattern could possibly still be used here even though you have no direct control over the subclasses by using wrappers (taking Integer as an example):
public class IntegerWrapper {
private Integer integer;
public IntegerWrapper(Integer anInteger){
integer = anInteger;
}
//Access the integer directly such as
public Integer getInteger() { return integer; }
//or method passthrough...
public int intValue() { return integer.intValue(); }
//then implement your visitor:
public void accept(NumericVisitor visitor) {
visitor.visit(this);
}
}
Of course, wrapping a final class might be considered a smell of its own but maybe it's a good fit with your subclasses. Personally, I don't think instanceof is that bad a smell here, especially if it is confined to one method and I would happily use it (probably over my own suggestion above). As you say, its quite readable, typesafe and maintainable. As always, keep it simple.
Instead of a huge if, you can put the instances you handle in a map (key: class, value: handler).
If the lookup by key returns null, call a special handler method which tries to find a matching handler (for example by calling isInstance() on every key in the map).
When a handler is found, register it under the new key.
This makes the general case fast and simple and allows you to handle inheritance.
You can use reflection:
public final class Handler {
public static void handle(Object o) {
try {
Method handler = Handler.class.getMethod("handle", o.getClass());
handler.invoke(null, o);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void handle(Integer num) { /* ... */ }
public static void handle(BigDecimal num) { /* ... */ }
// to handle new types, just add more handle methods...
}
You can expand on the idea to generically handle subclasses and classes that implement certain interfaces.
I think that the best solution is HashMap with Class as key and Handler as value. Note that HashMap based solution runs in constant algorithmic complexity θ(1), while the smelling chain of if-instanceof-else runs in linear algorithmic complexity O(N), where N is the number of links in the if-instanceof-else chain (i.e. the number of different classes to be handled). So the performance of HashMap based solution is asymptotically higher N times than the performance of if-instanceof-else chain solution.
Consider that you need to handle different descendants of Message class differently: Message1, Message2, etc. . Below is the code snippet for HashMap based handling.
public class YourClass {
private class Handler {
public void go(Message message) {
// the default implementation just notifies that it doesn't handle the message
System.out.println(
"Possibly due to a typo, empty handler is set to handle message of type %s : %s",
message.getClass().toString(), message.toString());
}
}
private Map<Class<? extends Message>, Handler> messageHandling =
new HashMap<Class<? extends Message>, Handler>();
// Constructor of your class is a place to initialize the message handling mechanism
public YourClass() {
messageHandling.put(Message1.class, new Handler() { public void go(Message message) {
//TODO: IMPLEMENT HERE SOMETHING APPROPRIATE FOR Message1
} });
messageHandling.put(Message2.class, new Handler() { public void go(Message message) {
//TODO: IMPLEMENT HERE SOMETHING APPROPRIATE FOR Message2
} });
// etc. for Message3, etc.
}
// The method in which you receive a variable of base class Message, but you need to
// handle it in accordance to of what derived type that instance is
public handleMessage(Message message) {
Handler handler = messageHandling.get(message.getClass());
if (handler == null) {
System.out.println(
"Don't know how to handle message of type %s : %s",
message.getClass().toString(), message.toString());
} else {
handler.go(message);
}
}
}
More info on usage of variables of type Class in Java: http://docs.oracle.com/javase/tutorial/reflect/class/classNew.html
You could consider the Chain of Responsibility pattern. For your first example, something like:
public abstract class StuffHandler {
private StuffHandler next;
public final boolean handle(Object o) {
boolean handled = doHandle(o);
if (handled) { return true; }
else if (next == null) { return false; }
else { return next.handle(o); }
}
public void setNext(StuffHandler next) { this.next = next; }
protected abstract boolean doHandle(Object o);
}
public class IntegerHandler extends StuffHandler {
#Override
protected boolean doHandle(Object o) {
if (!o instanceof Integer) {
return false;
}
NumberHandler.handle((Integer) o);
return true;
}
}
and then similarly for your other handlers. Then it's a case of stringing together the StuffHandlers in order (most specific to least specific, with a final 'fallback' handler), and your despatcher code is just firstHandler.handle(o);.
(An alternative is to, rather than using a chain, just have a List<StuffHandler> in your dispatcher class, and have it loop through the list until handle() returns true).
Just go with the instanceof. All the workarounds seem more complicated. Here is a blog post that talks about it: http://www.velocityreviews.com/forums/t302491-instanceof-not-always-bad-the-instanceof-myth.html
I have solved this problem using reflection (around 15 years back in pre Generics era).
GenericClass object = (GenericClass) Class.forName(specificClassName).newInstance();
I have defined one Generic Class ( abstract Base class). I have defined many concrete implementations of base class. Each concrete class will be loaded with className as parameter. This class name is defined as part of configuration.
Base class defines common state across all concrete classes and concrete classes will modify the state by overriding abstract rules defined in base class.
At that time, I don't know the name of this mechanism, which has been known as reflection.
Few more alternatives are listed in this article : Map and enum apart from reflection.
Add a method in BaseClass which returns name of the class. And override the methods with the specific class name
public class BaseClass{
// properties and methods
public String classType(){
return BaseClass.class.getSimpleName();
}
}
public class SubClass1 extends BaseClass{
// properties and methods
#Override
public String classType(){
return SubClass1.class.getSimpleName();
}
}
public class SubClass2 extends BaseClass{
// properties and methods
#Override
public String classType(){
return SubClass1.class.getSimpleName();
}
}
Now use the switch case in following way-
switch(obj.classType()){
case SubClass1:
// do subclass1 task
break;
case SubClass2:
// do subclass2 task
break;
}
What I use for Java 8:
void checkClass(Object object) {
if (object.getClass().toString().equals("class MyClass")) {
//your logic
}
}
The following code does exactly what I want it to, but I am curious if there is a better way of going about it. This would be so much easier if Interfaces allowed static methods, or if Java methods could be generalized/parameterized to the extent they can in C#.
I would much rather substitute the parameter "Class<TParsedClass> c" for "Class<AbstractClass> c". To me "Class<AbstractClass>" means a class that extends a certain abstract class, but apparently that is wrong because when I use that parameter and use it as I descibed above, I get compiler errors.
public <TData, TParsedClass> TParsedClass convert(TData data, Class<TParsedClass> c)
{
try
{
return (TParsedClass)c.getMethod("parse", data.getClass()).invoke(c, data);
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
}
Yes, there is a better way. Use interfaces:
public interface Parser< TData, TParsedClass >
{
TParsedClass parse( TData data );
}
public class IntParser
implements Parser< String, Integer >
{
public Integer parse( String data )
{
return Integer.valueOf( data );
}
}
public <TData, TParsedData> TParsedData convert(
TData data,
Parser< TData, TParsedData > parser
)
{
return parser.parse( data );
}
It's very hard to guess what you "exactly want to do", but I suppose you have some kind of TParsedClass with a static parse method, which populates a new TParsedClass instance with data from a TData instance.
If you think you need some kind of interface marker to indicate which other object a class can parse, why don't you implement the parse method as a non-static method, which populates 'this' with the data from the passed Object?
E.g.
public class A implements Parser<B> {
public void parse(B b) {
this.foo = b.foo;
this.bar = b.bar;
}
}
To convert, you would then do something like this:
A a = new A();
a.parse(b);
instead of
A a = A.parse(b);
You can define TParsedClass as TParsedClass extends AbstractClass, but the Class object doesn't represent an abstract class, it is a way of referring to the definition of a type via reflection.