각 데이터에 어울리는 타입을 고르는 연습입니다. ID와 타임스탬프는 long, 금액은 BigDecimal, 수량은 int.
import java.math.BigDecimal;
public class OrderInfo {
public static void main(String[] args) {
long orderId = 20260908_000123L; // 21억 초과 가능 → long
String customerName = "김민수";
int quantity = 3;
BigDecimal unitPrice = new BigDecimal("12900"); // 돈은 BigDecimal, 문자열로 생성
boolean isPaid = false;
char grade = 'B';
long orderedAt = System.currentTimeMillis(); // 밀리초 → long 필수
BigDecimal total = unitPrice.multiply(BigDecimal.valueOf(quantity));
System.out.println("주문번호: " + orderId);
System.out.println("고객: " + customerName + " (" + grade + "등급)");
System.out.println("금액: " + unitPrice + " x " + quantity + " = " + total);
System.out.println("결제여부: " + isPaid);
System.out.println("타임스탬프 자릿수: " + String.valueOf(orderedAt).length());
// 출력: 주문번호: 20260908000123
// 출력: 고객: 김민수 (B등급)
// 출력: 금액: 12900 x 3 = 38700
// 출력: 결제여부: false
// 출력: 타임스탬프 자릿수: 13
}
}각 타입의 최솟값·최댓값을 래퍼 클래스 상수로 확인하고, 클래스 필드는 초기화하지 않으면 기본값이 들어감을 확인합니다.
public class TypeRanges {
// 필드(클래스 멤버 변수)는 초기화 안 하면 기본값이 자동으로 들어감
static int defaultInt;
static double defaultDouble;
static boolean defaultBoolean;
static char defaultChar;
static String defaultString; // 참조 타입은 null
public static void main(String[] args) {
System.out.println("byte : " + Byte.MIN_VALUE + " ~ " + Byte.MAX_VALUE);
System.out.println("short : " + Short.MIN_VALUE + " ~ " + Short.MAX_VALUE);
System.out.println("int : " + Integer.MIN_VALUE + " ~ " + Integer.MAX_VALUE);
System.out.println("long : " + Long.MIN_VALUE + " ~ " + Long.MAX_VALUE);
System.out.println("float : " + Float.MIN_VALUE + " ~ " + Float.MAX_VALUE);
System.out.println("double: " + Double.MIN_VALUE + " ~ " + Double.MAX_VALUE);
System.out.println("char : " + (int) Character.MIN_VALUE + " ~ " + (int) Character.MAX_VALUE);
// 출력: byte : -128 ~ 127
// 출력: short : -32768 ~ 32767
// 출력: int : -2147483648 ~ 2147483647
// 출력: long : -9223372036854775808 ~ 9223372036854775807
// 출력: float : 1.4E-45 ~ 3.4028235E38
// 출력: double: 4.9E-324 ~ 1.7976931348623157E308
// 출력: char : 0 ~ 65535
System.out.println("기본값 int=" + defaultInt + " double=" + defaultDouble
+ " boolean=" + defaultBoolean + " char=[" + defaultChar + "] String=" + defaultString);
// 출력: 기본값 int=0 double=0.0 boolean=false char=[ ] String=null
}
}조회수 집계에서 int를 썼을 때 생기는 문제와 long/Math.addExact로 막는 방법입니다.
public class OverflowDemo {
public static void main(String[] args) {
int viewCount = Integer.MAX_VALUE;
System.out.println("현재 조회수: " + viewCount);
viewCount++;
System.out.println("1 증가 후: " + viewCount);
// 출력: 현재 조회수: 2147483647
// 출력: 1 증가 후: -2147483648
// 중간 계산 오버플로우
long wrong = 1_000_000 * 3_000; // int * int → int에서 이미 넘침
long right = 1_000_000L * 3_000; // long * int → long
System.out.println("wrong=" + wrong + " right=" + right);
// 출력: wrong=-1294967296 right=3000000000
// 명시적으로 잡기
try {
int safe = Math.addExact(Integer.MAX_VALUE, 1);
} catch (ArithmeticException e) {
System.out.println("오버플로우 감지: " + e.getMessage());
}
// 출력: 오버플로우 감지: integer overflow
}
}할인율 계산에서 정수 나눗셈, 캐스팅 순서, double 오차, BigDecimal 해법을 한 번에 비교합니다.
import java.math.BigDecimal;
import java.math.RoundingMode;
public class CastingDemo {
public static void main(String[] args) {
int sold = 37, total = 50;
System.out.println(sold / total); // 출력: 0 (정수 나눗셈)
System.out.println((double) sold / total); // 출력: 0.74
System.out.println((double) (sold / total)); // 출력: 0.0 (이미 늦음)
System.out.println(sold * 100 / total + "%"); // 출력: 74% (정수만으로 퍼센트)
double price = 12345.678;
System.out.println((int) price); // 출력: 12345 (버림)
System.out.println(Math.round(price)); // 출력: 12346 (반올림, long 반환)
System.out.println((int) -2.7); // 출력: -2 (0 방향)
// 부동소수점 오차
double a = 0.1, b = 0.2;
System.out.println(a + b); // 출력: 0.30000000000000004
System.out.println(a + b == 0.3); // 출력: false
// BigDecimal은 정확
BigDecimal x = new BigDecimal("0.1");
BigDecimal y = new BigDecimal("0.2");
System.out.println(x.add(y)); // 출력: 0.3
System.out.println(x.add(y).compareTo(new BigDecimal("0.3")) == 0); // 출력: true
// 10만원의 7.5% 부가세를 원 단위 반올림
BigDecimal amount = new BigDecimal("100000");
BigDecimal tax = amount.multiply(new BigDecimal("0.075")).setScale(0, RoundingMode.HALF_UP);
System.out.println("세금: " + tax); // 출력: 세금: 7500
// 자동 형변환 체인
byte by = 10;
short sh = by;
int in = sh;
long lo = in;
float fl = lo;
double db = fl;
System.out.println(db); // 출력: 10.0
// char ↔ int
char c = 'A';
int code = c;
char next = (char) (c + 1);
System.out.println(code + " " + next); // 출력: 65 B
}
}설정값을 상수로 빼고, 타입이 명백한 곳에서 var를 쓰는 실무 스타일입니다.
public class ConstantsAndVar {
static final int MAX_LOGIN_ATTEMPTS = 5;
static final double FREE_SHIPPING_THRESHOLD = 50_000.0;
static final String CURRENCY = "KRW";
public static void main(String[] args) {
var attempts = 0; // int
var orderAmount = 62_000.0; // double
var message = new StringBuilder(); // StringBuilder — 우변이 명백
attempts++;
System.out.println("시도 " + attempts + "/" + MAX_LOGIN_ATTEMPTS);
// 출력: 시도 1/5
var freeShipping = orderAmount >= FREE_SHIPPING_THRESHOLD; // boolean
message.append("주문 ").append(orderAmount).append(CURRENCY)
.append(freeShipping ? " (무료배송)" : " (배송비 3,000)");
System.out.println(message);
// 출력: 주문 62000.0KRW (무료배송)
// MAX_LOGIN_ATTEMPTS = 10; // 컴파일 오류: final 변수
// attempts = "many"; // 컴파일 오류: var는 int로 확정됨
}
}