2010-04-27 5 views
30

두 개의 숫자가 있습니다. 예 :두 개의 java.lang.Numbers를 추가하는 방법?

Number a = 2; 
Number b = 3; 
//Following is an error: 
Number c = a + b; 

Numbers에서 산술 연산이 지원되지 않는 이유는 무엇입니까? 어쨌든 자바에서이 두 숫자를 어떻게 추가할까요? (물론 나는 어딘가에서 그것들을 얻는다. 그리고 그들이 Integer인지 float인지 모른다.).

+0

이 실제로 그런 식으로 할당 (스몰 토크 addtition 구현을 살펴)하는 것? 내 말은, Number a = primitiveNumber가 유효한 것입니까? "something extends Number"를 반환하는 some 메서드에서 반환하는 경우 반환 된 Number가 instanceof Double 또는 Float인지 BigDecimal인지 여부를 실제로 확인할 수 있습니다. – Tedil

+0

@Tedil 예 "autoboxing"이라고 알려진 기능 덕분에 Java 1.5부터 이러한 종류의 할당이 가능합니다.원시 숫자 '2'는'int'이며, 이는'Number'의 서브 클래스 인'Integer'에 묶여 있습니다. –

+0

오버로드 된 메서드도 사용할 수 있습니다. 모든 경우에 적용됨 – Mob

답변

18

을 당신은 당신의 숫자가 정수 또는 부동 있는지 알 수없는 말을 .. . Number 클래스를 사용할 때 컴파일러는 숫자가 정수, 부동 또는 s인지 여부도 알 수 없습니다 오메 다른 것. 결과적으로 +와 - 같은 기본 수학 연산자는 작동하지 않습니다. 컴퓨터는 값을 처리하는 방법을 모릅니다.

토론을 바탕으로

START 편집, 내가 예를 들어 도움이 될 생각했다. 컴퓨터는 부동 소수점 숫자를 계수와 지수의 두 부분으로 저장합니다. 그러므로 이론적 인 시스템에서 001110은 0011 10 또는 3 = 9로 나눌 수 있습니다. 그러나 양의 정수는 이진수로 숫자를 저장하므로 001110은 2 + 4 + 8 = 14를 의미 할 수도 있습니다. 클래스를 사용할 때 Number의 경우 컴퓨터가 부동 소수점인지 int인지 또는 무엇인지 알 수 없으므로 001110을 알고 있지만 9 또는 14 또는 다른 값을 의미하는지 알 수 없습니다.

당신이 할 수있는 것은 작은 가정을하고 계산을 수행 할 유형 중 하나에 변환입니다 END 편집. 당신이 의심되는 경우 그래서 당신은 '

Number c = a.intValue() + b.intValue(); 

이있는 당신은뿐만 아니라

Integer c = a.intValue() + b.intValue(); 
일부 반올림 오류를 고통을 기꺼이 경우

, 또는

Float c = a.floatValue() + b.floatValue(); 

로 전환 할 수있을 수 정수를 다루지 않고 사소한 정밀도 문제는 괜찮습니다. 오히려 성능이 약간 타격 대신 해당 오류를 취할 것입니다 경우 또는

BigDecimal c = new BigDecimal(a.floatValue()).add(new BigDecimal(b.floatValue())); 
+1

거의 옳습니다. 그러나 나는 동의하지 않는다 "... 그것은 그것이 001110을 가지고있다. 그러나 그것이 9 또는 14 또는 다른 어떤 가치를 의미하는지 안다."는 것을 알고있다. Java HAS 런타임 유형 정보. Java는 Number 객체의 런타임 유형이 Integer인지 Double인지 여부를 알 수 있습니다. 이론적으로 유형을 구별하고 public number plus (Number a, Number b) {if (a instanceof Integer && b instanceof Integer) {새로운 정수 (a.intValue + b.intValue();}를 반환 할 수 있습니다. 등등 ... – fjf2002

7

java.lang.Number은 기본 유형의 모든 래퍼 클래스의 수퍼 클래스입니다 (java doc 참조). 목적에 맞는 적절한 기본 유형 (double, int 등) 또는 해당 래퍼 클래스 (Double, Integer 등)를 사용하십시오.

이 고려 다음

Number a = 1.5; // Actually Java creates a double and boxes it into a Double object 
Number b = 1; // Same here for int -> Integer boxed 

// What should the result be? If Number would do implicit casts, 
// it would behave different from what Java usually does. 
Number c = a + b; 

// Now that works, and you know at first glance what that code does. 
// Nice explicit casts like you usually use in Java. 
// The result is of course again a double that is boxed into a Double object 
Number d = a.doubleValue() + (double)b.intValue(); 
+2

이 점을 이해합니다. 그러나 이상하게도 Number 클래스 자체에서 직접 지원되지 않습니다. – amit

+0

@ amit.dev 모든 하위 클래스가 원하는대로 구현할 수있는 것은 아닙니다. 특히 Atomic 유형의 경우 유용한 계약을 정의하는 것이 어렵습니다. 더하다. 그리고 Short.add (Long)도 문제를 일으킬 수밖에 없습니다. – extraneon

+1

@ amit.dev : 직접 지원해야하는 이유는 무엇입니까? 추가 할 유형의 모든 순열에 대해 이상한 암시 적 캐스트 또는 연산자 오버로드를 지원하도록 Java를 요구하기 때문에 이는 의미가 없습니다. 내 대답에 예제 코드를 추가했습니다. 어쩌면 그것으로 인해 더 명확 해집니다. –

3

사용 :

Number c = a.intValue() + b.intValue(); // Number is an object and not a primitive data type. 

또는 :

int a = 2; 
int b = 3; 
int c = 2 + 3; 
+8

intValue()는 Double, Long 또는 BigDecimal에서 너무 잘 작동하지 않습니다. – Thilo

0

Number 당신의 인스턴스를 만들 수없는 abstract 클래스입니다. 올바른 인스턴스가 있으면 number.longValue() 또는 number.intValue()을 입력하여 추가 할 수 있습니다.

0

우선 Number가 추상 클래스라는 사실을 알고 있어야합니다.여기에서 일어나는 일은 2와 3을 만들 때, 그것들은 프리미티브로 해석되고 그 경우에는 서브 타입이 생성됩니다 (저는 정수라고 생각합니다). Integer는 Number의 하위 유형이므로 새로 작성된 Integer를 Number 참조로 지정할 수 있습니다.

그러나 숫자는 단지 추상화에 불과합니다. 정수 일 수도 있고 부동 소수점 일 수도 있습니다. 따라서 수학 연산의 의미가 모호합니다.

번호는 두 가지 이유로 고전 맵 오퍼레이션을 제공하지 않습니다

첫째, 자바 멤버 방법이 될 수 없습니다 연산자를. 그것은 C++이 아닙니다. 기껏해야 add()를 제공 할 수 있습니다.

둘째, 두 입력 (예 : int로 나누기)이있을 때 수행 할 작업 유형을 파악하는 것은 매우 까다 롭습니다.

그래서 대신 관심있는 특정 원시 유형으로 변환하고 수학 연산자를 적용하는 것은 사용자의 책임입니다.

+0

틀린, 당신은 추상 클래스의 인스턴스를 생성 할 수 없다. – Cam

+1

@incrediman : 내가 추상 클래스의 인스턴스를 생성하고 있음을 나타내 었는가? 나는 정수가 생성 된 후 숫자 참조. – Uri

+0

@incrediman, 사실, 추상 클래스에 대한 참조를 선언하고 기존 객체를 가리키는 것은 합법적이며, 추상 클래스의 새 인스턴스를 선언 할 수는 없습니다. – Pops

2

질문에 양면이 있다고 생각합니다.

번호에 연산자가 지원되지 않는 이유는 무엇입니까?

Java 언어 사양 이것을 지정하지 않으며 연산자 오버로딩이 없습니다. 또한 Number를 일부 기본 유형으로 변환하는 컴파일 타임 자연스러운 방법이 없으며 일부 유형의 연산을 정의하기위한 자연스러운 추가가 없습니다.

Number에서 기본 산술 연산이 지원되지 않는 이유는 무엇입니까? 내 댓글 :

에서 복사

(모든 서브 클래스는 당신이 기대하는 방식으로이를 구현할 수 없습니다. 특히 Atomic 유형의 경우 유용한 계약을 정의하는 것이 어렵습니다. 더하다.

또한 Short에 Long을 추가하려고하면 메서드 추가가 문제가됩니다.

7

또한 추가 작업을 처리하는 방법도 있습니다. 지금은 이것이 성능에 미치는 영향을 알지 못하지만 BigDecimal을 사용하는 것보다 적을 것이라고 가정합니다. 상위를가의

public static Number addNumbers(Number a, Number b) { 
    if(a instanceof Double || b instanceof Double) { 
     return new Double(a.doubleValue() + b.doubleValue()); 
    } else if(a instanceof Float || b instanceof Float) { 
     return new Float(a.floatValue() + b.floatValue()); 
    } else if(a instanceof Long || b instanceof Long) { 
     return new Long(a.longValue() + b.longValue()); 
    } else { 
     return new Integer(a.intValue() + b.intValue()); 
    } 
} 
+0

당신은''를 끝내기 때문에'N a'의 타입 만 확인하면됩니다. – ndm13

+0

위의 코드 조각에서 @ ndm13 나는 마녀 메서드에 사용할 형식 만 확인하고 있습니다. – SkidRunner

+0

대신에 a와 b의 유형을 모두 확인해야한다는 의미입니다. 제네릭은 같은 유형인지 확인하기 때문에 확인 만하면됩니다. – ndm13

8

유일한 방법은 정확하게 어떤 두 가지 유형을 추가합니다 : 이것은 심지어 다른 숫자 형을 가진 두 개의 인수 작동

Number a = 2f; // Foat 
Number b = 3d; // Double 
Number c = new BigDecimal(a.toString()).add(new BigDecimal(b.toString())); 

. number 형의 toString()가 정밀도를 떨어 뜨리지 않는 한, overflow 나 정밀도를 잃는 것과 같은 부작용을 일으키지 않습니다 (should?).

+1

클래스 만 BigDecimal.getPrimitiveType()을 사용하면 int.class 또는 double.class 또는 기타를 반환 할 수 있습니다. – Whimusical

0

가장 좋은 대답은 아래로 가장 알려진 유형의 이중 파견 시추와 util을 만들

관련 문제