help with reflection + constructors - java

I have code I'm working on to instantiate a CRC algorithm dependent on a polynomial passed in, and a string s that contains "crc8" or "crc16" or "crc32".
The classes CRC8, CRC16, and CRC32 all extend a class CRC and implement an interface HashAlgorithm. Each of them has a constructor CRCx(int polynomial).
My problem is, I get this error on all 3 of the getConstructor() lines:
Type mismatch:
cannot convert from Constructor<HashFactory.CRC16>
to Constructor<HashFactory.CRC>
Can anyone help explain why and help me fix this?
int polynomial; // assign from somewhere
Constructor<CRC> crc = null;
if ("crc8".equals(s))
{
crc = CRC8.class.getConstructor(Integer.TYPE);
}
if ("crc16".equals(s))
{
crc = CRC16.class.getConstructor(Integer.TYPE);
}
if ("crc32".equals(s))
{
crc = CRC32.class.getConstructor(Integer.TYPE);
}
if (crc != null)
{
CRC crcInstance = crc.newInstance(polynomial);
return (HashAlgorithm) crcInstance;
}

Try
int polynomial; // assign from somewhere
if ("crc8".equals(s)) {
return new CRC8(polynomial);
} else
if ("crc16".equals(s)) {
return new CRC16(polynomial);
} else
if ("crc32".equals(s)) {
return new CRC32(polynomial);
}
Or
package tests;
import java.lang.reflect.Constructor;
public class Construct {
static interface CRC { }
static class CRC8 implements CRC {
public CRC8(int p) { }
}
static class CRC16 implements CRC {
public CRC16(int p) { }
}
static class CRC32 implements CRC {
public CRC32(int p) { }
}
public static CRC getAlg(String s, int polynomial) {
try {
Class<?> clazz = Class.forName("tests.Construct$" + s.toUpperCase());
Constructor<?> c = clazz.getConstructor(Integer.TYPE);
return CRC.class.cast(c.newInstance(polynomial));
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
throw new AssertionError("Unknown algorithm: " +s);
}
public static void main(String[] args) throws Exception {
System.out.println(getAlg("crc8", 0));
System.out.println(getAlg("crc16", 0));
System.out.println(getAlg("crc32", 0));
System.out.println(getAlg("crc48", 0));
}
}
"Factory" pattern:
public static HashAlgorithm getHashAlgorithm(String s, int polynomial) {
if ("crc8".equals(s)) {
return new CRC8(polynomial);
} else
if ("crc16".equals(s)) {
return new CRC16(polynomial);
} else
if ("crc32".equals(s)) {
return new CRC32(polynomial);
}
throw new AssertionError("Unknown algorithm: " +s);
}
It can be done several other ways (e.g HashMap of algorithms to duplicatable classes of CRCs, etc.)

Try declaring the crc variable like this:
Constructor<? extends CRC> crc = null;

Thanks to the wonders of generics, Constructor<HashFactory.CRC16> is not type compatible with Constructor<HashFactory.CRC>. You need to pick something more general for your variable, like this:
Constructor<? extends CRC> crc = null;

Others have offered solutions to your problem, but my advice is to not use Java reflection where you don't need to. A solution that uses reflection is typically more slower, the code is more complex, and there typically are more "dynamic typing" failure cases to consider.
In your particular example, the "object factory" pattern is a better solution than using reflection to invoke constructors.

Related

Anonymous inner class example validity concern

I was trying to review some of the Java language using a spark chart I had once bought. Regarding the use of anonymous inner classes they give this example :
Dice rollDice() {
return new Dice() {
int number = (int)( Math.random() * 6 ) + 1;
};
}
Problem is, I do not see how this would work, and can not get the compiler to accept it as a method within another class. The compiler complains about each reference to Dice "symbol can not be found."
Am I not understanding their example correctly or is this completely invalid code? Thanks in advance!
p.s. if this is working code, could someone provide me with an example of how it can be used?
Edit: I have found something that finally makes sense
The syntax for an anonymous inner class is shown below
new SuperClassName/InterfaceName() {
// Implement or override methods in superclass or interface
// Other methods if necessary
}
This above code is passed to a method that takes an instance of Superclass or completely implements the Interface. For instance, a method that has an EventHandlerparameter and we have not already defined a class that implements the handle(ActionEvent e) method.
enlargeButton.setOnAction(
new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
circlePane.enlarge();
}
});
In this way, it will truly be anonymous. I think the example given in Java's own tutorial to be very poor.
It looks like you've mostly answered your own question and you will probably want to go through some full tutorial or documentation to understand things fully, but here are some answers to your immediate questions.
Your first sample code wont compile until you have a Dice class or interface you can extend. So as an example you can get this code to compile:
class Dicey {
interface Dice {
}
Dice rollDice() {
return new Dice() {
int number = (int) (Math.random() * 6) + 1;
};
}
public static void main(String... none) {
Dice dice = new Dicey().rollDice();
// dice.number; <-- not available
}
}
Now you can do this, but as you suspect this is not a very useful things to do (for a few reasons) but the biggest problem is that after you create this anonymous instance there isn't really a way to get to the .number member.
More usually you would have an anonymous subclass implement some methods on the interface, so that you can actually do something with it. So for example
class HelloAnonymous {
interface Hello {
String say();
}
Hello hello(String world) {
return new Hello() {
public String say() {
return world;
}
};
}
public static void main(String... none) {
System.out.println(new HelloAnonymous().hello("world").say());
// prints 'world'
}
}
gives you a way of making fantastically useful Hello objects that can say something. Having said all this, writing anonymous inner classes is fairly old school because functional interfaces now largely replace the need for them. So in this example you could have:
class HelloAnonymous {
#FunctionalInterface
interface Hello {
String say();
}
// old school
Hello hello(String world) {
return new Hello() {
public String say() {
return world;
}
};
}
// with lambda notation
Hello alsoHello(String world) {
return () -> {
return world;
};
}
public static void main(String... none) {
System.out.println(new HelloAnonymous().hello("world").say());
System.out.println(new HelloAnonymous().alsoHello("world").say());
}
}
since I don't know about 'Dice' class I cannot write same method but I try some thing similar to that. It compile and work can access 'number' variable by using reflection. My opinion is it is not very useful. Following is my code:
public class TestClass {
public static void main(String a[]){
TestClass aClass = rollDice();
try {
System.out.println("value of number : " + aClass.getClass().getDeclaredField("number").getInt(aClass));
}
catch (NoSuchFieldException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
}
static TestClass rollDice() {
return new TestClass() {
int number = (int) (Math.random() * 6) + 1;
};
}
}
That example is extremely broken. Throw that source away. Try this:
import java.util.Random;
public class DieFactory {
interface Die { int roll(); }
static Die create(long seed) {
Random random = new Random(seed);
return new Die() {
#Override
public int roll() {
return random.nextInt(6) + 1;
}
};
}
// Now you can roll 2 dice pretty easily.
public static void main(String [] args) {
DieFactory.Die die1 = DieFactory.create(42);
DieFactory.Die die2 = DieFactory.create(24);
for (int i = 0; i < 40; i++) {
System.out.println(die1.roll() + die2.roll());
}
}
}
Incidentally, the word "dice" is plural for the singular "die."

Need design suggestions for nested conditions

I need to write the logic with many conditions(up to 30 conditions) in one set of rule with many if else conditions and it could end in between or after all the conditions.
Here is the sample code I have tried with some possible scenario. This gives me result but doesn't look good and any minor miss in one condition would take forever to track.
What I have tried so far is, Take out common conditions and refactored to some methods. Tried creating interface with conditions and various set would implement it.
If you have any suggestion to design this, would help me. Not looking for detailed solution but even a hint would be great.
private Boolean RunCondition(Input input) {
Boolean ret=false;
//First if
if(input.a.equals("v1")){
//Somelogic1();
//Second if
if(input.b.equals("v2"))
//Third if
if(input.c >1)
//Fourth if
//Somelogic2();
//Go fetch key Z1 from database and see if d matches.
if(input.d.equals("Z1"))
System.out.println("Passed 1");
// Fourth Else
else{
System.out.println("Failed at fourth");
}
//Third Else
else{
if(input.aa.equals("v2"))
System.out.println("Failed at third");
}
//Second Else
else{
if(input.bb.equals("v2"))
System.out.println("Failed at second");
}
}
//First Else
else{
if(input.cc.equals("v2"))
System.out.println("Failed aat first");
}
return ret;
}
public class Input {
String a;
String b;
int c;
String d;
String e;
String aa;
String bb;
String cc;
String dd;
String ee;
}
The flow is complicated because you have a normal flow, plus many possible exception flows when some of the values are exceptional (e.g. invalid).
This is a perfect candidate to be handled using a try/catch/finally block.
Your program can be rewritten into following:
private Boolean RunCondition(Input input) {
Boolean ret=false;
try {
//First if
if(!input.a.equals("v1")) {
throw new ValidationException("Failed aat first");
}
//Somelogic1();
//Second if
if(!input.b.equals("v2")) {
throw new ValidationException("Failed at second");
}
//Somelogic2()
//Third if
if(input.c<=1) {
throw new ValidationException("Failed at third");
}
//Fourth if
//Somelogic2();
//Go fetch key Z1 from database and see if d matches.
if(!input.d.equals("Z1")) {
throw new ValidationException("Failed at fourth");
}
System.out.println("Passed 1");
} catch (ValidationException e) {
System.out.println(e.getMessage());
}
return ret;
}
Where you can define your own ValidationException (like below), or you can reuse some of the existing standard exception such as RuntimeException
class ValidationException extends RuntimeException {
public ValidationException(String arg0) {
super(arg0);
// TODO Auto-generated constructor stub
}
/**
*
*/
private static final long serialVersionUID = 1L;
}
You can read more about this in
https://docs.oracle.com/javase/tutorial/essential/exceptions/index.html
Make a separate class for the condition:
package com.foo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class App
{
static class Condition<T> {
final int idx;
final T compareValue;
public Condition(final int idx, final T compareValue) {
this.idx = idx;
this.compareValue = compareValue;
}
boolean satisfies(final T other) {
return other.equals(compareValue);
}
int getIdx() {
return idx;
}
}
public static void main( String[] args )
{
final List<Condition<String>> conditions = new ArrayList<Condition<String>>();
conditions.add(new Condition<String>(1, "v1"));
conditions.add(new Condition<String>(2, "v2"));
final List<String> inputs = new ArrayList<String>(Arrays.asList("v1", "xyz"));
boolean ret = true;
for (int i = 0; i < inputs.size(); i++) {
if (!conditions.get(i).satisfies(inputs.get(i)))
{
System.out.println("failed at " + conditions.get(i).getIdx());
ret = false;
break;
}
}
System.out.println("ret=" + ret);
}
}
#leeyuiwah's answer has a clear structure of the conditional logic, but exceptions aren't the right tool for the job here.
You shouldn't use exceptions to cope with non-exceptional conditions. For one thing, exceptions are really expensive to construct, because you have to walk all the way up the call stack to construct the stack trace; but you don't need the stack trace at all.
Check out Effective Java 2nd Ed Item 57: "Use exceptions only for exceptional conditions" for a detailed discussion of why you shouldn't use exceptions like this.
A simpler option is to define a little helper method:
private static boolean printAndReturnFalse(String message) {
System.out.println(message);
return false;
}
Then:
if(!input.a.equals("v1")) {
return printAndReturnFalse("Failed aat first");
}
// etc.
which I think is a simpler; and it'll be a lot faster.
Think of each rule check as an object, or as a Strategy that returns whether or not the rule passes. Each check should implement the same IRuleCheck interface and return a RuleCheckResult, which indicates if the check passed or the reason for failure.
public interface IRuleCheck
{
public RuleCheckResult Check(Input input);
public String Name();
}
public class RuleCheckResult
{
private String _errorMessage;
public RuleCheckResult(){}//All Good
public RuleCheckResult(String errorMessage)
{
_errorMessage = errorMessage;
}
public string ErrorMessage()
{
return _errorMessage;
}
public Boolean Passed()
{
return _errorMessage == null || _errorMessage.isEmpty();
}
}
public class CheckOne implements IRuleCheck
{
public RuleCheckResult Check(Input input)
{
if (input.d.equals("Z1"))
{
return new RuleCheckResult();//passed
}
return new RuleCheckResult("d did not equal z1");
}
public String Name();
}
Then you can simply build a list of rules and loop through them,
and either jump out when one fails, or compile a list of failures.
for (IRuleCheck check : checkList)
{
System.out.println("checking: " + check.Name());
RuleCheckResult result = check.Check(input);
if(!result.Passed())
{
System.out.println("FAILED: " + check.Name()+ " - " + result.ErrorMessage());
//either jump out and return result or add it to failure list to return later.
}
}
And the advantage of using the interface is that the checks can be as complicated or simple as necessary, and you can create arbitrary lists for checking any combination of rules in any order.

Java: Use the same code with two different versions of a dependent class

Consider a Java class Foo that uses a library Bar. Foo should be distributed as a binary .class file and use the version of Bar that is already existing on a clients classpath.
There are two different versions of Bar that only differ in its method signatures. Foo should be compatible with both of them.
Example code:
public class Foo {
public static void main(String[] args){
Bar.librarycall("hello from foo");
//or
Bar.librarycall("hello from foo",1);
}
}
//v1
public class Bar {
public static void librarycall(String argument){
System.out.println("Bar1: " + argument);
}
}
//v2
public class Bar {
public static void librarycall(String argument,int i){
for(int j = 0; j < i; j++)
System.out.println("Bar2: " + argument);
}
}
I want to avoid reflection if possible. How would you propose to create a class Foo that is compatible with both versions of Bar?
[Edit]
This problem originates in a project I am working on. Bar corresponds to an external library I am using but cannot be modified for the code to work (I don't have the source code and the license doesn't allow modifications).
A refelective solution.
Class<?> c;
try {
c = Class.forName("Bar");
Method meths[] = c.getMethods();
Method v1method = null;
Method v2method = null;
for(Method m:meths) {
if(!m.getName().equals("librarycall")) continue;
if(!Modifier.isStatic(m.getModifiers())) {
System.out.println("Should be static");
continue;
}
Class<?> params[] = m.getParameterTypes();
if(params.length == 1 && params[0].equals(String.class) )
v1method = m;
if(params.length == 2 && params[0].equals(String.class) && params[1].equals(Integer.TYPE) )
v2method = m;
}
if(v2method!=null) {
v2method.invoke(null,"V2",5);
}
else if(v1method!=null) {
v1method.invoke(null,"V1");
}
else
System.out.println("No method found");
} catch (ClassNotFoundException e) {
System.out.println(e);
} catch (IllegalArgumentException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
} catch (InvocationTargetException e) {
System.out.println(e);
}
You could use c = Bar.class; or if you already have an instance bar of Bar c = bar.getClass(). The invoke syntax is for static methods if its non static you need v1method.invoke(bar,"V1");.
Reflection does seem like the simplest way. The alternative would be to try calling the second version and catch a NoSuchMethodException.
public class Foo {
public static void main(String[] args){
try {
Bar.librarycall("hello from foo",1);
catch(NoSuchMethodException e) {
Bar.librarycall("hello from foo");
}
}
This is ugly, and slower, use Reflection its what its there for.
It sounds like this one task that is handled by the strategy pattern.
I'm assuming that:
You cannot change any of the versions of the Bar class files
You have the ability to write new Foo files
For some reason, you really want to avoid using Reflection
The two Bar files have the same package name
You may need to distribute two versions of the Foo class, as mentioned by JB Nizet in the comment to your question.

Static and non static access to value

I have a class called Packet and a class called PacketClientConnecting witch extends it. The instances of PacketClientConnecting and other packets are stored in ArrayList<Packet>.
I want to have access to id value in static and non-static ways eg PacketClientConnecting.getStaticId() or packetArrayList.get(5).getId().
How can i do this without overriding two functions in every class?
I don't think there's a really smooth way of doing this, but one can achieve what you want by using reflection (only once: in the base class):
class Packet {
public static int getStaticId() {
return 1;
}
// This method is virtual and will be inherited without change
public int getId() {
try {
// Find and invoke the static method corresponding
// to the run-time instance
Method getStaticId = this.getClass().getMethod("getStaticId");
return (Integer) getStaticId.invoke(null);
// Catch three reflection-related exceptions at once, if you are on Java 7+,
// use multi-catch or just ReflectiveOperationException
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
Now in the subclass all you need is define getStaticId():
class PacketClientConnecting extends Packet {
public static int getStaticId() {
return 2;
}
}
Let's test it:
class Main {
public static void main(String[] args) {
// Both print 1
System.out.println(Packet.getStaticId());
System.out.println(new Packet().getId());
// Both print 2
System.out.println(PacketClientConnecting.getStaticId());
System.out.println(new PacketClientConnecting().getId());
}
}
If you want to avoid the overhead of calling reflective operations every time you call getId(), you can use a field in the base class to cache the id:
class Packet {
public static int getStaticId() {
return 1;
}
private final int id = computeId();
public int getId() {
return id;
}
// This method runs once per instance created
private int computeId() {
try {
Method getStaticId = this.getClass().getMethod("getStaticId");
return (Integer) getStaticId.invoke(null);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}

Java and avoid if statements for objects with similar methods

I have 2 classes e.g. A and B.
These classes have a couple of getter/setter methods with the same name.
Now in the code I do the following:
if(obj.getClassName().equals(A.class.getName())){
A a = (A) obj;
String result = a.getInfo();
}
else if(obj.getClassName().equals(B.class.getName())){
B a = (B) obj;
String result = a.getInfo();
}
I was wondering if there is a way to call the getInfo avoiding the if statements.
Note: I can not refactor the classes to use inheritence or something else.
I was just interested if there is a trick in java to avoid the if statements.
Unless you want to use reflection, no. Java treats two types which happen to declare the same method (getInfo()) as entirely separate, with entirely separate methods.
If you've got commonality, you should be using a common superclass or a common interface that both of them inherit. You've tagged the question "design-patterns" - the pattern is to use the tools that the language provides to show commonality.
As Eng.Fouad shows, using instanceof is simpler anyway - and better, as it means your code will still work with subclasses of A or B.
You can isolate this ugliness, of course, by putting it in a single place - either with a facade class which can be constructed from either an A or a B, or by having a single method which performs this check, and then calling that from multiple places.
If you can't use inheritance and want to avoid if statements (even using instanceof)... well... the best you can do is wrap the check, cast and call in a function to avoid code duplication... otherwise there's no way to do this.
You need reflection. here is my complete example.
Class A
package a;
public class A {
String info;
public String getInfo() {
System.out.println("A getInfo");
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
Class B
package a;
public class B {
String info;
public String getInfo() {
System.out.println("B getInfo");
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
Test Class
package a;
import java.lang.reflect.Method;
public class TestAB {
public static void main(String[] args) {
A a= new A();
doSth(a);
}
private static void doSth(Object obj) {
Class c = obj.getClass();
Method m;
try {
m = c.getMethod("getInfo", new Class[] { });
String result = (String) m.invoke(obj);
} catch (Exception e) {
e.printStackTrace();
}
}
}
See this line :
Class c = obj.getClass();
and
m = c.getMethod("getInfo", new Class[] { });
and
String result = (String) m.invoke(obj);
There is no if statements
If obj is declared as either A or B, you can use overloaded methods. (A good argument for type safety.) Here's a test that illustrates this:
import static org.junit.Assert.*;
import org.junit.Test;
public class FooTest {
class A {
public String getInfo() {
return "A";
}
}
class B {
public String getInfo() {
return "B";
}
}
public String doBarFor(A a) {
return a.getInfo();
}
public String doBarFor(B b) {
return b.getInfo();
}
public String doBarFor(Object obj) {
throw new UnsupportedOperationException();
}
#Test
public void shouldDoBarForA() {
A a = new A();
assertEquals("A", doBarFor(a));
}
#Test
public void shouldDoBarForB() {
B b = new B();
assertEquals("B", doBarFor(b));
}
#Test(expected = UnsupportedOperationException.class)
public void shouldFailIfDeclaredAsObject() {
Object a = new A();
assertEquals("A", doBarFor(a)); // exception thrown
}
}
How about:
String result = null;
if(obj instanceof A)
{
result = ((A) obj).getInfo();
}
else if(obj instanceof B)
{
result = ((B) obj).getInfo();
}
Refer to : this tutorial if this is what you were trying to achieve.
If obj is an Object, you'll need to check. If you don't want to use an if-statement, you can try just casting and catch the exception:
String result = null;
try {
result = ((A)obj).getInfo();
}
catch(ClassCastException e1) {
try {
result = ((B)obj).getInfo();
}
catch(ClassCastException e2) {
// do something else
}
}
Another thing you can do is make both classes implement an Interface then check for just that Interface, something like:
public interface HasInfo
{
public String getInfo();
}
Then add implements HasInfo in the class definition for A and B. Then you can just check (or cast) to HasInfo.
In Java you can use a dot as a scope resolution operator with static methods. Try something like this:
String a_info = A.getInfo();
String b_info = B.getInfo();
With objects, if two interfaces really have the same method with the same parameters and the same return type, why must they be treated differently? Take a look here for some more insight into the problem.
Good luck.

Categories