I have an Operator interface for handling math operator that has two method like so:
public interface Operator
{
double calculate(double firstNumber,double secondNumber);
char getSign();
}
for each operator I have a class that implement Operator interface like so:
public class Plus implements Operator
{
public double calculate(double firstNumber,double secondNumber)
{
return firstNumber + secondNumber;
}
public char getSign()
{
return '+';
}
}
And so on...
In this code I use Reflections :
Reflections reflections = new Reflections("mypackage");
Set<Class<? extends Operator>> classes = reflections.getSubTypesOf(Operator.class);
Reflections is not the part of java Reflection API.I should just use java Reflection capability.
Can anyone help me to change this code that only use java Reflection API?
Instead of using the Reflections API, you can
search your class path for directories and JARs
for the directories look for each class file
for the JAR scan through the files for each class file
read the byte code of the class file with a library like ASM.
if the class implement your interface add it
otherwise check all the super classes and interfaces of the class to see if they implement the interface.
The reason you have to read the byte code is you want to avoid loading all the classes just to see the inheritance hierarchy, esp as some of the classes might not load or could take a long time.
Needless to say, using a library which does this for you is easier. If youw ant to write this yourself I suggest you read the source of the Reflections API to see how it does it.
A simpler solution is to use an enum
enum Operators implement Operator {
PLUS {
public double calculate(double x, double y) {
return x + y;
}
public char getSign() {
return '+';
}
},
MINUS {
public double calculate(double x, double y) {
return x - y;
}
public char getSign() {
return '-';
}
},
TIMES {
public double calculate(double x, double y) {
return x * y;
}
public char getSign() {
return '*';
}
},
DIVIDE {
public double calculate(double x, double y) {
return x / y;
}
public char getSign() {
return '/';
}
}
}
To get all the operators you can use
Operator[] operators = Operators.values();
You cannot scan the class path for the sub types. If you can correlate, even for JPA you would have to specify the entity names as part of configuration. Use a similar approach to specify the list of classes you like to scan through and check if the instanceof. Reflections API only can help with you in that case if not.
Related
My English is not good. So I try to explain my question in code. Please try to answer me in code. It makes me understand easily.
I have a question: In C++,we can realize that like these codes.
int max(int x,int y)
{
return (x>y)?x:y;
}
float max(float x,float y)
{
return (x>y)?x:y;
}
I can do this to expand code
template <class T>
T max(T x, T y)
{
return (x>y)?x:y;
}
How can I realize the similar function in Java.
You can use generics. Because generics do not work with primitives, and objects cannot be compared with greater-than and less-than operators, we must instead restrict the input types to Comparables (things which can be compared) so that we can use the compareTo method instead:
public static <T extends Comparable<T>> T max(T first, T second)
{
return first.compareTo(second) >= 0 ? first : second;
}
Sample usage:
max(1, 2)
will autobox the primitives to Integers (which do implement Comparable<Integer>) and return 2.
The underlying assumption in the c++ code is that the T type supports the > operator. Java doesn't have operator overloading, but the equivalent would be to limit the code to Ts that implement the Comparable interface:
public static <T extends Comparable<T>> T max(T x, T y)
{
if (x.compareTo(y) > 0) {
return x;
}
return y;
}
Or, alternatively, allow the caller to pass a custom Comparator:
public static <T> T max(T x, T y, Comparator<T> cmp)
{
if (cmp.compare(x, y) > 0) {
return x;
}
return y;
}
Use generics. They are like templates but work in runtime
package test;
class BoxPrinter<T> {
private T val;
public BoxPrinter(T arg) {
val = arg;
}
public String toString() {
return "{" + val + "}";
}
public T getValue() {
return val;
}
}
https://www.geeksforgeeks.org/generics-in-java/
More examples here
So I have a field called optionType and I want it to be able to take on 4 different integer values corresponding to certain options. For example optionType = 0 means the user wants to handle something a certain way, optionType = 1 means another way, etc.
But numbers by themselves are meaningless so I wanted to define constants instead in the class.
public class MyClass {
public static final int OPTION_TYPE_DO_THIS = 0;
public static final int OPTION_TYPE_DO_THAT = 1;
public static final int OPTION_TYPE_DO_SOMETHING_ELSE = 2;
public static final int OPTION_TYPE_DO_COOL_THING = 3;
private int optionType;
....
Is it considered normal to define all the constants out like that or is it better to use an enum like
public enum OPTION_TYPE {DO_THIS, DO_THAT, DO_SOMETHING_ELSE, DO_COOL_THING};
Or am I supposed to be using Enum instead somehow?
The key point is more on "how will that information be used at runtime". You see, if you starting thinking about writing code such as
switch(someEnum) {
case DO_THIS: ...
case DO_THAT:
... then you are already going into the wrong direction!
The point is: very often think that enums (or their even-more-low-level numeric constant cousins) are a good way to express such designs.
But that actually leads to quite some problems. Very often, the better, "more OO" way of thing is to use some abstract base class with specific subclasses; in other words: polymorphism!
Edit: just to make that more clear ... a "single" switch over an enum isn't really a problem. But far too often, people end up with many many places in code where they switch over their enums. And all of those places might need updates when you create additional enum constants. A coworker of mine calls that the "enum trap".
Take a look at this question and answer,
Even though it is written in the C# context, the conclusion states that:
Enums are great for lightweight state information.
Static class members would be able to support this multiple state without any extra functionality.
In java enums are more than just "enumerated names" as they are in other language (e.g. in C/C++).
My preferred use is to provide stateless behavior:
class Calculator {
enum Operation {
ADD{
double calculate(double a, double b){ return a + b;}
}
SUB{
double calculate(double a, double b){ return a - b;}
}
MUL{
double calculate(double a, double b){ return a * b;}
}
DIV{
double calculate(double a, double b){ return a / b;}
}
abstract double calculate(double a, double b);
}
Map<String,Operation> operations = new HashMap<>();
Calculator(){
operations.put("+",ADD);
operations.put("-",SUB);
operations.put("*",MUL);
operations.put("/",DIV);
}
public double calculate(double a, String operation, double b){
return operations.get(operation).calculate(a,b);
}
}
I am not primarily a Java programmer... I would like to find a corresponding Java syntax for class storing a function pointer (templatized) as a variable. The function pointer points to a function "outside" the class. The original code is in C++11:
#include <memory>
template <typename T>
using p_function = T(*)(T, T, T);
template <typename T>
class A
{
private:
int k;
p_function<T> pf;
public:
A() { pf = NULL; k = 0; }
A(p_function<T> pf_, int k_) { pf = pf_; k = k_; }
T getF(const T a1, const T a2, const T a3) const { return pf(a1, a2, a3); }
};
template <typename T>
T f1(T x, T y, T z) { return x + y + z; }
template <typename T>
T f2(T x, T y, T z) { return x - y - z; }
int main()
{
A<double> aa (f1<double>, 1.0);
double val= aa.getF(1.0, 2.0, 3.0);
}
Thinking about the problem, is it reasonable to use the interface?
public interface Function <T> {
T pf(T x, T y, T z);
}
or, is there any better way? Java is relatively rapidly develops, there might be "straighter" constructions than few years ago. There are several requirements which I am not able to join together. Could I ask for a short code sample in Java? Thank you very much for your help.
Use java 8. That uses "functional" interfaces (indeed) where an interface defines just one single function.
To not overuse the existing Function class, introduce your own name.
#FunctionalInterface
public interface TriFunction<T> {
T apply(T x, T y, T z);
}
Marking it with the FunctionalInterface annotation is a practice that prevents adding a second function and such.
class Foo {
public static Bar hop(Bar x, Bar y, Bar z) { ... }
}
TriFunction<Bar> pf = Foo::hop;
TriFunction<Integer> pg = (x, y, z) -> x + y + z;
Bar bara = pf.apply(a, b, c);
For primitive types better define own interfaces without generic parameter types. Above pg needs 3 times to unbox the wrapper objects, and one time to box it again to an object.
The package java.util.function contains many functional interfaces, like BinaryOperator and IntBinaryOperator.
In Java 8, you can use method references. More information here: https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
Basically, Java 8 gives interfaces with only one method the special property that they can be used (sort of) like function pointers. You can assign a lambda or a method reference to an object of such a type.
For example, somewhat related to your question:
public class HelloWorld {
public interface Function <T> {
T op(T x, T y);
}
public static class Functions {
static int add(int x, int y) { return x + y; }
static int sub(int x, int y) { return x - y; }
}
static Function<Integer> f1, f2; // <-- "function pointer"
public static void main(String []args) {
f1 = Functions::add; // <-- static method reference
f2 = Functions::sub; // <-- static method reference
System.out.println("Test: " + f1.op(1,2) + ", " + f2.op(1,2));
}
}
This code prints, as you'd expect:
Test: 3, -1
So that part of your question should work. However, the part where you define a generic addition is more problematic, because Java doesn't allow you to overload the operator '+'. So the following will not compile in Java:
T add(T x, T y) {
return x + y; // compile error -> no '+' defined for T
}
If you need T to be base types, you'll need to define your f1 and f2 for each base type you want to use. See also this question: Can I do arithmetic operations on the Number baseclass?
I am not sure if I get your question correctly, but have a look at this stackoverflow post.
There are several answers on how to implement function pointer in java.
EDIT
I am not experienced enough in C++ to provide a code sample.
EDIT 2
According to the post I mentioned above, you could try something like this:
public class WithFunction {
//Empty constructor, can be left out
public WithFunction () {...}
//The function you want to reference
public int myReferencedFunction () {...}
}
Then
public class MethodCaller {
public static Object call (Object theObject, String methodName) {
return theObject.getClass().getMethod(methodName).invoke(theObject);
//catch Exceptions
}
}
Then you can have it like
public static void main (String [] args) {
WithFunction obj1 = new WithFunction();
Object result = MethodCaller.call (obj1, "toString");
int result = (int) MethodCaller.call (obj1, "myReferencedFunction");
}
Notice:
You need to catch a lot of exceptions. Strong error handling needed..
If you use an interface, you can also implement it multiple times and should have the freedom you need
How the enum that we get from java 1.5 is different from C++ and other conventional Enum Type.
In java enums are complex objects, whilst in C++ every enum object is associated with a single integer value. In java you can have several attributes associated with a single enum value:
enum MyCategory {
SPORT("The sport category", "sport.png"),
NEWS("the news category", "news.jpg");
private String description;
private String iconPath;
private MyCategory(String description, String iconPath) {
this.description = description;
this.iconPath = iconPath;
}
public String getDescription() {
return description;
}
public String getIconPath() {
return iconPath;
}
}
Furthermore in java you can switch only Number types, Strings and enums. However I can not generalize the conventional enums as a whole...
EDIT One more thing the java enums can do is declare per-value operation (taken from the java tutorial):
public enum Operation {
PLUS { double eval(double x, double y) { return x + y; } },
MINUS { double eval(double x, double y) { return x - y; } },
TIMES { double eval(double x, double y) { return x * y; } },
DIVIDE { double eval(double x, double y) { return x / y; } };
// Do arithmetic op represented by this constant
abstract double eval(double x, double y);
}
Java programming language enums are far more powerful than their counterparts in other languages, which are little more than glorified integers. The new enum declaration defines a full-fledged class (dubbed an enum type). In addition to solving all the problems(Not typesafe, No namespace, Brittleness and Printed values are uninformative) that exists with following int Enum pattern which was used prior to java 5.0 :
public static final int SEASON_WINTER = 0;
it also allows you to add arbitrary methods and fields to an enum type, to implement arbitrary interfaces, and more. Enum types provide high-quality implementations of all the Object methods. They are Comparable and Serializable, and the serial form is designed to withstand arbitrary changes in the enum type.
Read the full article Java Enums for more details.
I'm writing an expression evaluator in Java. I would like the ability to add more operators (I currently have only (, ), +, -, *, /, and ^). Currently, my code looks like this:
case '+':
return a+b;
case '-':
return a-b;
case '*':
return a*b;
...
This works for my code because I have only a few operators. However, if I were to add more operators, the code would become cluttered. I am looking for a way to map an operator (represented by a String) to a method. For example, "ln" would be mapped to Math.log(), "^" would be mapped to Math.pow(), etc.
How would I go about doing this? If it's not feasible, what are some alternatives?
Not possible unless you want to use reflection. A solution without reflection could look like this:
public interface Operation {
int apply(int... operands);
}
public abstract class BinaryOperation implements Operation {
#Override
public int apply(int... operands) {
return apply(operands[0], operands[1]);
}
abstract int apply(int a, int b);
}
Map<String, Operation> operations = new HashMap<String, Operation>() {{
put("+", new Operation() {
#Override
public int apply(int... operands) {
return operands[0] + operands[1];
}
});
put("-", new BinaryOperation() {
#Override
public int apply(int a, int b) {
return a - b;
}
});
}};
You could use template methods.
public enum Functions {
ADD() {
#Override public int execute(int a, int b) {
return a+b;
}
},
SUB() {
#Override public int execute(int a, int b) {
return a-b;
}
};
//Template method
public abstract int execute(int a, int b);
}
Then map between string and enum with Map<String, Functions> functionMap
So if you want to add you can do functionMap.put("+", Functions.ADD);
Then call functionMap.get("+").execute(a,b);
I suppose you could also use varargs if different functions take different numbers of arguments.
public abstract int execute (Integer... inputs);
This example is modified from Making the Most of Java 5.0: Enum Tricks and what #duffymo said.
Building on the Operation suggestion above, a Map<String, Operation> would manage it with a lookup.
I think your setup is the optimal setup as I cannot think of a way to do this easily in java, although in a language like c/c++ you could easily map strings to function pointers but I don't think there's an equivalent of this in Java AFAIK. The beauty of switch statements though is that they actually avoid the clutter because visually you can easily see what the case of the switch statement is and just look for the appropriate case that you want (although for strings you made need a giant if cascade since == operator is not overloaded in java for string comparison).
Edit: See Ryan Stewarts comment, they use OOP ways of doing exactly what you want. Although that seems more cluttered than your switch statement in some cases.