Why does this code print 2.0 and not 1.0?
abstract class B<T extends Number> {
abstract Number f(T j);
}
class A<T extends Number> extends B<T> {
public Number f(Float j) {
return 1f;
}
public Number f(T j) {
return j;
}
}
public class J {
public static void main(String[] args) {
B<Float> a = new A<>();
Number r = a.f(2f);
System.out.println(r);
}
}
What are you expecting. You have only one method declared in class B:
abstract Number f(T j);
The method in the class A
public Number f(Float j);
does not override the former. They have different signatures. So the method
public Number f(T j) {
return j;
}
gets called.
So the heart of the problem here is that you have declared the variable a to be of type B. Since the B class has only one method, that's the one that wins. However, in your main, if you change the type of a to be of type A, you'll notice that it will not compile because it is ambiguous. However, if you did change the method in the class A to accept a primitive instead, and in the main() method defined the variable a to be of type A, it would result in 1.0. I.e., the following will result in printing 1.0:
class A<T extends Number> extends B<T> {
public Number f(float j) {
return 1f;
}
public Number f(T j) {
return j;
}
}
public class J {
public static void main(String[] args) {
A<Float> a = new A<>();
Number r = a.f(2f);
System.out.println(r);
}
}
In Your code below
abstract class B<T extends Number> {
abstract Number f(T j);
}
class A<T extends Number> extends B<T> {
public Number f(Float j) //this method does not override the superclass method
{
return 1f;
}
public Number f(T j) {
return j;
}
}
public class J {
public static void main(String[] args) {
B<Float> a = new A<>();
Number r = a.f(2f);
System.out.println(r);
}
}
when call to a.f(2f) is occured it will call the
public Number f(T j)
{
return j;
}
which return j thus output provided is 2.0
float is not the same thing as Float.
Auto-boxing makes it feel the same, but one main difference is you can't pass a null into a float parameter.
I recommend using the #Override annotation on your overridden methods, so the compiler will tell you if the signature is correct
Related
How can I create abstract generic method doSomething() that accepts different enums? Enum1 and Enum2, Enum3 and so on?
public abstract class NumerOne {
public abstract void doSomething();
}
public class NumberTwo extends NumberOne {
#Override
public void doSomething (Enum1 enum1) {
enum1.createSomething();
}
The most appropriate way to accept a handful of Enum types, but not accept any enum (<T extends Enum<T>) or (even worse) Object would be to create an interface and have all the enums that you want to accept implement that interface:
interface CreatorOfSomething {
// I have no idea what type should be returned here,
// as you don't use this value in your example.
// But I'm pretty sure it can't be void, so I'll go with Integer.
// You can have this parameterised as <T> at the interface level.
Integer createSomething();
}
enum Enum1 implements CreatorOfSomething {
A, B, C;
#Override
public Integer createSomething() {
return ordinal();
}
}
enum Enum2 implements CreatorOfSomething {
X { // you can override the method for individual constants
#Override
public Integer createSomething() {
// .....
}
},
Y { ....
}
Then your method would look like:
public void doSomething(CreatorOfSomething creator) {
creator.createSomething();
}
The code you posted does not even compile. Nor could we run it. Next time please provide an SSCCE in which you address your question.
Here's the solution for the problem you have:
abstract class NumberOne {
public abstract <T extends Enum<T>> void doSomething(T pEnum);
}
enum Enum1 {
A, B
}
enum Enum2 {
C, D
}
public class NumberTwo extends NumberOne {
#Override public <T extends Enum<T>> void doSomething(final T pEnum) {
System.out.println("Value: " + pEnum);
}
public static void main(final String[] args) {
final NumberTwo n2 = new NumberTwo();
n2.doSomething(Enum1.A);
n2.doSomething(Enum2.D);
}
}
I'm working on code where I have to cast base class onto derived one where I have an array of generic types that are derived by the base on.
For example, I have Base and Derived1, Derived2 and I put them into Class[]{Derived1.class, Derived2.class} and I pass this array to the constructor of the class.
In this constructor, I have to create instances of these derived classes and I don't know how to do that because I get the info that Class and Base are incompatible.
Here is my code example
public abstract class Base {
public abstract Base create(String s);
}
public class Derived extends Base {
java.lang.Integer value;
private static Derived integer = new Derived();
public static Derived getInstance(){
return integer;
}
public Base create(String s) {
value = java.lang.Integer.parseInt(s);
return this;
}
}
public class Clazz {
Class<? extends Base> type;
ArrayList<Base> arrayList;
public Class<? extends Base> getType() {
return type;
}
}
public class AnotherClazz{
ArrayList<Clazz> clazzArrayList;
Class<? extends Base>[] types;
AnotherClazz(Class<? extends Base>[] args){
clazzArrayList = new ArrayList<>();
types = args; // assuming I pass 2 elements in array
String[] strings = new String[]{"1","2"};
for (int i=0; i<args.length; ++i){
if (types[i] instanceof Base){
// here i want to check validity of class
}
}
for (int i=0; i<strings.length; ++i){
clazzArrayList.get(i).arrayList.add(((types[i]) Base).getInstance().create(strings[i]));
//here i want to create instance of object from type assigned to specific column
}
}
Thanks for the help.
To check the validity, try this
if (types[i].getClass().isAssignableFrom(Base.class))
If I read the question correctly, you want to create a few instances of derived classes that all have the same constructor arguments. If that is the case, then you need to give each derived class the same constructor (it does not need to be in the base class) and use Constructor.newInstance(parameters) to create the instances. Further, since you want to ensure that each derived class extents the base class then you will want to use Class.isAssignableFrom(class). For example,
import java.lang.reflect.Constructor;
public class SO52930530 {
public abstract static class Base {
public abstract <T> T getValue();
}
public static class Derived1 extends Base {
String value;
public Derived1(String value) {
this.value = value;
}
public <T> T getValue() {
return (T) value;
}
}
public static class Derived2 extends Base {
Integer value;
public Derived2(String value) {
this.value = new Integer(value);
}
public <T> T getValue() {
return (T) value;
}
}
public static void main(String... args) throws Exception {
Class<? extends Base>[] extensions = new Class[]{Derived1.class, Derived2.class};
String[] values = new String[]{"a", "1"};
Base[] instances = new Base[values.length];
for (int i = 0; i < instances.length; i++) {
Class extension = extensions[i];
if (Base.class.isAssignableFrom(extension)) {
Constructor constructor = extension.getConstructor(String.class);
instances[i] = (Base) constructor.newInstance(values[i]);
}
}
for (int i = 0; i < instances.length; i++) {
System.out.printf("%d %s %s\n", i, instances[i].getClass(), instances[i].getValue());
}
}
}
I hope this helps.
Thanks for helping with checking validity (it works!) but I still don't get this newInstance creation because I have to read data from .csv file and my derived classes are in fact "wrappers" for primitive types like int, float, etc. and I am supposed to create new object using methods getInstance() and create(string s), so it looks like this:
public static class Derived1 extends Base { //Integer wrapper
Integer value;
public Derived1(Integer value) {
this.value = value;
}
private static Integer integer = new Integer();
public static Integer getInstance(){
return integer;
}
private Integer(){};
public Base create(String s) {
value = java.lang.Integer.parseInt(s);
return this;
}
}
and I don't know how to use Class to cast to appriopriate type.
I have following class structure,
abstract class AbstractA {...}
class A1 extends AbstractA {...}
class A2 extends AbstractA {...}
abstract class AbstractB<T extends AbstractA> {
public void handle(T a) { ... }
}
class B1 extends AbstractB<A1> {
public void handle(A1 a) {
super.handle(a);
...
}
}
class B2 extends AbstractB<A2> {
public void handle(A2 a) {
super.handle(a);
...
}
}
Now I want to implement a generic method that would take a list of AbstractB and related AbstractA as parameters. e.g.
Handler.<B1, A1>handle(listOfB1, A1);
Handler.<B2, A2>handle(listOfB2, A2);
and
Handler.<B1, A2>handle(listOfB1, A2);
Handler.<B2, A1>handle(listOfB2, A1);
is not allowed.
I tried
class Handler {
// public static <T extends AbstractB<K extends AbstractA>, K extends AbstractA> handle(List<T> list, K a) {
public static <T extends AbstractB<? extends AbstractA>, K extends AbstractA> handle(List<T> list, K a) {
for (T tmp : list) {
tmp.handle(a);
}
}
}
but both does not compile. Can anyone help and give me any clue? Thanks!
Change it to :
public static <T extends AbstractB<K>, K extends AbstractA> void handle(List<T> list, K a) {
for (T tmp : list) {
tmp.handle(a);
}
}
Note that your method was missing a return type (I'm assuming your intended a void return type).
However, the main issue was that the type bound of T should be extends AbstractB<K> and not extends AbstractB<? extends AbstractA>.
Consider what happens in your current definition of the static handle method.
The current signature of the static method allows this call :
List<B1> listOfB1;
Handler.<B1, A2>handle(listOfB1, A2);
But in the body of the static method, you can't pass an A2 instance to the handle method of a B1 instance, which is why your code doesn't pass compilation. Therefore the type bound of T must depend on K.
I have to make an especific sort in a object. I read a lot of tutorials and utilized the class Comparable.
My Class:
public class PaAcao implements Serializable, IAcao, Comparable<PaAcao> /* Ordenar */ {
#Override
public int compareTo(PaAcao acaoCompara) {
//return this.aresta - outro.aresta;
int i = 0;
String[] array1 = this.cnrAcao.split(".");
String[] array2 = acaoCompara.cnrAcao.split(".");
for(String c : array1){
if (array2.length > i){
if (Integer.parseInt(c) > Integer.parseInt(array2[i]))
{
return 1;
}
if (Integer.parseInt(c) < Integer.parseInt(array2[i]))
{
return -1;
}
}
i++;
}
return -1;
}
For this Class i have an interface:
package br.com.agraria.qualidade.model.entity;
public interface IAcao{
public abstract String getCnmUsuarResp();
public abstract Usuario getusuarResp();
public abstract void setusuarResp(Usuario usuarResp);
public abstract PaStatusAcao getIcdStatus();
public abstract String getCnrAcao();
public abstract Boolean getLpublico();
}
And i get the error below:
public class PaAcaoServiceImpl extends HibernateGenericServiceImpl<PaAcao> implements PaAcaoService {
#Override
public List<? extends IAcao> processarAcoes(List<? extends IAcao> acoesProcessar) {
SessaoPrivilegiosGerente sessaoPrivilegiosGerente = sessaoService.getSessaoPrivilegiosGerente();
List<IAcao> macroRemover = new ArrayList<IAcao>();
Collections.sort(acoesProcessar);
...
}
}
The problem is in the line Collections.sort(acoesProcessar);
I get the message:
Bound mismatch: The generic method sort(List<T>) of type Collections
is not applicable for the arguments (List<capture#14-of ? extends IAcao>). The inferred type capture#14-of ? extends IAcao is not a
valid substitute for the bounded parameter <T extends Comparable<? super T>>
The resolution was (Thanks Deactivator2 for helping me with this):
Extends Comparable on the interface IAcao:
package br.com.agraria.qualidade.model.entity;
public interface IAcao extends Comparable<IAcao>{
public abstract String getCnmUsuarResp();
public abstract Usuario getusuarResp();
public abstract void setusuarResp(Usuario usuarResp);
public abstract PaStatusAcao getIcdStatus();
public abstract String getCnrAcao();
public abstract Boolean getLpublico();
}
And in my class PaAcao, I remove the implements of Comparable because it'll be duplicated and change the type os compareTo to IAcao and not PaAcao:
public class PaAcao implements Serializable, IAcao /* Ordenar */ {
#Override
public int compareTo(IAcao acaoCompara) {
//return this.aresta - outro.aresta;
int i = 0;
String[] array1 = this.cnrAcao.split(".");
String[] array2 = acaoCompara.cnrAcao.split(".");
for(String c : array1){
if (array2.length > i){
if (Integer.parseInt(c) > Integer.parseInt(array2[i]))
{
return 1;
}
if (Integer.parseInt(c) < Integer.parseInt(array2[i]))
{
return -1;
}
}
i++;
}
return -1;
}
I've made an interface of math operation with one method, calculate, taking various number of arguments
public interface MathOperation {
public <T extends Number> T calculate(T... args);
}
There's also simple implementation of this class, which does not work:
private class Sum implements MathOperation {
#Override
public <T extends Number> T calculate(T... args) {
return args[0] + args[1];
}
}
The problem is:
bad operand types for binary operator '+'
first type: T
second type: T
where T is a type-variable:
T extends Number declared in method <T>calculate(T...)
What I'm trying to achieve is a simple class, taking for example two Doubles and returning Double as well.
Is there possibility to achieve this?
+ cannot be applied to types that extend Number. new Integer(5) + new Integer(5) works because of autoboxing. You will have to look at the runtime type of args and do the operation accordingly.
Something on the lines of:
private class Sum implements MathOperation {
#Override
public <T extends Number> T calculate(Class<T> clazz, T... args) {
if (clazz.equals(Integer.class))
{
return Integer.class.cast(args[0]) + Integer.class.cast(args[1]);
} else (....)
}
}
For Addition we can use doubleValue() method of Number class. To return the same type value, the idea is to use a Function or Supplier or a Factory to create instances of the type T.
class MathOperation<T extends Number> {
public double add(T a, T b) {
double d = a.doubleValue() + b.doubleValue();
return d;
}
public T add(T a, T b, Function<Double,T> function) {
double d = a.doubleValue() + b.doubleValue();
return function.apply(d);
}
}
You can test the runtime type as shown in the other answers. Or you can try a different design: Create an abstract class that works as a factory:
interface MathContext<T extends Number> {
...
T valueOf(double d);
T valueOf(int i);
T add (T... args);
}
And concrete classes for the types that you want to use:
DoubleContext implements MathContext<Double> {
...
Double valueOf(int i) {
return i;
}
Double valueOf(double d) {
return d;
}
Double add(Double... args) {
Double res = 0;
for (Double arg: args) {
res += arg;
}
return res;
}
}
Now you could implement your MathOperation using that class. However, it's not really needed any more.