简体   繁体   中英

Using generics in Java and numeric types

Hey there I have just started Java for a course I will be taking soon (yeah I'm a nerd, I study before I have start the class). I wanted to cram a few concepts together to learn how everything works together in Java.

Now, what I wanted to try to do is a simple Shape (Forme in french) class which has a least 1-2 classes inheriting from it and make a few instances inside a collections object. I also wanted to make those classes generics to try that out as well. That is the part I'm having trouble with.

I'm very used to C++ so that may be where the confusion lies, but it seems that I can't use generics so that, for example, I can specify that dimensions will be in, say, Integer or Double or Float or whatever. Is it possible ?

The GetArea() method below can't compile because of base and hauteur .

package testconcepts;

import java.util.*;
import java.lang.*;

abstract class Forme <T extends Number> {
    protected String nom_forme;

    String NomForme() { return nom_forme; }

    abstract Double GetArea();
}

class Triangle <T extends Number> extends Forme {
    protected T base, hauteur;

    Triangle() { 
        this.nom_forme = "TRIANGLE"; 
    }

    @Override
    Double GetArea() { return base * hauteur / 2; }

    T GetBase() { return base; }
    T GetHauteur() { return hauteur; }
    void SetBase(T base) { this.base = base; }
    void SetHauteur(T hauteur) { this.hauteur = hauteur; }
}

public class TestConceptsJava {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(new Triangle<Double>());
    }
}

Notice that I also cannot make assignments to 0 in the constructor because of type issues.

Also, I know there are very similar topics, but I haven't found a solution to my problem yet in those other questions.

TLDR How can I make work generics with primitive type wrappers (Double, Integer..) ?

So your problem is this line I guess:

Double GetArea() { return base * hauteur / 2; }

The reason you receive an error is because the * operator is undefined for objects of type Number . Since you know that you will be dealing with int s and double s (I assume), you can try this:

Double GetArea() { return base.doubleValue() * hauteur.doubleValue() / 2; }

As a note, usually we start method names with a lower case letter, ie getArea() .

In GetArea(), you're calling the * operator on two classes. How much sense would it make to say something like:

Object o1 = //whatever;
Object o2 = //whatever;

return o1 * o2;

Not much right? You can't multiply two classes. What you actually want to do is multiply the underlying value of those wrapper classes (which is not done implicitly for you in Java). Rewriting GetArea() like this should solve your problem:

Double GetArea() { return base.doubleValue() * hauteur.doubleValue() / 2; }

Note that you'll also have to use the underlying value everywhere else that you care about it in that class.

Changing to Double GetArea() { return base.doubleValue() * hauteur.doubleValue() / 2; } Double GetArea() { return base.doubleValue() * hauteur.doubleValue() / 2; } will make code compile, but this is bad idea in Java, since generics in java aren't for this. They just, basically, to ensure static type safety when using collections of objects.

Java has no operator overloading, so you can't expect * to work for anything except primitive types.

I'd suggest reading basic Java generics tutorial to get an idea what are they for in Java: http://docs.oracle.com/javase/1.5.0/docs/guide/language/generics.html

Look at this part of your calculation:

base * hauteur

Since both base and hauteur are declared using a wrapper class, you cannot use the * operator like you can with primitive types. Instead, you need to get the value explicitly:

base.doubleValue() * hauteur.doubleValue()

Note that this wouldn't be a problem if either base or hauteur were declared with a primitive type. Then the Java compiler would be able to use auto-unboxing to convert the other one to the appropriate type and do any implicit conversions needed.

What you're looking for is called "auto-(un)boxing". Unfortunately, operations on T must be valid for all subtypes of Number , and "auto-(un)boxing" is not such an operation (eg, it will not work with BigInteger ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM