This is my class structure.
public class Node<T> {
private T value;
public Node(T val) {
this.value = val;
}
public T evaluate() {
return value;
};
}
T can be Integer, Double, Date, Long or String.
Now, is there anyway I can get to know exactly what that type T is? Thanks.
You can invoke getClass() method on that generic variable and find out the class. Basically generics are erased at run-time, so an unbounded generic is nothing but java.lang.Object. So you can invoke all the method supported by Object class on that generic variable
At run-time, getClass() on generic object will return the actual class which was used to substitute the generic
For example
public class Node<T> {
private T value;
public Node(T val) {
Class<?> clazz = val.getClass();
checkType(clazz);
this.value = val;
}
public T evaluate() {
return value;
};
private void checkType(Class<?> c) {
if(c.getName().equals(Integer.class.getName())) {
//...
}
}
}
Much easier, use instanceof.
public class Node<T> {
private T value;
public Node(T val) {
checkType(val);
this.value = val;
}
public T evaluate() {
return value;
};
private void checkType(T val) {
if(val instanceof Integer) {
//...
}
}
}
Though there is already an accepted answer, I think it may be good to add one more answer:
As mentioned by #BaileyS, there is no way to get info of T in a place without an instance of T.
The solution greatly depends on why you want T, how you are using it. Normally, if we need the type of T for the logic (e.g. creating a new instance of T), it is usually done by providing the Class instance.
For example, you can make your Node class be:
public class Node<T> {
private T value;
private Class<T> valueType;
public Node(T val, Class<T> valueType) {
this.value = val;
this.valueType = valueType;
}
//.....
}
If you know that your node will store only Number you could restrict it.
public class Node<T extends Number> {
private final T value;
public Node(T val) {
this.value = val;
}
public T evaluate() {
return value;
};
public Class<? extends Number> type() {
return value.getClass();
}
}
Related
I want to build a Logic Tree in Java which contains the conditions that could be used
for database insertions.
for example:
Node tree = input0.eq(3).and(input1.eq(1).or(input2.greaterThan(5)));
could be converted to:
WHERE input0=3 AND (input1 = 1 OR input2 > 5)
Since a Node could be a logical expression like and,or etc. as well as a Leaf with data, I thought a parent Node class and two child classes, would be ideal. But I have no idea how to handle nested expressions. I already read a few similiar questions here, but they weren't really specific enough.
public class Node {
public Long id;
public Node parent;
public List<Node> children;
}
public class LogicalNode extends Node {
LogicType logicType;
public LogicalNode () {
super();
}
getter and setter...
}
public class LeafNode extends Node {
Object input;
public LeafNode () {
super();
}
getter and setter...
}
public enum LogicType
{
AND("and"),
OR("or"),
NOT("not"),
EQ("="),
GREATER_THAN(">"),
LESSER_THAN("<");
private String name;
LogicType (String name) {
this.name= name;
}
public String getName() {
return name;
}
}
To get you started, try something similar to this:
public abstract class Node {
abstract void toSql();
Node eq(Node other) {
return new LogicalNode(LogicalType.EQ, this, other);
}
...
}
public class LeafNode extends Node {
LeafNode(int value) {
this.value = value;
}
String toSql() {
return this.value.toString();
}
}
public class LogicalNode extends Node {
LogicalNode(LogicalType type, Node left, Node right) {
this.logicalType = type;
this.left = left;
this.right = right;
}
String toSql() {
return String.format(
"(%s) %s (%s)",
this.left.toSql(),
this.logicalType.getName(),
this.right.toSql()
);
}
}
The key here is that the LogicalNode is constructed using two other Nodes, but it doesn't concern itself with whether or not they are LeafNodes or LogicalNodes. All LogicalNode knows is that it has two things that can be converted to a string using toSql.
I've created a kind of custom type on a JSF project using PrimeFaces.
I'd use this type with PrimeFaces's inputNumber but I get the error:
NumberFormatException class java.lang.NumberFormatException
java.lang.NumberFormatException at
java.math.BigDecimal.(BigDecimal.java:550) at
java.math.BigDecimal.(BigDecimal.java:383) at
java.math.BigDecimal.(BigDecimal.java:806) at
org.primefaces.component.inputnumber.InputNumberRenderer.formatForPlugin(InputNumberRenderer.java:292)
at
org.primefaces.component.inputnumber.InputNumberRenderer.encodeScript(InputNumberRenderer.java:231)
at
org.primefaces.component.inputnumber.InputNumberRenderer.encodeEnd(InputNumberRenderer.java:124)
In short, I've created a class MyCurrency that stores a double and extends ValueExpression, like the following:
public final class MyCurrency extends ValueExpression implements Comparable<MyCurrency>, Serializable {
private Double value;
private MyCurrency(final Double value) {
this.value = value;
}
public Double getValue() {
return this.value;
}
public Long longValue() {
return value.longValue();
}
#Override
public int compareTo(final MyCurrency o) {
return this.getValue().compareTo(o.getValue());
}
#Override
public Object getValue(final ELContext context) {
return new BigDecimal(this.value);
}
#Override
public void setValue(final ELContext context, final Object value) {
this.value = new Builder().withValue(value).build().value;
}
public static class Builder {
private Double value;
public Builder withValue(final Double value) {
this.value = value;
return this;
}
public Builder withValue(final Long value) {
this.value = new Double(value);
return this;
}
public Builder withValue(final Object value) {
this.value = Double.parseDouble(value.toString());
return this;
}
public MyCurrency build() {
return new MyCurrency(this.value);
}
}
}
And in my bean I've a property with type MyCurrency.
When I use it with an inputNumber:
<p:inputNumber id="importoDa" value="#{myBean.myAmount}" />
I get the error [NumberFormatException].
Any help, please?
Not sure if it's a solution for what you are asking, but it seems that you are trying to format the input of your inputNumber as currency an compare it's value to another object. It might be easier to store only the double or BigDecimal value in your bean and format it in the view as currency. You can achieve this using the symbol and decimalPlaces properties of the <p:inputNumber> tag this way:
<p:inputNumber id="importoDa" value="#{myBean.myAmount}" symbol="$" decimalPlaces="2" />
Hope it helps :)
If I am writing a wrapper for a generic class, which I have tried to embed the type into at construction (as in this SO question):
class Foo<T> {
private T value;
private Class<T> type;
public Foo(Class<T> type, T value) {
this.value = value;
this.type = type;
}
public T getValue() {
return value;
}
public Class<T> getType() {
return type;
}
}
I have a list of instances of Foo, which I want to transform into a list of FooWrappers, along these lines:
List<Foo<?>> someListOfFoos = ...
List<FooWrapper<?>> fooWrappers = someListOfFoos
.stream()
.map(foo -> FooWrapper.from(foo))
.collect(Collectors.toList());
Is there any way to recover the type of each element in someListOfFoos when building each FooWrapper? Something along these lines:
class FooWrapper<T> {
private Foo<T> foo;
public static FooWrapper<?> from(Foo<?> toWrap) {
Class<E> type = toWrap.getType(); // i know this is wrong
return new FooWrapper<type>(toWrap); // this is very wrong
}
private FooWrapper(Foo<T> foo) {
this.foo = foo;
}
}
You just have to modify your FooWrapper#from slightly, by introducing a generic:
public static <E> FooWrapper<E> from(Foo<E> toWrap) {
return new FooWrapper<E>(toWrap);
}
I have some UI client filters (combobox and checkbox group) that I need to use on server side: I thought to use an enum to identify filter types and others enums to identify each filter's options.
// All UI filters
public enum FilterType {
AGGREGATION("aggregation"),
AREA("area"),
PRODUCTION("production"),
DATA_TYPE("datatype"),
PRODUCER("producer"),
NETWORK("network"),
SOURCE("source");
private String value;
private FilterType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
// FilterType.AGGREGATION filter options
public enum AggregationOptionType {
STANDARD("standard"),
DTR("dtr"),
CO("co");
private String value;
private AggregationOptionType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
I would like to craete a hard link between FilterType.AGGREGATION and AggregationOptionType forcing the access to an option via FilterType.AGGREGATION.DTR.
How can I "nest" an enum inside a value of another enum?
Are there other patterns (maybe smarter than mine) to achieve the same result?
EDIT
A clarification: I do NOT need to assign to each value of the outer enum a value of a common inner enum. I need to assign a whole different inner enum to each value of the outer enum.
You can put one enum into another, like:
enum OuterEnum {
A, B;
enum InnerEnum {
C, D;
}
}
To use like:
class Enumuser {
OuterEnum.InnerEnum ie = OuterEnum.InnerEnum.C;
}
But of course, that is not exactly what you are looking for.
You need to go one step further:
enum OuterEnum {
A(InnerEnum.C), B(InnerEnum.D);
private final InnerEnum inner;
private OuterEnum(InnerEnum inner) { this.inner = inner; }
public InnerEnum getInner() { return inner; }
enum InnerEnum {
C, D;
}
}
class Enumuser {
OuterEnum.InnerEnum inner = OuterEnum.A.getInner();
}
But a final word of warning: don't get too hang up on using enums for such purposes. You see, as soon as you start writing switch statements all over the place that switch over such enums, in order to do this or that ... you are probably doing something wrong. Consider not "falling into that enum trap" please.
Instead you should be looking into using polymorphism, like shown here!
You can add it to the Enum, as a variable.
But only if you can have all the sub Enums under the same enum type ie
public enum FilterType {
AGGREGATION("aggregation",Subfilter.DTR);
}
You can do something like as follows:
//All UI filters
public interface FilterType {
// FilterType.AGGREGATION
public interface AGGREGATION {
// FilterType.AGGREGATION filter options
enum AggregationOptionType {
STANDARD("standard"),
DTR("dtr"),
CO("co");
private String value;
private AggregationOptionType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
}
}
e.g. for AGGREGATION
Just use it in the same way like a String value and if you want to have a single file, so hold your enums in a interface class:
public interface Enums {
public enum FilterType {
AGGREGATION("aggregation", AggregationOptionType.DTR),
AREA("area"),
PRODUCTION("production"),
DATA_TYPE("datatype"),
PRODUCER("producer"),
NETWORK("network", AggregationOptionType.CO),
SOURCE("source");
public final String value;
public final AggregationOptionType type;
private FilterType(String value, AggregationOptionType typy) {
this.value = value;
this.type = typy;
}
private FilterType(String value) {
this.value = value;
this.type = AggregationOptionType.STANDARD;
}
}
public enum AggregationOptionType {
STANDARD("standard"),
DTR("dtr"),
CO("co");
public final String value;
private AggregationOptionType(String value) {
this.value = value;
}
}
}
Good day SO people. I have a problem regarding returning the inner enum values of my enum. I do not know which return type to use. I have tried googling and bumped into some solutions the uses generics however, I still have no luck. I do not know if my question has a solution or probably I did a bad design. So here goes, below
is my enum.
public enum KEYS
{
A("value"),
B("value"),
C("value");
public enum KEYS_GROUP_A
{
ITEM_A ("value"),
ITEM_B ("value"),
ITEM_C ("value");
private String value;
private KEYS_GROUP_A( String _value )
{
value = _value;
}
public String getVal()
{
return value;
}
}
public enum KEYS_GROUP_B
{
ITEM_A ("value"),
ITEM_B ("value"),
ITEM_C ("value");
private String value;
private KEYS_GROUP_B( String _value )
{
value = _value;
}
public String getVal()
{
return value;
}
}
public enum KEYS_GROUP_C
{
ITEM_A ("value"),
ITEM_B ("value"),
ITEM_C ("value");
private String value;
private KEYS_GROUP_C( String _value )
{
value = _value;
}
public String getVal()
{
return value;
}
}
private String value;
private PROPERTY_KEYS(String _value)
{
value = _value;
}
public String getVal()
{
return value;
}
public <?> getEnumValues(int x)
{
if ( 0 == x )
{
return KEYS.KEYS_GROUP_A.values();
}
else if ( 1 == x )
{
return KEYS.KEYS_GROUP_B.values();
}
else
{
return KEYS.KEYS_GROUP_C.values();
}
}
}
What I am trying to do is the getEnumValues() method. I have tried the return type <T extends Enum<T>> T but still an error occurs. Please tell if my design is bad or should not really be done. Please state some references. I'm willing to read and learn. Please shed some light! Thanks in advance!
The most specific type you can return is
public Enum<?>[] getEnumValues(int x)
You can return a more "useful" type if you define an interface like this:
interface HasVal { String getVal(); }
then make your enums all implement that interface, e.g.:
public enum KEYS_GROUP_A implements HasVal {
// ...
#Override public String getVal() { return value; }
}
Then you can return
public HasVal[] getEnumValues(int x)
and be able to invoke the getVal method on the instances:
for (HasVal val : getEnumValues(x)) {
System.out.println(val.getVal());
}
You can't use:
public <T extends Enum<T>> T[] getEnumValues(int x)
because this isn't satisfiable for a general T. For instance, I could define:
enum Blah {}
and then try to invoke:
Blah[] blah = getEnumValues(1);
That wouldn't be type safe, because at least one (well, all, actually) of the code paths return a value which is not covariant with Blah[].