I'm trying to do a generic class in Java.
Reading some guides, I found how to declare it and also how to call its function as well.
My class is a point and without methods it would be in this way:
class Pnt<type>{
protected type x, y;
protected int col;
}
Now, I'm trying to make an add method, but I am not able to do it.
What I tried is:
void add(type x_, type y_){
x += x_;
y += y_;
}
The IDE is yelling at me that += is undefined for type variables...
I know that in Java isn't possible to define a new operator like in C++, so I'm asking for an alternative way to add two type variables!
P.S. All the type that I will use would be doubles, floats and integers, that's why I'm trying to make a simple addiction.
When you say class Pnt<type>, ti means that type is an object and not a primitive data type like int or double. You can perform += operation on numeric primitive data types like int, float, etc and not on an object. In fact you can't perform the += operation with any generic object.
The objects of Integer, Float, etc. support the += operator, because they are wrapper classes and get unboxed to primitive types and autoboxed later. But the compiler has no way to confirm that the type will be an Integer or Float. Therefore, it generates a compile time error.
There are two problems: First, if it should be fast, you have to use primitives directly, and these are not supported as a parameter in generics. This effectively means you have to maintain three versions for Point separately.
If you want to use generics, you can use the corresponding class (like Integer), but there is still one problem: Their super type Number does not have an add method (let alone a + operator or +=).
So the only way I know is to implement your own numeric class hierarchy which supports an add method:
abstract class Numeric<T extends Number> {
public abstract T getValue();
public abstract Numeric<T> add(Numeric<T> other);
#Override
public String toString() {
return getValue().toString();
}
}
class MyInt extends Numeric<Integer> {
public final Integer value;
public MyInt(Integer _value) {
super();
this.value = _value;
}
#Override
public Integer getValue() {
return this.value;
}
#Override
public Numeric<Integer> add(Numeric<Integer> other) {
return new MyInt(this.value + other.getValue());
}
}
class MyDouble extends Numeric<Double> {
public final double value;
public MyDouble(Double _value) {
super();
this.value = _value;
}
#Override
public Double getValue() {
return this.value;
}
#Override
public Numeric<Double> add(Numeric<Double> other) {
return new MyDouble(this.value + other.getValue());
}
}
Based on this you can implement at least a generic point:
class NumericPoint<T extends Number> {
public final Numeric<T> x;
public final Numeric<T> y;
public NumericPoint(Numeric<T> _x, Numeric<T> _y) {
super();
this.x = _x;
this.y = _y;
}
public NumericPoint<T> add(NumericPoint<T> other) {
return new NumericPoint<T>(this.x.add(other.x), this.y.add(other.y));
}
#Override
public String toString() {
return "(" + this.x + "/" + this.y + ")";
}
}
to be used with
NumericPoint<Integer> ip1 =
new NumericPoint<Integer>(new MyInt(1), new MyInt(2));
NumericPoint<Integer> ip2 =
new NumericPoint<Integer>(new MyInt(3), new MyInt(4));
NumericPoint<Integer> ip = ip1.add(ip2);
System.out.println(ip);
NumericPoint<Double> dp1 =
new NumericPoint<Double>(new MyDouble(1.1), new MyDouble(2.1));
NumericPoint<Double> dp2 =
new NumericPoint<Double>(new MyDouble(3.1), new MyDouble(4.1));
NumericPoint<Double> dp = dp1.add(dp2);
System.out.println(dp);
I have modified your example: The numerics and the points are immutable. It's implemented like BigDecimal for example. So the add method belongs to the generic class, and it returns a new instance.
Related
Let's consider this code:
public interface Number {
public Number plus(Number n);
}
public class Complex implements Number {
private double re, im;
public Complex(double re, double im) {
this.re = re;
this.im = im;
}
#Override
public Complex plus(Complex c) {
return new Complex(this.re + c.re, this.im + this.im);
}
}
It wouldn't compile because if Complex.plus() overrides Number.plus(), its argument must be exactly the same as the overridden method. I thought about using generics for the type of objects a number can interact with, but it produces a very unclean code, with unparametrized use of Number and redundancy:
public interface Number<T extends Number> {
public T plus(T n);
}
public class Complex implements Number<Complex> {
private double re, im;
public Complex(double re, double im) {
this.re = re;
this.im = im;
}
#Override
public Complex plus(Complex c) {
return new Complex(this.re + c.re, this.im + this.im);
}
}
Is there a more elegant way to achieve this?
Thank you for your help.
Simple fix: make the type parameter self-bounded:
public interface Number<T extends Number<T>> {
(and then pinky-swear that you'll only ever define a classes that implement the interface for themselves, e.g. class Self implements Number<Self>)
However, I would do this without the Number interface, at least in terms of the plus method. Unless you can meaningfully add different subtypes of Number, having such a method in the common interface doesn't obviously serve a purpose.
Consider why there are no arithmetic methods defined on the standard Number interface.
Instead, don't have the plus "operator" in the Complex class either: use the standard BinaryOperator interface to define a plus operator for specific types:
BinaryOperator<Complex> complexPlus = (a, b) -> new Complex(a.re + b.re, a.im + b.im);
BinaryOperator<Integer> integerPlus = (a, b) -> a + b; // Or Integer::sum.
and then apply these:
Complex complexSum = complexPlus.apply(firstComplex, secondComplex);
Integer integerSum = integerPlus.apply(firstInt, secondInt);
I have a generic interface like this:
interface A<T> {
T getValue();
}
This interface has limited instances, hence it would be best to implement them as enum values. The problem is those instances have different type of values, so I tried the following approach but it does not compile:
public enum B implements A {
A1<String> {
#Override
public String getValue() {
return "value";
}
},
A2<Integer> {
#Override
public Integer getValue() {
return 0;
}
};
}
Any idea about this?
You can't. Java doesn't allow generic types on enum constants. They are allowed on enum types, though:
public enum B implements A<String> {
A1, A2;
}
What you could do in this case is either have an enum type for each generic type, or 'fake' having an enum by just making it a class:
public class B<T> implements A<T> {
public static final B<String> A1 = new B<String>();
public static final B<Integer> A2 = new B<Integer>();
private B() {};
}
Unfortunately, they both have drawbacks.
As Java developers designing certain APIs, we come across this issue frequently. I was reconfirming my own doubts when I came across this post, but I have a verbose workaround to it:
// class name is awful for this example, but it will make more sense if you
// read further
public interface MetaDataKey<T extends Serializable> extends Serializable
{
T getValue();
}
public final class TypeSafeKeys
{
static enum StringKeys implements MetaDataKey<String>
{
A1("key1");
private final String value;
StringKeys(String value) { this.value = value; }
#Override
public String getValue() { return value; }
}
static enum IntegerKeys implements MetaDataKey<Integer>
{
A2(0);
private final Integer value;
IntegerKeys (Integer value) { this.value = value; }
#Override
public Integer getValue() { return value; }
}
public static final MetaDataKey<String> A1 = StringKeys.A1;
public static final MetaDataKey<Integer> A2 = IntegerKeys.A2;
}
At that point, you gain the benefit of being a truly constant enumeration value (and all of the perks that go with that), as well being an unique implementation of the interface, but you have the global accessibility desired by the enum.
Clearly, this adds verbosity, which creates the potential for copy/paste mistakes. You could make the enums public and simply add an extra layer to their access.
Designs that tend to use these features tend to suffer from brittle equals implementations because they are usually coupled with some other unique value, such as a name, which can be unwittingly duplicated across the codebase for a similar, yet different purpose. By using enums across the board, equality is a freebie that is immune to such brittle behavior.
The major drawback to such as system, beyond verbosity, is the idea of converting back and forth between the globally unique keys (e.g., marshaling to and from JSON). If they're just keys, then they can be safely reinstantiated (duplicated) at the cost of wasting memory, but using what was previously a weakness--equals--as an advantage.
There is a workaround to this that provides global implementation uniqueness by cluttering it with an anonymous type per global instance:
public abstract class BasicMetaDataKey<T extends Serializable>
implements MetaDataKey<T>
{
private final T value;
public BasicMetaDataKey(T value)
{
this.value = value;
}
#Override
public T getValue()
{
return value;
}
// #Override equals
// #Override hashCode
}
public final class TypeSafeKeys
{
public static final MetaDataKey<String> A1 =
new BasicMetaDataKey<String>("value") {};
public static final MetaDataKey<Integer> A2 =
new BasicMetaDataKey<Integer>(0) {};
}
Note that each instance uses an anonymous implementation, but nothing else is needed to implement it, so the {} are empty. This is both confusing and annoying, but it works if instance references are preferable and clutter is kept to a minimum, although it may be a bit cryptic to less experienced Java developers, thereby making it harder to maintain.
Finally, the only way to provide global uniqueness and reassignment is to be a little more creative with what is happening. The most common use for globally shared interfaces that I have seen are for MetaData buckets that tend to mix a lot of different values, with different types (the T, on a per key basis):
public interface MetaDataKey<T extends Serializable> extends Serializable
{
Class<T> getType();
String getName();
}
public final class TypeSafeKeys
{
public static enum StringKeys implements MetaDataKey<String>
{
A1;
#Override
public Class<String> getType() { return String.class; }
#Override
public String getName()
{
return getDeclaringClass().getName() + "." + name();
}
}
public static enum IntegerKeys implements MetaDataKey<Integer>
{
A2;
#Override
public Class<Integer> getType() { return Integer.class; }
#Override
public String getName()
{
return getDeclaringClass().getName() + "." + name();
}
}
public static final MetaDataKey<String> A1 = StringKeys.A1;
public static final MetaDataKey<Integer> A2 = IntegerKeys.A2;
}
This provides the same flexibility as the first option, and it provides a mechanism for obtaining a reference via reflection, if it becomes necessary later, therefore avoiding the need for instantiable later. It also avoids a lot of the error prone copy/paste mistakes that the first option provides because it won't compile if the first method is wrong, and the second method does not need to change. The only note is that you should ensure that the enums meant to be used in that fashion are public to avoid anyone getting access errors because they do not have access to the inner enum; if you did not want to have those MetaDataKeys going across a marshaled wire, then keeping them hidden from outside packages could be used to automatically discard them (during marshaling, reflectively check to see if the enum is accessible, and if it is not, then ignore the key/value). There is nothing gained or lost by making it public except providing two ways to access the instance, if the more obvious static references are maintained (as the enum instances are just that anyway).
I just wish that they made it so that enums could extend objects in Java. Maybe in Java 9?
The final option does not really solve your need, as you were asking for values, but I suspect that this gets toward the actual goal.
If JEP 301: Enhanced Enums gets accepted, then you will be able to use syntax like this (taken from proposal):
enum Primitive<X> {
INT<Integer>(Integer.class, 0) {
int mod(int x, int y) { return x % y; }
int add(int x, int y) { return x + y; }
},
FLOAT<Float>(Float.class, 0f) {
long add(long x, long y) { return x + y; }
}, ... ;
final Class<X> boxClass;
final X defaultValue;
Primitive(Class<X> boxClass, X defaultValue) {
this.boxClass = boxClass;
this.defaultValue = defaultValue;
}
}
By using this Java annotation processor https://github.com/cmoine/generic-enums, you can write this:
import org.cmoine.genericEnums.GenericEnum;
import org.cmoine.genericEnums.GenericEnumParam;
#GenericEnum
public enum B implements A<#GenericEnumParam Object> {
A1(String.class, "value"), A2(int.class, 0);
#GenericEnumParam
private final Object value;
B(Class<?> clazz, #GenericEnumParam Object value) {
this.value = value;
}
#GenericEnumParam
#Override
public Object getValue() {
return value;
}
}
The annotation processor will generate an enum BExt with hopefully all what you need!
if you prefer you can also use this syntax:
import org.cmoine.genericEnums.GenericEnum;
import org.cmoine.genericEnums.GenericEnumParam;
#GenericEnum
public enum B implements A<#GenericEnumParam Object> {
A1(String.class) {
#Override
public #GenericEnumParam Object getValue() {
return "value";
}
}, A2(int.class) {
#Override
public #GenericEnumParam Object getValue() {
return 0;
}
};
B(Class<?> clazz) {
}
#Override
public abstract #GenericEnumParam Object getValue();
}
I want to make good use of polymorphism in java when implementing math operations between objects of math classes.
I got from the answers in How to add two java.lang.Numbers?
that the general solution when using java.lang.Number is to know or check the real objects class and make the appropriate hardcoded conversion to float, int, etc.
But this approach actually is not very object oriented. The java language designers chose to give the java.lang.Number class and its derivatives a set of methods floatValue(), intValue() and so on.
In light of this, Is my proposed approach, below, not going to work?.
To implement mathematical operations in a seamless way I want to to rewrite the Number class Hierarchy to allow to do something like this:
MyNumber a = b.getValue() + c.getValue();
where the real type of b and c don't matter
The base class would be:
public abstract class MyNumber {
protected Object mValue;
public abstract <N> N getValue();
}
And, for example, my integer class would look like:
public class MyInteger extends MyNumber {
public MyInteger(int value) {
mValue = value;
}
#Override
public Integer getValue() {
return (Integer) mValue;
}
}
and similarly for MyFloat, MyDouble, etc.
It will not work with different types.
public class MyInteger extends MyNumber {
public MyInteger(int value) {
mValue = value;
}
#Override
public Integer getValue() {
return (Integer) mValue;
}
}
public class MyFloat extends MyNumber {
public MyFloat(float value) {
mValue = value;
}
#Override
public Float getValue() { // first issue: types don't match. can't override
return (float) mValue; // second issue: type won't match with other getValue methods, arithmetic will fail
}
}
Your problem is even before the arithmetic. You'll need to use generics, or some kind of type-resolving and/or type-converting mechanis to get past this issue.
Firstly, overriding methods need to have matching signatures, and Types are part of that signature.
Secondly, after having a single type, Java does not have operator overloading. Therefore you will need to implement a method that MyNumber has that can take your two Generic or high level Object's and do that type casting or conversion itself.
Why won't the following program compile? Correct it so that it will compile and properly implement Comparable.
class Int implements Comparable
{
private int x;
public Int(int x)
{
this.x = x;
}
public int compareTo(Int other)
{
return x - other.x;
}
}
----//// im assuming that the compareTo method is wrong.. but i dont know why or how to fix it.
The interface Comparable is defined with a type parameter of <T>.
If one does not provide a generic type parameter to a class or interface that requires it, then the default type parameter is assumed to be Object.
So, in effect, your class declaration reads like this:
public class Int implements Comparable<Object>
Now, this is where things get interesting. compareTo(T other) takes the generic type parameter as its type argument. If you don't explicitly declare the type to be something, then the method signature reads compareTo(Object other).
Suffice to say, but Object and Int aren't the same object. When you attempt to declare your method as #Override, the compiler will inform you that your method doesn't inherit or implement anything.
Ultimately, what this boils down to: you have to fix your type parameter. If you want to compare against Int, explicitly declare it so:
public class Int implements Comparable<Int>
Now, your code will compile.
Replace:
class Int implements Comparable
With:
class Int implements Comparable<Int>
You need to specify what you're comparing to. If it's blank, then you need to compare Objects in compareTo().
Try This
public class Int implements Comparable<Int> {
private int x;
public Int(int x) {
this.x = x;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
#Override
public int compareTo(Int other) {
return x-other.getX();
}
}
class Aliphatic<F> extends Organic<F>{}
class Hexane<G> extends Aliphatic<G>{}
public class Organic<E>{
void react(E e){}
static void main(String[] args){
Organic<? extends Organic> compound = new Aliphatic<Organic>();
compound.react(new Organic());
}
}
Why can't I call react method with Organic argument?
The generic type ot the reference <? extends Organic> says that the generic type of the instantiation canb either a Organic, or a subtype of Organic.
Is because the compiler doesn't know this instantiation generic type until runtime type an so, it does not bind any value to its generic criteria?
Why is this case working? Is this case the same?
public class WildcardCollection {
public static void main (String[] args){
WildcardCollection w = new WildcardCollection();
w.myMethod(new Items("hola",1)); //Compile
w.myMethod(new SubItems("nuevo",3)); //Compile
}
public <T extends Items> void myMethod(T a){ //Same as above
System.out.println("hi: "+a);
}
}
class SubItems extends Items {
SubItems(){};
SubItems(String s, int i){ super(s,i);}
}
class Items implements Comparable<Items> {
private String name;
private int value;
public Items() {}
public Items(String n, int i){ this.name = n; this.value = i;}
public String getName(){ return this.name;}
public int getValue(){ return this.value;}
public String toString(){ return "(" + this.name + "-" + this.value + ")";}
public int compareTo(Items i){
return this.value - i.getValue();
}
}
Quite simply, if you have an object of some generic type with a type parameter T instantiated with a ? extends X wildcard then you can't call methods on the object that take parameters of type T because the compiler can't guarantee type safety. However you can call methods that return T (and assign the return value to a variable of type X). In your specific example it looks like this should be safe
Organic<? extends Organic> compound = new Aliphatic<Organic>();
compound.react(new Organic());
but remember that the compiler has to match the react call based on the declaration type (? extends Organic), it can't rely on what you've assigned on the RHS. If the compiler allowed this then it would also have to allow
Organic<? extends Organic> compound = new Aliphatic<Hexane<?>>();
compound.react(new Organic());
which is clearly not correct - it's exactly the same situation as
Collection<? extends Number> nums = new ArrayList<Float>();
nums.add(Integer.valueOf(1));
(all this is aside from the fact that since Organic is generic you need to say Organic<? extends Organic<?>> or similar rather than just Organic<? extends Organic>)