Итак, я прочитал обсуждение чисел здесь , потому что у меня похожая проблема.
В моем случае я хочу разрешить математические операции над числами. Моя идея заключалась в том, чтобы написать неизменный класс «RealNumber», который обрабатывает примитивные числа (целое, длинное, плавающее и двойное) без набора экземпляров элементов управления. Кто-то упомянул методы перегрузки и разрешил компилятору работать.
Это была моя первая попытка:
простой TestClass:
public class Test {
public static void main(String[] args) {
RealNumber<Double> d = RealNumber.create(3.4);
d.add(4.7);
}
}
Класс RealNumber: (пожалуйста, укажите метод с комментарием)
public class RealNumber<N extends Number> extends Number{
N number;
private RealNumber(N number){
if (number == null){
throw new NullPointerException("number is null");
}
this.number = number;
}
public N get(){
return number;
}
//note this Method
public RealNumber<N> add(N number){
return add(number);
}
private RealNumber<Integer> add(Integer number){
return new RealNumber<Integer>(intValue() + number);
}
private RealNumber<Long> add(Long number){
return new RealNumber<Long>(longValue() + number);
}
private RealNumber<Float> add(Float number){
return new RealNumber<Float>(floatValue() + number);
}
private RealNumber<Double> add(Double number){
return new RealNumber<Double>(doubleValue() + number);
}
@Override
public int intValue() {
return number.intValue();
}
@Override
public long longValue() {
return number.longValue();
}
@Override
public float floatValue() {
return number.floatValue();
}
@Override
public double doubleValue() {
return number.doubleValue();
}
public static final RealNumber<Integer> create(Integer number){
return new RealNumber<Integer>(number);
}
public static final RealNumber<Long> create(Long number){
return new RealNumber<Long>(number);
}
public static final RealNumber<Float> create(Float number){
return new RealNumber<Float>(number);
}
public static final RealNumber<Double> create(Double number){
return new RealNumber<Double>(number);
}
}
поэтому первый тест приводит меня к StackOverflowError, потому что метод «add» всегда вызывает сам себя.
вторая попытка (только измененные методы)
public RealNumber<N> add(Number number){
return add(number);
}
Во-первых, это не так хорошо, потому что это позволит добавлять BigDecimals или другие вещи, такие как Boolean, а во-вторых, приводит меня к той же StackOverflowError. поэтому я изменился:
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....
, который не компилируется в моем 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....
, но приносит еще 2 проблемы: этот шаблон позволяет добавить Doubles к Ints (что приводит к RealNumber of Integer) и приводит к StackOverflowError, если передается BigInteger, Byte или какой-либо другой Number
Итак, мои основные вопросы:
Почему компилятор выбирает правильный метод в Test.class, если каждый add
метод является открытым и завершается ошибкой, если он является закрытым.
Что я могу сделать, чтобы исправить проблемы?