Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:Java.lang.Number的重载(通用)方法_Java_Generics_Numbers_Polymorphism_Overloading - Fatal编程技术网

Java:Java.lang.Number的重载(通用)方法

Java:Java.lang.Number的重载(通用)方法,java,generics,numbers,polymorphism,overloading,Java,Generics,Numbers,Polymorphism,Overloading,所以我读了,因为我有一个类似的问题。 在我的例子中,我希望能够允许对数字进行数学运算。我的想法是编写一个不可变的“RealNumber”类来处理原始数(整数、长数、浮点和双精度),而不需要一堆instanceof控件。有人提到要重载方法,让编译器来完成这项工作。 这是我第一次尝试: 简单测试类: public class Test { public static void main(String[] args) { RealNumber<Double> d = RealNum

所以我读了,因为我有一个类似的问题。 在我的例子中,我希望能够允许对数字进行数学运算。我的想法是编写一个不可变的“RealNumber”类来处理原始数(整数、长数、浮点和双精度),而不需要一堆instanceof控件。有人提到要重载方法,让编译器来完成这项工作。
这是我第一次尝试:

简单测试类:

public class Test {
public static void main(String[] args) {
    RealNumber<Double> d = RealNumber.create(3.4);
    d.add(4.7);
    }
}
公共类测试{
公共静态void main(字符串[]args){
realnumed=RealNumber.create(3.4);
d、 增加(4.7);
}
}
RealNumber类:(请在注释中提及方法)

public类RealNumber扩展了Number{
N数;
私有实数(N个){
if(number==null){
抛出新的NullPointerException(“数字为null”);
}
这个数字=数字;
}
公共N get(){
返回号码;
}
//注意这个方法
公共重新分配编号添加(N编号){
返回添加(编号);
}
私有实数加法(整数){
返回新的RealNumber(intValue()+number);
}
私有实数添加(长数){
返回新的实数(longValue()+数字);
}
私有实数添加(浮动数){
返回新的实数(floatValue()+数字);
}
私有实数添加(双倍数){
返回新的实数(doubleValue()+数字);
}
@凌驾
公共int值(){
返回编号。intValue();
}
@凌驾
公共长期价值(){
返回编号。longValue();
}
@凌驾
公共浮动价值(){
返回number.floatValue();
}
@凌驾
公共双双值(){
返回数字。doubleValue();
}
公共静态最终实数创建(整数){
返回新的实数(number);
}
公共静态最终实数创建(长数){
返回新的实数(number);
}
公共静态最终实数创建(浮动数){
返回新的实数(number);
}
公共静态最终实数创建(双倍数){
返回新的实数(number);
}
}
因此,第一个测试将我引向StackOverflowerr,因为方法“add”总是调用自己

第二次尝试(仅更改方法)

public RealNumber添加(数字){
返回添加(编号);
}
第一个没有那么好,因为它允许添加大小数或其他类似布尔值的东西,第二个导致我使用相同的StackOverflower错误。所以我改变了:

public RealNumber<N> add(N number){
    return add(number);
}

//note the public here
public RealNumber<Double> add(Double number){
    return new RealNumber<Double>(doubleValue() + number);
}
//... public RealNumber<Integer, Long, Float> add....
public RealNumber添加(N个){
返回添加(编号);
}
//注意这里的公众
公共重新分配编号添加(双倍编号){
返回新的实数(doubleValue()+数字);
}
//... 公共重新编号添加。。。。
在我的TestClass中编译失败->“add(Double)方法对于RealNumber类型是不明确的
最后,这起作用:

public RealNumber<N> add(Number number){
    return add(number);
}

//note the public here
public RealNumber<Double> add(Double number){
    return new RealNumber<Double>(doubleValue() + number);
}
//... public RealNumber<Integer, Long, Float> add....
public RealNumber添加(数字){
返回添加(编号);
}
//注意这里的公众
公共重新分配编号添加(双倍编号){
返回新的实数(doubleValue()+数字);
}
//…公共重新编号添加。。。。
但也带来了另外两个问题:这种模式允许向int添加double(这会导致整数的RealNumber),如果传递biginger、Byte或其他一些
数字,则会导致stackoverflower错误

所以我的主要问题是:

如果每个
add
方法都是公共的,如果它们是私有的,编译器为什么在Test.class中选择正确的方法


如何解决这些问题?

[对不起,我第一次尝试时没有完全理解这个问题。]


我不认为这里有一个简单的答案@Rafael,因为正如@Andrei Bodnarescu指出的,类型擦除意味着您在运行时没有
N
参数的类型。我认为您必须为
Number
的每个子类提供
add()
方法的具体实现

public RealNumber<Integer> add(Integer number) {
    return new RealNumber<Integer>(intValue() + number);
}
public RealNumber<Long> add(Long number) {
    return new RealNumber<Long>(longValue() + number);
}
public RealNumber add(整数){
返回新的RealNumber(intValue()+number);
}
公共重新分配编号添加(长编号){
返回新的实数(longValue()+数字);
}
如果您不想将整数添加到double,那么我想您需要执行以下操作:

public RealNumber<Integer> add(Integer number){
    if (!(this instanceof Integer)) {
        throw new IllegalArgumentException("You can't do this...");
    }
    return new RealNumber<Integer>(intValue() + number);
}
public RealNumber<N> add(N number,Class<N> numberClass){
        return add(number);
    }
public RealNumber add(整数){
如果(!(此整数实例)){
抛出新的IllegalArgumentException(“你不能这么做…”);
}
返回新的RealNumber(intValue()+number);
}
我看不出有什么简单的方法可以解决这个问题。

public RealNumber<N> add(N number){
        return add(number);
    }
public RealNumber添加(N个){
返回添加(编号);
}
方法总是调用自己,因为类型擦除:在Java中,泛型仅用于编译时,它们在运行时不再存在,因此VM实际上不知道类型N是什么,因此它调用可用的最通用的方法,即此方法。您还必须将类型作为类作为参数传递给方法,类似于:

public RealNumber<Integer> add(Integer number){
    if (!(this instanceof Integer)) {
        throw new IllegalArgumentException("You can't do this...");
    }
    return new RealNumber<Integer>(intValue() + number);
}
public RealNumber<N> add(N number,Class<N> numberClass){
        return add(number);
    }
public RealNumber add(N号,类号Class){
返回添加(编号);
}

Java不允许您使用不同的返回值重写方法。如果您想要另一个
add
方法返回
RealNumber
,那么我将其称为
addReal()
或其他什么。对于float和double,您可以使用
doubleValue()
对于int和long,您可以使用
longValue()
对于
int
您也可以使用
doubleValue()
除非您需要准确地表示所有
值,否则您可以使用
double
double
,如果它们需要准确,您可以使用
bigdecimic
@Gray,我不能将其命名为addReal,因为这样我就没有重载。第二个区别是add(Number)和add(N Number)出于同样的原因,这也不起作用。类型擦除不会调用正确的
add(Integer…
或其他方法