자바 의 의혹 을 풀 면 얼마나 많은 것 을 알 수 있 습 니까?

8504 단어 자바
본 시리즈 의 내용 은 《 JAVA 해 혹 》 이라는 책 에서 유래 하 였 다.
수치 식
1. 패 리 티 판단
i% 2 = = 1 을 사용 하여 홀수 여 부 를 판단 하지 마 십시오. i 가 마이너스 홀수 일 때 성립 되 지 않 기 때문에 i% 2 를 사용 하 십시오! =0. 홀수 인지 아 닌 지 를 판단 하거나 사용 합 니 다.
고 효율 (i & 1)! =0 으로 판단 하 다.
2. 소수 정밀 계산
System.out.println(2.00 -1.10);//0.8999999999999999  

위의 계산 결 과 는 0.9 가 아니 라 일련의 소수 이다.문 제 는 1.1 이라는 숫자 가 double 로 정확하게 표시 되 지 않 기 때문에 표 시 됩 니 다.
그것 에 가장 가 까 운 double 값 으로 보 여 줍 니 다. 이 프로그램 이 2 에서 뺀 것 은 바로 이 값 입 니 다. 그러나 이 계산 결 과 는 0.9 에 가장 가 까 운 double 값 이 아 닙 니 다.
일반적으로 문 제 는 모든 소수 가 이 진 부동 소수점 으로 정확하게 표시 할 수 있 는 것 이 아니 라 는 점 이다.
이 진 부동 소수점 은 화폐 계산 에 매우 적합 하지 않다. 왜냐하면 1.0 을 10 의 다른 어떠한 마이너스 미터 로 표시 할 수 없 기 때문이다.
문 제 를 해결 하 는 첫 번 째 방식 은 화폐의 최소 단위 (분) 를 사용 하여 표시 하 는 것 이다.
System.out.println(200-110);//90  

두 번 째 방식 은 BigDecimal 을 사용 하 는 것 이지 만 BigDecimal (String) 구조 기 를 사용 해 야 하 며, BigDecimal (double) 로 구성 해 서 는 안 된다.
float 나 double 형 을 String 으로 바 꾸 고 BigDecimal (String) 을 사용 하여 구성 할 수도 없습니다. float 나 double 을 String 으로 바 꾸 고 있 기 때 문 입 니 다.
시간 정밀 도 를 잃 어 버 렸 다.예 를 들 어 new BigDecimal (0.1) 은 BigDecimal, 즉
0.1000000000000000000005551121257827021181583454115625, BigDecimal 을 정확하게 사용 하면 프로그램 이 우리 가 원 하 는 것 을 인쇄 할 수 있 습 니 다.
바라 보 는 결과 0.9:
System.out.println(new BigDecimal("2.0").subtract(new BigDecimal("1.10")));// 0.9

또 두 부동 소수점 크기 를 비교 하려 면 빅 데 시 멜 의 compare To 방법 을 사용 해 야 한다.
3. int 정수 곱 하기 넘 침
우 리 는 하루 의 초 수 를 계산한다.

long microsPerDay = 24 * 60 * 60 * 1000 * 1000;//       :86400000000  
System.out.println(microsPerDay);//     :500654080  

문 제 는 계산 과정 에서 넘 쳤 다 는 점 이다.이 계산식 은 완전히 int 연산 으로 실 행 된 것 이 며, 연산 이 끝 난 후에 야 그 결 과 는 향상 되 었 다.
long, 이 때 는 너무 늦 었 습 니 다. 계산 이 넘 쳤 습 니 다.
해결 방법 은 계산 식 의 첫 번 째 인 자 를 log 형 으로 명확 하 게 합 니 다. 그러면 표현 식 의 모든 후속 계산 을 log 연산 으로 강제 할 수 있 습 니 다. 이것 은
샘플 결 과 는 넘 치지 않 습 니 다.
long microsPerDay = 24L * 60 * 60 * 1000 * 1000;  

4. 음의 16 진법 과 8 진법 글자 상수
'숫자 상량' 의 유형 은 모두 int 형 이 고 그들 이 몇 진법 이 든 간 에 '2147483648', '0x 180000000 (16 진법, 총 33) 이다.
비트, 그래서 정수 의 수치 범 위 를 초과 하 였 습 니 다) "글자 의 상수 가 잘못 되 었 습 니 다. 컴 파일 할 때 int 의 수치 범 위 를 초과 하 였 으 므 로 log 로 표시 하 는 것 을 확인 해 야 합 니 다.
“2147483648L”、“0x180000000L”.
10 진 글자 의 상수 는 하나의 특성 만 있 습 니 다. 즉, 모든 10 진 글자 의 상수 가 양수 입 니 다. 마이너스 10 진 을 쓰 려 면 바른 10 진 이 필요 합 니 다.
상량 앞 에 '-' 를 붙 이면 된다.
16 진법 이나 8 진법 글자 의 상수 가 반드시 양수 나 음수 가 아니 라 플러스 인지 마이너스 인지 현재 상황 에 따라 보아 야 한다. 만약 16 진법 과 8 진법 글자 가
면 상수 의 최고 위 치 를 1 로 설정 하면 마이너스 입 니 다.

System.out.println(0x80);//128   
//0x81   int ,   ( 32 ) 0,       
System.out.println(0x81);//129   
System.out.println(0x8001);//32769  
System.out.println(0x70000001);//1879048193   
//   0x80000001 int ,   ( 32 ) 1,       
System.out.println(0x80000001);//-2147483647  
//   0x80000001L    long ,   ( 64 ) 0,       
System.out.println(0x80000001L);//2147483649  
//  int   
System.out.println(0x80000000);//-2147483648  
//    32 ,          L  long,         
System.out.println(0x8000000000000000L);//-9223372036854775808  

위 에서 알 수 있 듯 이 16 진법 의 글자 상수 가 int 형 을 나타 내 고 32 비트 를 넘 으 면 뒤에 'L' 을 추가 해 야 한다. 그렇지 않 으 면 컴 파일 할 수 없다.... 와 같다
과 가 32 이면 마이너스 int 양수 이 고 32 위 를 넘 으 면 long 형 이지 만 log 로 명확 하 게 지정 해 야 한다.
System.out.println(Long.toHexString(0x100000000L + 0xcafebabe));// cafebabe 

결 과 는 왜 0x1cafebabe 가 아 닙 니까?이 프로그램 이 실행 하 는 덧셈 은 혼합 형식의 계산 입 니 다. 왼쪽 조작 수 는 log 형 이 고 오른쪽 조작 수 는 int 형식 입 니 다.
.이 계산 을 실행 하기 위해 자바 는 int 형식의 수 치 를 원생 유형 을 넓 히 는 것 으로 log 형식 으로 변환 한 다음 에 두 개의 log 형식 수 치 를 더 합 니 다.... 때문에
int 는 기호 가 있 는 정수 형식 이기 때문에 이 변환 은 기호 확장 을 실행 합 니 다.
이 덧셈 의 오른쪽 동작 수 는 0xcafeabe 가 32 비트 로 log 형식의 수치 인 0xffffffffffffcafeabeL 로 올 라 간 후 이 수치 에 왼쪽 동작 을 더 했다.
0x100000000L 을 만들다.int 형식 으로 볼 때 기호 확장 을 거 친 후의 오른쪽 조작 수의 높이 는 - 1 이 고 왼쪽 조작 수의 32 위 는 1, 2 개 이다.
값 을 더 해서 0 을 얻 었 습 니 다:
  0x 0xffffffffcafebabeL
+0x 0000000100000000L
-----------------------------
0x 00000000cafebabeL
정확 한 결 과 를 얻 으 려 면 0x1cafebabe 를 두 번 째 조작 배열 에 'L' 을 더 해 정확 한 log 형 으로 명확 하 게 보면 된다. 이때 시 척 을 더 하면 된다.
전시 부 호 는 0:

System.out.println(Long.toHexString(0x100000000L + 0xcafebabeL));// 1cafebabe  

5. 좁은 숫자 형식 을 넓 은 형식 으로 올 릴 때 기호 비트 확장 을 사용 합 니까? 0 확장 을 사용 합 니까?
System.out.println((int)(char)(byte)-1);// 65535  

결 과 는 왜 65535 이지 - 1 이 아 닙 니까?
좁은 정형 을 넓 은 정형 으로 변환 할 때 기호 확장 규칙: 최초의 수치 유형 이 기호 가 있 으 면 기호 확장 을 실행 합 니 다 (즉, 기호 위치 가 있 으 면)
1 이면 1 로 확장 하고 0 이면 0 으로 확장 합 니 다).만약 그것 이 char 라면, 그것 이 어떤 유형 으로 향상 되 든 지 간 에 0 확장 을 실행 합 니 다.
위의 규칙 을 이해 한 후에 우 리 는 다시 미 제 를 살 펴 보 자. byte 는 기호 가 있 는 유형 이기 때문에 byte 수치 - 1 (바 이 너 리 는 11111111) 을 제시 하고 있다.
char 로 올 라 갈 때 기호 위치 확장 이 발생 하고 기호 위치 가 1 이 므 로 8 개 1 을 보충 하고 마지막 으로 16 개 1 이다.그리고 char 에서 int 로 올 라 갈 때
char 형 은 다른 유형 으로 향상 되 었 기 때문에 기호 확장 이 아 닌 0 확장 을 사용 하여 int 수 치 는 65535 가 되 었 습 니 다.
하나의 char 수치 c 를 너비 가 더 넓 은 유형 으로 바 꿀 때 0 으로 만 확장 되 지만 0 으로 확장 하려 는 의 도 를 분명하게 표현 하면 고려 할 수 있 습 니 다.
비트 마스크 사용 하기:
int i = c & 0xffff;//      :int i = c ;

만약 에 char 수치 c 를 너비 가 더 넓 은 정형 으로 바 꾸 고 기호 가 확장 되 기 를 원한 다 면 먼저 char 를 short 로 바 꾸 십시오.
char 는 같은 폭 을 가지 고 있 지만 기호 가 있 습 니 다.
int i = (short)c;  

byte 수치 b 를 char 로 바 꾸 고 기호 확장 을 원 하지 않 는 다 면 마스크 를 사용 하여 제한 해 야 합 니 다.
char c = (char)(b & 0xff);// char c = (char) b;      

6. ((byte)0x90 == 0x90)?
답 은 같 지 않다. 겉 으로 는 성립 된 것 처럼 보이 지만 그것 은 false 와 같다.byte 수치 (byte) 0x 90 과 int 수치 0x 90, Java 를 비교 하기 위해
원생 유형 을 넓 혀 서 byte 를 int 로 올 린 다음 에 이 두 int 수 치 를 비교 합 니 다.byte 는 기호 형식 이 있 기 때문에 이 변환 은 실 행 됩 니 다.
기호 확장, 마이너스 byte 수 치 를 숫자 적 으로 같은 int 값 (1001000 * 61664) 으로 올 립 니 다.이 예 에서 이 변환 은 (byte) 0x 90 을 int 수치 - 112 로 향상 시 킵 니 다. int 수치의 0x 90, 즉 + 144 와 같 지 않 습 니 다.
해결 방법: 기호 확장의 영향 을 제거 하기 위해 차단 코드 를 사용 하여 byte 를 int 로 변환 합 니 다.
((byte)0x90 & 0xff)== 0x90  

7. 삼원 식 (?:)

char x = 'X';  
int i = 0;  
System.out.println(true ? x : 0);// X  
System.out.println(false ? i : x);// 88 

조건 식 결과 형식의 규칙:
(1) 두 번 째 와 세 번 째 조작 수가 같은 유형 을 가지 고 있다 면 조건 식 의 유형 입 니 다.
(2) 만약 에 하나의 조작 유형 이 T 라면 T 는 byte, short 또는 char 를 나타 내 고 다른 조작 수 는 int 형식의 '글자 상수' 이 며
그 값 은 타 입 T 로 표시 할 수 있 습 니 다. 그 조건 식 의 타 입 은 T 입 니 다.
(3) 그렇지 않 으 면 조작 수 유형 을 향상 시 킬 것 이 고 조건 식 의 유형 은 두 번 째 와 세 번 째 조작 이 올 라 간 후의 유형 입 니 다.
현재 상기 규칙 을 사용 하여 위의 미 제 를 풀 고 있 습 니 다. 첫 번 째 표현 식 은 두 번 째 규칙 에 부합 합 니 다. 하나의 조작 수의 유형 은 char 이 고 다른 유형 은 글자 상 입 니 다.
양 이 0 인 int 형 이지 만 0 은 char 로 표시 할 수 있 기 때문에 최종 반환 유형 은 char 형식 을 기준 으로 합 니 다.두 번 째 표현 식 은 세 번 째 규칙 에 부합 합 니 다. i 는 int 이기 때 문 입 니 다.
형 변 수 는 x 가 char 형 변수 이기 때문에 x 를 int 형 으로 먼저 올 리 기 때문에 마지막 결과 유형 은 int 형 이지 만 i 를 final 로 정의 하면
결과 형식 을 char 로 되 돌려 줍 니 다. 이 때 두 번 째 규칙 에 부합 합 니 다. final 형식의 변 수 는 컴 파일 할 때 '글자 상수 0' 을 사용 하여 3 원 표를 교체 하기 때 문 입 니 다.
달 식:

final int i = 0;  
System.out.println(false ? i : x);// X 

JDK 1.4 버 전이 나 그 전에 조건 부 연산 자 는?:에서 두 번 째 와 세 번 째 조작 수가 인용 유형 일 때 조건 조작 자 는 그 중의 하 나 를 요구한다.
다른 하위 유형 이 어야 합 니 다. 같은 부류 가 있 을 까 봐 두 렵 습 니 다.

public class T {  
 public static void main(String[] args) {  
  System.out.println(f());  
 }  
 public static T f() {  
  // !!1.4    , 1.5    
  // !!return true?new T1():new T2();  
  return true ? (T) new T1() : new T2();// T1  
 }  
}  
  
class T1 extends T {  
 public String toString() {  
  return "T1";  
 }  
}  
  
class T2 extends T {  
 public String toString() {  
  return "T2";  
 }  
}  

5.0 이상 버 전에 서 조건 조작 자 는 두 번 째 와 세 번 째 조작 수 를 계속 할 때 항상 합 법 적 입 니 다.그 결과 유형 은 이 두 가지 유형 중 가장 좋다.
소공 초과.공공 초 류 는 항상 존재 합 니 다. Object 는 모든 대상 유형의 초 유형 이 고 위의 최소 공공 초 류 는 T 이기 때문에 컴 파일 할 수 있 습 니 다.
참고:http://jiangzhengjun.iteye.com/blog/652623

좋은 웹페이지 즐겨찾기