JAVA

Java 기본 자료형과 객체형 변수 완전 정복: 선언부터 초기화까지 실전 가이드

CodeByJin 2025. 9. 6. 08:03
반응형

Java 프로그래밍에서 변수는 데이터를 저장하는 핵심 요소입니다. 하지만 많은 초보 개발자들이 기본 자료형(Primitive Type)과 객체형 변수(Object Type)의 차이점을 제대로 이해하지 못해 메모리 관리나 성능 최적화에서 어려움을 겪습니다. 이번 포스팅에서는 Java의 변수 시스템을 체계적으로 분석하고, 실무에서 바로 적용할 수 있는 선언과 초기화 방법을 상세히 다루어 보겠습니다.

Java 변수의 두 가지 세계: 기본 자료형 vs 객체형

기본 자료형(Primitive Types)의 특징
Java에서 기본 자료형은 사전에 정의된 8가지 데이터 타입으로, Java 언어의 기초를 이루는 핵심 요소입니다. 이들은 단순한 값을 저장하며, 객체가 아닌 실제 데이터 자체를 메모리에 직접 저장합니다.

8가지 기본 자료형의 완전한 분석

// 정수형 타입들    
byte smallNumber = 127;    // 8비트, -128 ~ 127    
short mediumNumber = 32767; // 16비트, -32,768 ~ 32,767    
int standardNumber = 2147483647; // 32비트, 가장 널리 사용    
long bigNumber = 9223372036854775807L; // 64비트, 큰 숫자용    
// 실수형 타입들
float floatValue = 3.14f;  // 32비트 단정밀도
double doubleValue = 3.14159265359; // 64비트 배정밀도

// 문자와 논리형
char character = 'A';      // 16비트 유니코드 문자
boolean isTrue = true;     // true 또는 false

기본 자료형의 핵심 특징을 살펴보면

  • null 값을 가질 수 없음: 항상 기본값을 가집니다
  • 스택 메모리에 직접 저장: 빠른 접근이 가능합니다
  • 메서드나 속성이 없음: 순수한 값만 저장합니다
  • 소문자로 시작: 모든 기본 타입명이 소문자입니다

객체형 변수(Reference Types)의 세계

객체형 변수는 사용자가 정의하거나 Java에서 제공하는 클래스의 인스턴스를 참조합니다. 이들은 실제 객체가 아닌 객체의 주소값(참조)을 저장합니다.

// 객체형 변수의 다양한 예시    
String name = "Java Programming";    
Integer wrapperInt = 100;    
ArrayList<String> list = new ArrayList<>();    
Scanner scanner = new Scanner(System.in);    

// 사용자 정의 클래스
class Person {
private String name;
private int age;

public Person(String name, int age) {    
    this.name = name;    
    this.age = age;    
}

}

Person developer = new Person("김개발", 30);

객체형 변수의 주요 특징

  • null 값 허용: 초기화하지 않으면 null이 기본값
  • 힙 메모리에 객체 저장: 참조값은 스택에, 실제 객체는 힙에
  • 메서드와 속성 보유: 다양한 기능을 제공
  • 대문자로 시작: 클래스명은 대문자로 시작

메모리 할당의 비밀: 스택 vs 힙

기본 자료형의 메모리 관리
기본 자료형 변수는 선언과 동시에 스택 메모리에 실제 값이 저장됩니다. 이는 매우 효율적인 메모리 사용 패턴을 보여줍니다.

public void primitiveMemoryExample() {    
    int a = 10;  // 스택에 10이 직접 저장    
    int b = a;   // 스택에 새로운 공간에 10이 복사됨    
    b = 20;      // b만 변경, a는 영향 없음    

System.out.println("a = " + a); // 출력: a = 10    
System.out.println("b = " + b); // 출력: b = 20

}

객체형 변수의 메모리 구조
객체형 변수의 경우 스택에는 참조값, 힙에는 실제 객체가 저장되는 이중 구조를 가집니다.

public void referenceMemoryExample() {    
    // 스택: studentA (참조값), 힙: 실제 배열 객체    
    int[] studentA = {90, 85, 95};     
    int[] studentB = studentA;  // 같은 객체를 참조    
    studentB[0] = 100;  // 원본 배열 변경    

System.out.println("studentA[0] = " + studentA[0]); // 출력: 100    
System.out.println("studentB[0] = " + studentB[0]); // 출력: 100

}

이러한 메모리 구조의 차이는 성능과 메모리 사용량에 직접적인 영향을 미칩니다.

저장 위치스택 메모리스택(참조) + 힙(객체)
메모리 사용량적음상대적으로 많음
접근 속도빠름상대적으로 느림
가비지 컬렉션해당없음대상이 됨

변수 선언의 예술: 문법과 베스트 프랙티스

기본 선언 문법의 완전한 이해
Java에서 변수 선언은 데이터 타입과 변수명의 조합으로 이루어집니다.

// 기본 문법: [접근제한자] 데이터타입 변수명 [= 초기값];    
public class VariableDeclaration {    
    // 인스턴스 변수 (필드)    
    private int instanceVar;    
    public String publicField;    
    
    // 클래스 변수 (정적 변수)    
    public static final int CONSTANT_VALUE = 100;    
    private static double classVariable = 3.14;    
    
    public void methodExample() {    
        // 지역 변수    
        int localInt = 50;    
        String localString = "Local Variable";    
            
        // 반복문에서의 변수 선언    
        for (int i = 0; i < 10; i++) {    
            // i는 이 블록 내에서만 유효    
        }    
    }

}

변수명 작성 규칙의 실전 적용

Java에서는 엄격한 변수명 규칙을 따라야 합니다.

필수 규칙들

// ✅ 올바른 변수명    
int age = 25;    
int _privateVar = 10;    
int $dollarSign = 100;    
int myVeryLongVariableName123 = 0;    

// ❌ 잘못된 변수명
// int 2invalid = 10;     // 숫자로 시작 불가
// int my var = 20;       // 공백 포함 불가
// int class = 30;        // 예약어 사용 불가
// int my-variable = 40;  // 하이픈 사용 불가

권장 네이밍 컨벤션

// camelCase 사용    
int studentAge = 20;    
String firstName = "홍길동";    
boolean isDataValid = true;    

// 상수는 대문자와 언더스코어
public static final int MAX_RETRY_COUNT = 3;
public static final String DEFAULT_ENCODING = "UTF-8";

// 의미 있는 이름 사용
int userCount = 0;        // ✅ 명확함
int x = 0;               // ❌ 의미 불분명

// 부울린 변수는 is/has/can으로 시작
boolean isLoggedIn = false;
boolean hasChildren = true;
boolean canEdit = false;

초기화 전략: 안전하고 효율적인 방법들

선언과 초기화의 타이밍
변수의 선언과 초기화 시점은 코드의 가독성과 성능에 큰 영향을 미칩니다.

public class InitializationStrategies {    
    // 1. 선언과 동시에 초기화 (권장)    
    public void immediateInitialization() {    
        int count = 0;              // ✅ 즉시 초기화    
        String message = "Hello";   // ✅ 명확한 초기값    
        boolean isActive = false;   // ✅ 기본값 설정    
    }    
    
    // 2. 조건부 초기화    
    public void conditionalInitialization(boolean condition) {    
        String result;  // 선언만    
            
        if (condition) {    
            result = "Success";    
        } else {    
            result = "Failed";    
        }    
        // 모든 경로에서 초기화 보장    
            
        System.out.println(result); // 안전하게 사용    
    }    
    
    // 3. 늦은 초기화 (필요시에만)    
    public void lazyInitialization() {    
        Scanner scanner = null;  // 일단 null로 초기화    
            
        try {    
            scanner = new Scanner(System.in);    
            // 필요한 시점에 초기화    
            String input = scanner.nextLine();    
        } finally {    
            if (scanner != null) {    
                scanner.close();    
            }    
        }    
    }

}

기본값과 초기화 패턴
Java에서 변수들은 컨텍스트에 따라 다른 기본값을 가집니다.

public class DefaultValues {    
    // 인스턴스 변수들은 자동으로 기본값을 가짐    
    private int intField;        // 0    
    private double doubleField;  // 0.0    
    private boolean boolField;   // false    
    private char charField;      // '\u0000' (null 문자)    
    private String stringField;  // null    
        
    public void localVariableExample() {    
        // 지역 변수는 반드시 초기화 필요    
        int localInt;    
        // System.out.println(localInt); // ❌ 컴파일 에러!    
            
        localInt = 10; // 초기화 후 사용 가능    
        System.out.println(localInt); // ✅ 정상 동작    
    }    
    
    // 배열 초기화의 다양한 방법    
    public void arrayInitialization() {    
        // 방법 1: 선언과 동시에 초기화    
        int[] numbers1 = {1, 2, 3, 4, 5};    
            
        // 방법 2: new 키워드 사용    
        int[] numbers2 = new int[]{1, 2, 3, 4, 5};    
            
        // 방법 3: 크기만 지정 (기본값으로 초기화)    
        int[] numbers3 = new int[5]; // 모두 0으로 초기화    
            
        // 방법 4: 동적 초기화    
        int[] numbers4 = new int[5];    
        for (int i = 0; i < numbers4.length; i++) {    
            numbers4[i] = i * 2;    
        }    
    }

}

래퍼 클래스: 기본 타입과 객체의 가교

래퍼 클래스의 필요성과 활용
Java는 모든 기본 자료형에 대응하는 래퍼 클래스를 제공합니다. 이는 객체가 필요한 상황에서 기본 타입을 사용할 수 있게 해주는 핵심 메커니즘입니다.

public class WrapperClassDemo {    
    public void wrapperBasics() {    
        // 기본 타입 → 래퍼 클래스 대응표    
        byte b = 10;        Byte wrapperByte = b;    
        short s = 100;      Short wrapperShort = s;    
        int i = 1000;       Integer wrapperInt = i;    
        long l = 10000L;    Long wrapperLong = l;    
        float f = 3.14f;    Float wrapperFloat = f;    
        double d = 3.14159; Double wrapperDouble = d;    
        char c = 'A';       Character wrapperChar = c;    
        boolean bool = true; Boolean wrapperBool = bool;    
    }    
    
    // 컬렉션에서의 필수 활용    
    public void collectionUsage() {    
        // ❌ 컬렉션에는 기본 타입 사용 불가    
        // ArrayList intList = new ArrayList();    
            
        // ✅ 래퍼 클래스 사용 필수    
        ArrayList integerList = new ArrayList<>();    
        integerList.add(10);    // 오토박싱    
        integerList.add(20);    
            
        int value = integerList.get(0); // 오토언박싱    
        System.out.println("첫 번째 값: " + value);    
    }    
    
    // 유틸리티 메서드 활용    
    public void utilityMethods() {    
        // 문자열 → 숫자 변환    
        String numberStr = "12345";    
        int number = Integer.parseInt(numberStr);    
        Integer wrapperNumber = Integer.valueOf(numberStr);    
            
        // 진법 변환    
        String binaryStr = Integer.toBinaryString(255);  // "11111111"    
        String hexStr = Integer.toHexString(255);        // "ff"    
            
        // 최대값, 최소값 확인    
        System.out.println("int 최대값: " + Integer.MAX_VALUE);    
        System.out.println("int 최소값: " + Integer.MIN_VALUE);    
            
        // null 처리 가능    
        Integer nullableInt = null;  // 기본 타입으로는 불가능    
        if (nullableInt != null) {    
            System.out.println("값: " + nullableInt);    
        }    
    }

}

오토박싱과 언박싱의 내부 동작
Java 5부터 도입된 오토박싱(Autoboxing)과 언박싱(Unboxing)은 기본 타입과 래퍼 클래스 간의 자동 변환을 제공합니다.

public class AutoBoxingDemo {    
    public void autoBoxingExamples() {    
        // 오토박싱: 기본 타입 → 래퍼 클래스    
        Integer autoBoxed = 100;  // new Integer(100)과 동일    
        Double autoBoxedDouble = 3.14; // new Double(3.14)와 동일    
            
        // 언박싱: 래퍼 클래스 → 기본 타입    
        int unboxed = autoBoxed;  // autoBoxed.intValue()와 동일    
        double unboxedDouble = autoBoxedDouble; // doubleValue() 호출    
            
        // 연산에서의 자동 변환    
        Integer a = 10;    
        Integer b = 20;    
        int sum = a + b;  // 자동으로 언박싱되어 계산    
            
        // 메서드 호출에서의 변환    
        printInteger(50);      // int → Integer 자동 변환    
        int result = getInteger(); // Integer → int 자동 변환    
    }    
    
    public void printInteger(Integer value) {    
        System.out.println("Integer 값: " + value);    
    }    
    
    public Integer getInteger() {    
        return 100;    
    }    
    
    // 성능 주의사항    
    public void performanceConsiderations() {    
        // ❌ 반복문에서의 불필요한 박싱/언박싱    
        Integer sum = 0;    
        for (int i = 0; i < 1000000; i++) {    
            sum += i;  // 매번 박싱/언박싱 발생    
        }    
            
        // ✅ 개선된 버전    
        int primitiveSum = 0;    
        for (int i = 0; i < 1000000; i++) {    
            primitiveSum += i;  // 기본 타입으로 고속 연산    
        }    
        Integer finalSum = primitiveSum; // 최종에만 박싱    
    }

}

실전 활용 패턴과 성능 최적화

변수 스코프와 생명주기 관리
변수의 스코프(범위)를 적절히 관리하는 것은 메모리 효율성과 코드 가독성에 중요합니다.

public class ScopeManagement {    
    private int instanceVariable = 100;  // 인스턴스 생명주기와 동일    
    private static int classVariable = 200; // 클래스 로딩부터 프로그램 종료까지    
    
    public void scopeExample() {    
        int methodVariable = 300;  // 메서드 실행 동안만 유효    
            
        if (methodVariable > 0) {    
            int blockVariable = 400;  // 이 블록 내에서만 유효    
                
            // 모든 변수에 접근 가능    
            System.out.println("Instance: " + instanceVariable);    
            System.out.println("Class: " + classVariable);    
            System.out.println("Method: " + methodVariable);    
            System.out.println("Block: " + blockVariable);    
        }    
            
        // blockVariable은 여기서 접근 불가    
        // System.out.println(blockVariable); // 컴파일 에러    
            
        // 루프 변수의 스코프    
        for (int i = 0; i < 3; i++) {    
            int loopLocal = i * 10;    
            System.out.println("Loop: " + loopLocal);    
        }    
        // i와 loopLocal 모두 여기서 접근 불가    
    }    
    
    // 변수 선언 위치 최적화    
    public void optimizedVariableDeclaration() {    
        // ✅ 사용 직전에 선언 (권장)    
        if (needsProcessing()) {    
            String processResult = performHeavyCalculation();    
            handleResult(processResult);    
        }    
            
        // ❌ 너무 이른 선언 (비권장)    
        // String processResult = null;    
        // ... 많은 코드 ...    
        // if (needsProcessing()) {    
        //     processResult = performHeavyCalculation();    
        // }    
    }    
    
    private boolean needsProcessing() { return true; }    
    private String performHeavyCalculation() { return "result"; }    
    private void handleResult(String result) { /* 처리 로직 */ }

}

메모리 효율적인 변수 사용 전략
메모리 사용량을 최적화하기 위한 실전 전략들을 살펴보겠습니다.

public class MemoryOptimization {    
    // 1. 적절한 데이터 타입 선택    
    public void chooseRightDataTypes() {    
        // 작은 값은 작은 타입 사용    
        byte smallCounter = 10;     // 1바이트    
        short mediumCounter = 1000; // 2바이트    
        // int largeCounter = 10;   // 4바이트 (불필요하게 큰 타입)    
            
        // 대용량 배열에서는 메모리 절약이 중요    
        byte[] largeFlagArray = new byte[1000000]; // 1MB    
        // int[] largeFlagArray = new int[1000000]; // 4MB (4배 더 큼)    
    }    
    
    // 2. 객체 재사용 패턴    
    public class ObjectReuse {    
        private StringBuilder reusableBuilder = new StringBuilder();    
            
        public String formatMessage(String name, int count) {    
            // 매번 새 StringBuilder 생성 대신 재사용    
            reusableBuilder.setLength(0); // 내용 초기화    
            reusableBuilder.append("User: ").append(name)    
                          .append(", Count: ").append(count);    
            return reusableBuilder.toString();    
        }    
    }    
    
    // 3. 컬렉션 크기 미리 지정    
    public void preAllocateCollections() {    
        // ❌ 기본 크기로 시작 (빈번한 재할당 발생)    
        ArrayList<String> inefficient = new ArrayList<>();    
            
        // ✅ 예상 크기로 미리 할당    
        ArrayList<String> efficient = new ArrayList<>(1000);    
            
        // HashMap도 동일한 원리    
        HashMap<String, Integer> preAllocatedMap = new HashMap<>(1000, 0.75f);    
    }    
    
    // 4. null 체크와 방어적 프로그래밍    
    public void defensiveProgramming() {    
        String userInput = getUserInput();    
            
        // ✅ null 체크 후 사용    
        if (userInput != null && !userInput.isEmpty()) {    
            String processedInput = userInput.trim().toLowerCase();    
            handleValidInput(processedInput);    
        } else {    
            handleInvalidInput();    
        }    
            
        // Optional을 활용한 null 안전성    
        Optional<String> optionalInput = Optional.ofNullable(userInput);    
        optionalInput.filter(s -> !s.isEmpty())    
                    .map(String::trim)    
                    .map(String::toLowerCase)    
                    .ifPresentOrElse(    
                        this::handleValidInput,    
                        this::handleInvalidInput    
                    );    
    }    
    
    private String getUserInput() { return null; }    
    private void handleValidInput(String input) { }    
    private void handleInvalidInput() { }

}

실무에서의 변수 관리 베스트 프랙티스

코드 품질을 높이는 변수 활용법
실제 프로젝트에서 활용할 수 있는 변수 관리 기법들을 정리해보겠습니다.

public class PracticalVariableManagement {    
    // 1. 상수를 활용한 매직 넘버 제거    
    private static final int MAX_RETRY_ATTEMPTS = 3;    
    private static final long TIMEOUT_MILLISECONDS = 5000L;    
    private static final String DEFAULT_CHARSET = "UTF-8";    
    
    // 2. 열거형을 활용한 상태 관리    
    public enum ProcessingState {    
        PENDING, PROCESSING, COMPLETED, FAILED    
    }    
    
    private ProcessingState currentState = ProcessingState.PENDING;    
    
    // 3. 불변 객체 패턴    
    public final class ImmutableUser {    
        private final String name;    
        private final int age;    
        private final List<String> hobbies;    
            
        public ImmutableUser(String name, int age, List<String> hobbies) {    
            this.name = name;    
            this.age = age;    
            // 방어적 복사로 불변성 보장    
            this.hobbies = Collections.unmodifiableList(new ArrayList<>(hobbies));    
        }    
            
        // getter 메서드들...    
        public String getName() { return name; }    
        public int getAge() { return age; }    
        public List<String> getHobbies() { return hobbies; }    
    }    
    
    // 4. 빌더 패턴을 활용한 객체 생성    
    public static class UserBuilder {    
        private String name;    
        private int age;    
        private String email;    
        private List<String> hobbies = new ArrayList<>();    
            
        public UserBuilder name(String name) {    
            this.name = name;    
            return this;    
        }    
            
        public UserBuilder age(int age) {    
            this.age = age;    
            return this;    
        }    
            
        public UserBuilder email(String email) {    
            this.email = email;    
            return this;    
        }    
            
        public UserBuilder addHobby(String hobby) {    
            this.hobbies.add(hobby);    
            return this;    
        }    
            
        public ImmutableUser build() {    
            // 유효성 검사    
            if (name == null || name.trim().isEmpty()) {    
                throw new IllegalArgumentException("이름은 필수입니다.");    
            }    
            if (age < 0 || age > 150) {    
                throw new IllegalArgumentException("나이가 유효하지 않습니다.");    
            }    
                
            return new ImmutableUser(name, age, hobbies);    
        }    
    }    
    
    // 5. 리소스 관리 패턴    
    public void resourceManagement() {    
        // try-with-resources 사용    
        try (Scanner scanner = new Scanner(System.in);    
             FileWriter writer = new FileWriter("output.txt")) {    
                
            String input = scanner.nextLine();    
            writer.write(input);    
                
        } catch (IOException e) {    
            System.err.println("파일 처리 중 오류: " + e.getMessage());    
        }    
        // 자동으로 리소스 해제됨    
    }

}

디버깅과 유지보수를 위한 변수 관리
코드의 유지보수성을 높이는 변수 관리 방법들을 알아보겠습니다.

public class DebuggingFriendlyCode {    
    private static final Logger logger = LoggerFactory.getLogger(DebuggingFriendlyCode.class);    
    
    // 1. 의미 있는 변수명과 주석    
    public double calculateTotalPrice(List<Product> products, Customer customer) {    
        double subtotalAmount = 0.0;    
        double discountAmount = 0.0;    
        double taxAmount = 0.0;    
            
        // 상품별 가격 합계 계산    
        for (Product product : products) {    
            subtotalAmount += product.getPrice() * product.getQuantity();    
        }    
            
        // 고객 등급별 할인 적용    
        if (customer.isPremiumMember()) {    
            discountAmount = subtotalAmount * 0.1; // 10% 할인    
        }    
            
        // 세금 계산 (할인 후 금액 기준)    
        double discountedAmount = subtotalAmount - discountAmount;    
        taxAmount = discountedAmount * 0.08; // 8% 부가세    
            
        double finalAmount = discountedAmount + taxAmount;    
            
        // 디버깅을 위한 로깅    
        logger.debug("가격 계산 상세: 소계={}, 할인={}, 세금={}, 최종={}",    
                    subtotalAmount, discountAmount, taxAmount, finalAmount);    
            
        return finalAmount;    
    }    
    
    // 2. 검증과 예외 처리    
    public void validateAndProcess(String input) {    
        // 전제조건 검사    
        Objects.requireNonNull(input, "입력값은 null일 수 없습니다");    
            
        String trimmedInput = input.trim();    
        if (trimmedInput.isEmpty()) {    
            throw new IllegalArgumentException("입력값이 비어있습니다");    
        }    
            
        // 상태 변수로 처리 과정 추적    
        ProcessingState state = ProcessingState.PENDING;    
            
        try {    
            state = ProcessingState.PROCESSING;    
            String processedData = performComplexProcessing(trimmedInput);    
                
            state = ProcessingState.COMPLETED;    
            logger.info("처리 완료: 입력길이={}, 출력길이={}",     
                       trimmedInput.length(), processedData.length());    
                
        } catch (Exception e) {    
            state = ProcessingState.FAILED;    
            logger.error("처리 실패: 상태={}, 입력={}", state, trimmedInput, e);    
            throw e;    
        }    
    }    
    
    private String performComplexProcessing(String input) {    
        // 복잡한 처리 로직    
        return input.toUpperCase();    
    }    
    
    // 3. 테스트 친화적 코드    
    public static class TestableCalculator {    
        private final double taxRate;    
        private final double discountRate;    
            
        public TestableCalculator(double taxRate, double discountRate) {    
            this.taxRate = taxRate;    
            this.discountRate = discountRate;    
        }    
            
        public double calculate(double baseAmount) {    
            // 중간 계산값들을 명확히 분리    
            double discountedAmount = baseAmount * (1 - discountRate);    
            double finalAmount = discountedAmount * (1 + taxRate);    
                
            return Math.round(finalAmount * 100.0) / 100.0; // 소수점 2자리로 반올림    
        }    
    }

}

// 보조 클래스들
class Product {
    private final String name;
    private final double price;
    private final int quantity;

    public Product(String name, double price, int quantity) {    
        this.name = name;    
        this.price = price;    
        this.quantity = quantity;    
    }    
    
    public double getPrice() { return price; }    
    public int getQuantity() { return quantity; }

}

class Customer {
    private final boolean isPremium;

    public Customer(boolean isPremium) {    
        this.isPremium = isPremium;    
    }    
    
    public boolean isPremiumMember() { return isPremium; }

}

Java 변수 마스터가 되는 길

Java에서 기본 자료형과 객체형 변수의 차이를 이해하는 것은 효율적인 프로그래밍의 첫걸음입니다. 기본 자료형은 빠른 성능과 적은 메모리 사용량이라는 장점을 제공하며, 객체형 변수는 풍부한 기능과 유연성을 제공합니다.

핵심 포인트 정리
메모리 관리 측면에서 기본 자료형은 스택에 직접 저장되어 빠른 접근이 가능하며, 객체형 변수는 힙과 스택을 함께 사용하는 복합 구조를 가집니다.

실무 활용에서는 상황에 맞는 적절한 타입 선택이 중요합니다. 성능이 중요한 반복문에서는 기본 자료형을, 컬렉션이나 null 처리가 필요한 경우에는 래퍼 클래스를 활용하는 것이 좋습니다.

변수 선언과 초기화는 코드의 안전성과 가독성에 직결됩니다. 사용 직전 선언, 즉시 초기화, 의미 있는 네이밍이라는 세 가지 원칙을 지키면 유지보수하기 좋은 코드를 작성할 수 있습니다.

이러한 기본기를 탄탄히 다지면, 복잡한 Java 애플리케이션을 개발할 때도 메모리 효율성과 성능 최적화를 동시에 고려한 코드를 작성할 수 있을 것입니다. Java 프로그래밍의 여정에서 변수 관리는 단순해 보이지만 가장 중요한 기초 소양이라는 점을 잊지 마시기 바랍니다.

자바 String 문자열의 불변성(immutable) 이해하기: 완벽 가이드

자바를 공부하다 보면 가장 먼저 마주하게 되는 흥미로운 개념 중 하나가 바로 String의 불변성(Immutable)입니다. 많은 개발자들이 "분명히 문자열을 변경했는데 왜 불변이라고 하지?"라는 의문을

byteandbit.tistory.com

반응형