backend
  • README
  • DOCS
    • Java Docs
    • Servlet Docs
    • JSP Docs
    • DB & SQL Docs
    • Spring Boot Docs
    • Spring Security Docs
    • AWS Docs
  • 설치하기
    • Intellij 설정
  • 자바
    • 01 Java란?
    • 02 자바 시작하기
    • 03 자료형과 연산자
    • 04 제어문
    • 05 메소드
    • 06 클래스 기초
      • Static 보충자료
      • 패키지 보충자료
    • 07 객체지향 프로그래밍
    • 08 클래스 더 알아보기
      • 열거형 ENUM 보충자료
    • 09 클래스와 자료형
      • 다형성 보충자료
      • 제네릭 보충자료
    • 10 컬렉션 프레임워크
      • 컬렉션 프레임워크 보충자료
    • 11 람다식과 함수형 프로그래밍
      • 람다식 보충자료
    • 12 오류 대비하기
      • 오류 보충자료
    • 13 멀티태스킹
      • 멀티태스킹 보충자료
    • 교재보충
      • java.lang
  • 스프링
    • 서블릿, JSP
      • 05 Servlet(서블릿)
        • 서블릿 보충자료
        • 서블릿 추가코드
        • XML, YAML, JSON
      • 06 JSP(자바 서버 페이지)
        • JSP 보충자료
      • 07 JSTL(JSP 스탠다드 태그 라이브러리)
        • JSTL 보충자료
      • 08 Cookie(쿠키), Session(세션)
      • 09 서블릿,필터,리스너
        • 서블릿,필터,리스너 보충자료
      • 11 도서관리 프로젝트 실습
    • Spring Boot
      • 01 스프링 등장 배경, 객체지향
        • 스프링 등장 배경, 객체지향 보충자료
      • 02 IOC(제어의 역전), DI(의존성 주입)
        • IOC 보충자료
        • DI 보충자료
      • 03 스프링 구조
        • 스프링 구조 보충설명
      • 04 테스트코드 실습
      • 05 스프링 빈 설정
        • 스프링 빈 설정 보충자료
      • 06 싱글톤
        • 싱글톤 보충 자료
      • 07 스프링 빈 자동설정
        • 스프링 빈 자동설정 보충자료
      • 08 빈 생명주기
        • 빈 생명주기 보충자료
      • 09 빈 스코프
        • 빈 스코프 보충자료
      • 10 스프링 MVC
        • 스프링 MVC 보충자료
        • 데이터베이스 연동에 필요한 부분
      • 11 Validation(검증)
        • Validation(검증) 보충자료
      • 12 Bean Validation(빈검증)
        • Bean Validation(빈검증) 보충자료
      • 13 예외처리
        • 예외처리 보충자료
      • 14 타입변환
      • 15 JDBC(Java Database Connectivity)
      • 16 커넥션풀
      • 17 트랜잭션
        • 트랜잭션 보충자료
      • 18 JDBC 템플릿 활용
      • 19 MyBatis
      • 20 JPA(Java Persistence API)
      • 22 게시판 프로젝트 실습
    • Spring Security
      • 보안(Security)
      • Spring Security
      • 2. Spring Security 알아보기
        • 보안 위협 실제 사례와 방어 전략
      • 3. Spring Security 기본 동작 흐름
      • 4. Spring Security로 인증 권한 추가하기
        • Spring Security의 인증 및 인가
      • 5. Spring Security에서 세션 관리하기
        • 세션(Session)과 쿠키(Cookie) 비교, 토큰(Token)과의 관계
        • 해싱 및 해싱알고리즘
        • base64
      • 6. Spring Security 악용 보호
        • SameSite
      • 7. Spring Security로 인가 권한 추가하기
      • 8. Bcrypt(비크립트) 암호화
      • OAuth2 적용하기
  • 네트워크
    • HTTP
    • OSI 7계층
  • DB&SQL
    • 01 Database(데이터베이스)와 SQL 개요
    • 02 관계형 모델
    • 03 집합
    • 04 JOIN 연산
    • 05 MySQL
      • 세이브포인트
      • DBeaver, Mysql 오토커밋 설정 관련
    • 06 SQL 기초
      • 예시데이터 쿼리문
    • 07 SQL 실습
      • 실습 스키마
    • 08 Join 활용
      • 실습스키마
    • 09 SQL 활용
      • 실습스키마
    • 10 정규화
      • 실습 스키마
    • 데이터타입
    • 예시 프로젝트 스키마 구성
  • AWS
    • SSL 연결하기
    • 보충설명
Powered by GitBook
On this page
  • 정수 자료형들과 관련 연산자
  • 정수형 (Integer Types)
  • 실수형 (Floating-point Types)
  • 산술 연산자 (Arithmetic Operators)
  • 예시
  • 대입 연산자 (Assignment Operators)
  • 단항연산자(Unary Operators
  • 관계 연산자 (Relational Operators)
  • 예시
  • 형변환
  • 1. 정수와 정수 연산 시 형변환
  • 예시:
  • 2. 정수와 실수 연산 시 형변환
  • 예시:
  • 3. 실수와 실수 연산 시 형변환
  • 예시:
  • 4. 명시적 형변환
  • 예시:
  • 요약
  • Boolean 자료형
  • boolean 자료형의 특징
  • 예시: boolean 변수 선언 및 초기화
  • boolean 자료형에서 사용하는 연산자
  • 1. 논리 AND (&&)
  • 2. 논리 OR (||)
  • 3. 논리 NOT (!)
  • 조건부 연산자 (Conditional Operators)
  • 예시
  • 문자 자료형
  • 1. 문자 자료형 (Character Type): char
  • 예시:
  • 2. 문자열 자료형 (String Type): String
  • 예시:
  • 3. ''와 ""의 차이
  • 차이 예시:
  • 이스케이프 문자열(Escape Sequences)
  • 자주 사용하는 이스케이프 문자열 목록
  • 예시 코드
  • 출력 결과
  • formatted()
  • 기본 구조
  • 예시
  • 문자열 포매팅
  • 실수 포매팅
  • 주요 포맷 지정자(Format Specifier)
  • 포맷 지정자와 옵션 사용
  • 1. 소수점 자릿수 지정
  • 2. 출력 너비 지정
  • 3. 좌측 정렬
  • formatted()의 장점
  • 정리
  • 문자열의 메소드
  • length()
  • isEmpty()
  • isBlank()
  • trim() 메소드
  • 예시:
  • charAt() 메소드
  • 구문:
  • 예시:
  • indexOf() 메소드
  • 구문:
  • 예시:
  • 주의사항:
  • lastIndexOf() 메소드
  • 구문:
  • 예시:
  • 주의사항:
  • 차이점:
  • equals() 메소드
  • 구문:
  • 예시:
  • 결과:
  • 주요 특징:
  • 대소문자 무시 비교: equalsIgnoreCase()
  • equals()와 ==의 차이:
  • contains() 메소드
  • 구문:
  • startsWith() 메소드
  • 구문:
  • endsWith() 메소드
  • 구문:
  • 출력 결과:
  • 설명:
  • 추가예제 (offset 활용)
  • compareTo() 메소드
  • 구문:
  • 예시:
  • 출력:
  • 설명:
  • 주요 특징:
  • 예시:
  • 활용
  • toUpperCase()
  • toLowerCase()
  • 주요 특징:
  • 결론:
  • null
  • 예시:
  • 비어있는 문자열 ("")
  • 예시:
  • 배열
  • 특징
  • 배열 선언 및 초기화
  • 1. 배열 선언
  • 2. 배열 초기화
  • 3. 선언과 동시에 초기화
  • 배열 요소 접근
  • 배열의 길이
  • 다차원 배열
  • 2차원 배열 선언 및 초기화:
  • 2차원 배열 요소 접근:
  • 배열의 장단점
  • 장점:
  • 단점:
  • 예제 코드
  • 출력:
  • 배열의 참조형 특성
  • 배열의 참조형 특성 주요 개념
  • 배열의 참조형 특성의 장단점
  • 배열 복사 (Array Copy)
  • 타입추론
  • var 키워드
  • 예시 : 타입 추론을 사용한 변수 선언
  • 제약사항
  • 예시: 잘못된 타입 추론 사용
  • 배열의 경우 초기화시 명시
  • 불가능한 방식
  • 올바른 방식
  • 불가능한 또 다른 예
  • 정리
  1. 자바

03 자료형과 연산자

정수 자료형들과 관련 연산자

정수형 (Integer Types)

Java는 네 가지 정수형을 제공합니다.

자료형
크기
값의 범위

byte

1바이트

-128 ~ 127

short

2바이트

-32,768 ~ 32,767

int

4바이트

-2,147,483,648 ~ 2,147,483,647

long

8바이트

-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807

  • 정수형은 소수점이 없는 정수를 저장할 때 사용됩니다.

byte smallNumber = 100;
short myShortNumber = 10000;
int myNumber = 100_000;
long bigNumber = 10_000_000_000L;  
// 'L'은 long 타입을 명시. int 범위를 넘었을 땐 'L' 쓰기
// _ 으로 가독성 높게 처리 가능

실수형 (Floating-point Types)

Java는 두 가지 실수형을 제공합니다:

자료형
크기
정밀도

float

4바이트

소수점 이하 약 6-7자리 정밀도

double

8바이트

소수점 이하 약 15자리 정밀도

  • 실수형은 소수점이 있는 숫자를 저장할 때 사용됩니다.

float pi = 3.14f;  // 'f'는 float 타입을 명시. f 붙이지 않으면 double 로 인식
double bigPi = 3.141592653589793;

산술 연산자 (Arithmetic Operators)

산술 연산자는 두 숫자 피연산자에 대해 기본적인 산술 계산을 수행합니다.

부수효과를 일으키지 않습니다.

연산자
이름
설명

+

덧셈

두 피연산자를 더합니다.

-

뺄셈

첫 번째 피연산자에서 두 번째를 뺍니다.

*

곱셈

두 피연산자를 곱합니다.

/

나눗셈

첫 번째 피연산자를 두 번째로 나눕니다. 정수 나눗셈의 경우 소수점 이하를 버립니다.

%

나머지 (모듈로)

첫 번째 피연산자를 두 번째로 나눈 나머지를 반환합니다.

예시

ArithmeticOperatorsExample.java

public class ArithmeticOperatorsExample {
    public static void main(String[] args) {
        int a = 15;
        int b = 4;

        System.out.println("a + b = " + (a + b)); // 19
        System.out.println("a - b = " + (a - b)); // 11
        System.out.println("a * b = " + (a * b)); // 60
        System.out.println("a / b = " + (a / b)); // 3
        System.out.println("a % b = " + (a % b)); // 3
    }
}

출력:

a + b = 19
a - b = 11
a * b = 60
a / b = 3
a % b = 3

설명:

  • a / b는 정수 나눗셈이므로 소수점 이하가 버려져 결과는 3입니다.

  • a % b는 a를 b로 나눈 나머지인 3을 반환합니다.

대입 연산자 (Assignment Operators)

대입 연산자는 값을 변수에 할당하는 데 사용됩니다. 또한, 대입 연산자는 다른 연산자와 결합하여 복합 대입 연산자를 형성할 수 있습니다.

부수효과를 일으킵니다.

연산자
이름
설명

=

대입

오른쪽 피연산자의 값을 왼쪽 피연산자에 할당합니다.

+=

더하고 대입 (Add and Assign)

왼쪽 피연산자에 오른쪽 피연산자를 더한 후 결과를 왼쪽 피연산자에 할당합니다.

-=

빼고 대입 (Subtract and Assign)

왼쪽 피연산자에서 오른쪽 피연산자를 뺀 후 결과를 왼쪽 피연산자에 할당합니다.

*=

곱하고 대입 (Multiply and Assign)

왼쪽 피연산자에 오른쪽 피연산자를 곱한 후 결과를 왼쪽 피연산자에 할당합니다.

/=

나누고 대입 (Divide and Assign)

왼쪽 피연산자를 오른쪽 피연산자로 나눈 후 결과를 왼쪽 피연산자에 할당합니다.

%=

나머지 대입 (Modulus and Assign)

왼쪽 피연산자를 오른쪽 피연산자로 나눈 나머지를 왼쪽 피연산자에 할당합니다.

단항연산자(Unary Operators

단항 연산자(Unary Operators)는 하나의 피연산자를 사용하여 연산을 수행하는 연산자입니다. 이들은 피연산자의 값을 수정하거나, 피연산자에 대해 특정 작업을 수행하는 데 사용됩니다.

값 자체에는 사용할 수 없습니다.

연산자
이름
설명
부수효과

++a

전위 증가 연산자

변수의 값을 1 증가시키고 그 값을 반환

1 증가

a++

후위 증가 연산자

현재 값을 반환한 후 변수의 값을 1 증가

1 증가

--a

전위 감소 연산자

변수의 값을 1 감소시키고 그 값을 반환

1 감소

a--

후위 감소 연산자

현재 값을 반환한 후 변수의 값을 1 감소

1 감소

+

단항 더하기 연산자

값에 영향을 주지 않음, 양수임을 명시적으로 표현

없음

-

단항 빼기 연산자

피연산자의 부호를 반전시킴 (양수 → 음수, 음수 → 양수)

없음

관계 연산자 (Relational Operators)

관계 연산자는 두 피연산자 간의 관계를 비교하여 불린 값(true 또는 false)을 반환합니다.

연산자
이름
설명

==

같음

두 피연산자가 같은지 비교합니다.

!=

같지 않음

두 피연산자가 다른지 비교합니다.

>

크다

첫 번째 피연산자가 두 번째보다 큰지 비교합니다.

<

작다

첫 번째 피연산자가 두 번째보다 작은지 비교합니다.

>=

크거나 같다

첫 번째 피연산자가 두 번째보다 크거나 같은지 비교합니다.

<=

작거나 같다

첫 번째 피연산자가 두 번째보다 작거나 같은지 비교합니다.

예시

RelationalOperatorsExample.java

public class RelationalOperatorsExample {
    public static void main(String[] args) {
        int x = 10;
        int y = 20;

        System.out.println("x == y: " + (x == y)); // false
        System.out.println("x != y: " + (x != y)); // true
        System.out.println("x > y: " + (x > y));   // false
        System.out.println("x < y: " + (x < y));   // true
        System.out.println("x >= 10: " + (x >= 10)); // true
        System.out.println("y <= 15: " + (y <= 15)); // false
    }
}

다음 링크를 통해 우선순위를 확인할 수 있음

형변환

서로 다른 자료형 간의 연산은 형변환이 자동으로 이루어집니다. 이 과정은 명시적 형변환(type casting)과 암시적 형변환(implicit casting)으로 나뉩니다. 암시적 형변환은 자바 컴파일러에 의해 자동으로 수행되며, 데이터 손실이 없는 안전한 변환에서 발생합니다. 명시적 형변환은 프로그래머가 직접 형변환을 명시적으로 지정해야 하는 경우 발생합니다.

CastingExample.java 참고

1. 정수와 정수 연산 시 형변환

정수 자료형끼리의 연산에서, 동일한 자료형끼리 연산하면 자동 형변환이 필요하지 않습니다. 하지만 작은 자료형에서 큰 자료형으로 연산을 수행할 때는 암시적 형변환이 발생합니다.

예시:

int a = 5;
long b = 10L;

// long으로 자동 변환됨 (암시적 형변환)
long result = a + b;
System.out.println(result);  // 출력: 15
  • int형 변수 a가 long형 변수 b와 연산될 때, a가 자동으로 long으로 변환되어 연산됩니다. 이는 암시적 형변환이며, 더 큰 자료형으로 변환되므로 안전합니다.

2. 정수와 실수 연산 시 형변환

정수와 실수 간의 연산에서는 정수가 실수로 암시적 형변환됩니다. int나 long 등의 정수형은 float 또는 double로 자동 변환되며, 연산 결과는 실수형이 됩니다.

예시:

int c = 5;
double d = 2.5;

// double로 자동 변환됨
double result = c + d;
System.out.println(result);  // 출력: 7.5
  • int형 변수 c는 double형 변수 d와 연산되기 전에 자동으로 double로 변환됩니다. 이는 데이터 손실이 없기 때문에 안전한 암시적 형변환입니다.

3. 실수와 실수 연산 시 형변환

두 실수 자료형(float과 double) 간의 연산에서도 형변환이 일어납니다. float과 double이 함께 사용될 경우, float은 암시적으로 double로 변환됩니다. 실수형 연산의 결과는 더 큰 정밀도를 가진 자료형인 double이 됩니다.

예시:

float f = 3.5f;
double e = 2.5;

// float이 double로 변환됨
double result = f + e;
System.out.println(result);  // 출력: 6.0
  • float형 변수 f는 double로 변환된 후 e와 연산됩니다. 이 역시 암시적 형변환으로, 결과는 double 자료형이 됩니다.

4. 명시적 형변환

형변환이 필요한 경우 명시적으로 형변환을 할 수 있습니다. 예를 들어, 실수를 정수로 변환할 때 데이터 손실이 발생할 수 있으므로 명시적 형변환이 필요합니다.

예시:

double pi = 3.14159;
int intPi = (int) pi;  // 소수점 이하가 버려짐
System.out.println(intPi);  // 출력: 3
  • double형 값을 int로 변환할 때 소수점 이하가 제거되므로 데이터 손실이 발생할 수 있습니다. 이때는 명시적 형변환을 사용해야 합니다.

요약

  • 정수와 정수 연산: 더 큰 정수형으로 자동 변환 (암시적 형변환).

  • 정수와 실수 연산: 정수는 실수로 자동 변환되어 연산 (암시적 형변환).

  • 실수와 실수 연산: float은 double로 자동 변환되어 연산 (암시적 형변환).

  • 명시적 형변환: 정밀도 손실이 발생할 수 있는 변환에는 명시적으로 형변환을 지정해야 함.

Boolean 자료형

BooleanExample.java 참고

boolean 자료형은 참(true) 또는 거짓(false) 중 하나의 값을 가질 수 있는 논리 자료형입니다. boolean 자료형은 1비트 크기의 메모리를 차지하며, 주로 조건문, 반복문 등의 제어 흐름에서 사용됩니다. 참(true)과 거짓(false) 값만을 가질 수 있기 때문에 매우 단순한 논리 판단에 적합합니다.

boolean 자료형의 특징

  • 값의 범위: true 또는 false만 가질 수 있음.

  • 기본값: 클래스 필드에서 초기화되지 않은 boolean 변수는 기본적으로 false로 초기화됩니다.

  • 용도: 주로 조건문(if, while)이나 논리 연산(&&, ||, !)에서 사용됩니다.

예시: boolean 변수 선언 및 초기화

boolean isJavaFun = true;
boolean isFishTasty = false;

System.out.println("Java is fun: " + isJavaFun);  // 출력: Java is fun: true
System.out.println("Fish is tasty: " + isFishTasty);  
// 출력: Fish is tasty: false

boolean 자료형에서 사용하는 연산자

1. 논리 AND (&&)

  • 두 값이 모두 true일 때만 true를 반환합니다.

  • 즉, 둘 중 하나만 false 여도 false 반환합니다.

boolean result = (5 > 3) && (8 > 6);  // true && true => true
System.out.println(result);  // 출력: true

2. 논리 OR (||)

  • 두 값 중 하나라도 true이면 true를 반환합니다.

boolean result = (5 > 3) || (2 > 6);  // true || false => true
System.out.println(result);  // 출력: true

3. 논리 NOT (!)

  • true는 false로, false는 true로 반전시킵니다.

boolean isJavaFun = true;
System.out.println(!isJavaFun);  // 출력: false

조건부 연산자 (Conditional Operators)

조건부 연산자는 삼항 연산자로도 알려져 있으며, 세 개의 피연산자를 사용하여 조건에 따라 값을 선택합니다.

연산자
이름
설명

?:

삼항 조건 연산자

조건식이 true이면 첫 번째 값을, false이면 두 번째 값을 반환합니다.

예시

ConditionalOperatorsExample.java

public class ConditionalOperatorsExample {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;

        // 삼항 조건 연산자 사용
        String result = (a > b) ? "a가 b보다 큽니다." : "a가 b보다 작거나 같습니다.";
        System.out.println(result); // "a가 b보다 작거나 같습니다."

        // 변수 할당 예시
        int max = (a > b) ? a : b;
        System.out.println("최대값: " + max); // 최대값: 20
    }
}

출력:

a가 b보다 작거나 같습니다.
최대값: 20

설명:

  • (a > b) ? "a가 b보다 큽니다." : "a가 b보다 작거나 같습니다."는 a가 b보다 큰지 검사하여, 참일 경우 "a가 b보다 큽니다."를 반환하고, 거짓일 경우 "a가 b보다 작거나 같습니다."를 반환합니다.

  • int max = (a > b) ? a : b;는 a와 b 중 더 큰 값을 max에 할당합니다.

문자 자료형

Java에서 문자 자료형(char)과 문자열 자료형(String)은 서로 다른 방식으로 문자를 다루는 두 가지 자료형입니다. 이 자료형들은 ASCII 코드를 사용하여 문자를 숫자로 변환해 내부적으로 처리됩니다.

1. 문자 자료형 (Character Type): char

  • 자료형: char는 하나의 문자를 저장하는 기본형 자료형입니다.

  • 크기: char는 2바이트(16비트) 크기로, 유니코드 문자 세트를 지원합니다.

  • 값의 범위: 유니코드 문자의 값 범위는 \u0000에서 \uffff까지이며, 이는 0에서 65535 사이의 값을 가집니다.

  • 리터럴 표기법: 작은 따옴표(' ')로 하나의 문자를 표현합니다.

예시:

char letter = 'A';  // 'A'는 ASCII 코드 값 65
char number = '1';  // '1'은 ASCII 코드 값 49
char symbol = '#';  // '#'은 ASCII 코드 값 35

2. 문자열 자료형 (String Type): String

  • 자료형: String은 여러 문자가 연속적으로 모인 참조형 자료형입니다. String은 Java에서 가장 많이 사용하는 클래스 중 하나입니다.

  • 크기: String의 크기는 문자열의 길이에 따라 다릅니다. 각 문자는 2바이트 크기를 차지하며, 유니코드를 사용하여 다양한 문자를 지원합니다.

  • 리터럴 표기법: 큰 따옴표(" ")로 여러 문자를 감싸서 문자열을 표현합니다.

  • 불변성: String 객체는 한 번 생성되면 변경할 수 없습니다. 문자열이 변경될 경우, 새로운 String 객체가 생성됩니다.

예시:

String word = "Hello";  // 문자열은 큰 따옴표를 사용
String greeting = "Hi, " + word;  // 문자열 결합

3. ''와 ""의 차이

  • 작은 따옴표(' ')는 단일 문자를 표현하는 데 사용되며, char 자료형에서 사용됩니다.

  • 큰 따옴표(" ")는 문자열을 표현하는 데 사용되며, String 자료형에서 사용됩니다.

차이 예시:

char singleChar = 'A';  // 하나의 문자
String word = "Apple";  // 여러 문자의 조합
  • 'A'는 단일 문자로 char 자료형에 할당되고, "Apple"은 문자열로 여러 문자를 포함하여 String 자료형에 할당됩니다.

이스케이프 문자열(Escape Sequences)

이스케이프 문자열(Escape Sequences)은 특수 문자를 표현하기 위해 사용하는 문자열입니다. 자바에서 특정 문자들은 출력 시 특별한 의미를 가지기 때문에, 이런 문자를 정상적으로 처리하거나 출력하려면 이스케이프 시퀀스를 사용해야 합니다. 이스케이프 시퀀스는 백슬래시(\)로 시작하며, 그 뒤에 오는 문자가 특수한 의미를 가집니다.

자주 사용하는 이스케이프 문자열 목록

이스케이프 시퀀스
설명
예시 출력

\n

새로운 줄 (줄바꿈)

줄바꿈

\t

탭 (수평 탭)

탭 간격

\\

백슬래시 (\) 자체를 출력

\

\'

작은 따옴표 (')를 출력

'

\"

큰 따옴표 (")를 출력

"

예시 코드

EscapeSequencesExample.java

public class EscapeSequencesExample {
    public static void main(String[] args) {
        // 여러 가지 이스케이프 시퀀스 사용
        System.out.println("Hello\nWorld!");  // 줄바꿈
        System.out.println("Hello\tWorld!");  // 탭
        System.out.println("He said, \"Java is fun!\"");  // 큰 따옴표
        System.out.println("Path: C:\\Program Files\\Java");  // 백슬래시
    }
}

출력 결과

Hello
World!
Hello   World!
He said, "Java is fun!"
Path: C:\Program Files\Java

formatted()

formatted() 메소드는 Java 15부터 도입된 메소드로, **String.format()**의 간결한 대체 방법입니다. 이 메소드는 문자열 포매팅을 좀 더 직관적으로 작성할 수 있게 해 줍니다. **String.formatted()**는 원래의 문자열을 포맷팅할 문자열로 변환하는 데 사용되며, 포맷 지정자(%s, %d, %f 등)를 통해 값들을 해당 위치에 삽입합니다.

기본 구조

"포맷 문자열".formatted(값1, 값2, ...);
  • 포맷 문자열: 포맷 지정자를 포함한 문자열입니다. %s는 문자열을, %d는 정수를, %f는 실수를 출력할 때 사용됩니다.

  • 값들: 포맷 문자열에 맞게 들어갈 값들입니다. 순서대로 각각의 포맷 지정자에 대응됩니다.

예시

문자열 포매팅

String name = "홍길동";
int age = 30;
String result = "이름: %s, 나이: %d".formatted(name, age);
System.out.println(result);  // 출력: 이름: 홍길동, 나이: 30
  • %s는 문자열을, %d는 정수를 출력하는 포맷 지정자입니다.

  • "이름: %s, 나이: %d" 문자열에 대해 name(홍길동)과 age(30)를 전달하여 "이름: 홍길동, 나이: 30"이라는 포맷팅된 문자열을 반환합니다.

실수 포매팅

double price = 123.456;
String formattedPrice = "가격: %.2f원".formatted(price);
System.out.println(formattedPrice);  // 출력: 가격: 123.46원
  • %.2f: 소수점 두 자리까지 실수를 출력하는 포맷 지정자입니다.

  • 실수 price가 소수점 두 자리까지 반올림되어 출력됩니다.

주요 포맷 지정자(Format Specifier)

포맷 지정자
설명
예시 출력

%s

문자열(String)

"홍길동" → "홍길동"

%d

정수(Integer)

123 → 123

%f

부동소수점(Float)

123.456 → 123.456000

%x

16진수(Hexadecimal)

255 → ff

%%

퍼센트 문자(%)

출력: %

포맷 지정자와 옵션 사용

1. 소수점 자릿수 지정

double number = 3.141592;
String result = "원주율: %.2f".formatted(number);
System.out.println(result);  // 출력: 원주율: 3.14
  • %.2f: 소수점 이하 둘째 자리까지 표시하고, 그 이후는 반올림합니다.

2. 출력 너비 지정

int number = 42;
String result = "번호: %5d".formatted(number);
System.out.println(result);  // 출력: 번호:    42 (앞에 3칸의 공백 추가)
  • %5d: 최소 5자리의 공간을 확보하여 출력합니다. 값이 적으면 앞에 공백이 추가됩니다.

3. 좌측 정렬

int number = 42;
String result = "번호: %-5d".formatted(number);
System.out.println(result);  // 출력: 번호: 42   (뒤에 3칸의 공백 추가)
  • %-5d: 최소 5칸을 확보하고 좌측 정렬하여 값을 출력합니다.

formatted()의 장점

  • 간결함: String.format()보다 더 직관적이고 코드가 짧아 가독성이 좋습니다.

  • 간편한 포맷팅: 기본 문자열에 바로 포맷팅을 적용할 수 있어, 문자열 조작이 더 쉬워집니다.

정리

  • formatted()는 Java 15에서 도입된 문자열 포맷팅 메소드로, 문자열에 포함된 포맷 지정자를 사용해 값을 삽입하는 데 사용됩니다.

  • %s, %d, %f 등 다양한 포맷 지정자를 활용해 문자열, 정수, 실수 등의 데이터를 포맷팅할 수 있습니다.

  • formatted()는 더 간결한 방식으로 포맷팅된 문자열을 처리할 수 있습니다.

문자열의 메소드

length()

  • 설명: 문자열의 길이를 반환하는 메소드입니다. 문자열에 포함된 문자의 개수를 반환하며, 공백도 하나의 문자로 취급됩니다. 빈 문자열의 경우에는 0을 반환합니다.

  • 예시:

    String str = "Hello";
    System.out.println(str.length());  // 출력: 5
    • "Hello"는 5개의 문자를 포함하므로 5를 반환합니다.

isEmpty()

  • 설명: 문자열이 비어있는지 확인하는 메소드입니다. 즉, 문자열의 길이가 0이면 true를 반환하고, 그렇지 않으면 false를 반환합니다.

  • 예시:

    String str1 = "";
    String str2 = "Hello";
    System.out.println(str1.isEmpty());  // 출력: true
    System.out.println(str2.isEmpty());  // 출력: false
    • ""는 빈 문자열이므로 true를 반환하고, "Hello"는 문자가 있으므로 false를 반환합니다.

isBlank()

  • 설명: 문자열이 비어있거나, 공백 문자만으로 구성되어 있는지 확인하는 메소드입니다. isEmpty()는 문자열이 아예 없는 경우에만 true를 반환하는 반면, isBlank()는 공백 문자(" "), 탭(), 줄바꿈() 등만 있는 경우에도 true를 반환합니다.

  • 예시:

    String str1 = "   ";  // 공백 문자만 있음
    String str2 = "Hello";
    System.out.println(str1.isBlank());  // 출력: true
    System.out.println(str2.isBlank());  // 출력: false
    • str1은 공백만 있으므로 true를 반환하고, str2는 내용이 있는 문자열이므로 false를 반환합니다.

trim() 메소드

  • 설명: trim()은 문자열의 양쪽 끝에 있는 공백(스페이스, 탭, 줄바꿈 등)을 제거하는 메소드입니다. 문자열의 앞과 뒤에 있는 모든 공백을 삭제하며, 문자열 중간의 공백은 유지합니다.

  • 주의사항: 이 메소드는 문자열의 내용을 수정하는 것이 아니라, 공백이 제거된 새로운 문자열을 반환합니다. 따라서 원본 문자열은 변하지 않습니다.

예시:

String str = "   Hello, World!   ";
String trimmedStr = str.trim();
System.out.println(trimmedStr);  // 출력: "Hello, World!"
  • trim()을 호출하면 앞과 뒤에 있는 공백이 제거되고 "Hello, World!"만 남습니다.

charAt() 메소드

  • 설명: charAt() 메소드는 문자열에서 특정 인덱스에 위치한 문자를 반환하는 메소드입니다. 인덱스는 0부터 시작하므로, 첫 번째 문자의 인덱스는 0입니다. 이 메소드를 사용해 문자열 내의 특정 위치의 문자를 추출할 수 있습니다.

구문:

char charAt(int index)
  • index - 반환하고자 하는 문자의 위치를 나타내는 정수형 값입니다.

  • 반환값: 해당 인덱스의 char 값을 반환합니다. 만약 인덱스가 범위를 벗어나면 StringIndexOutOfBoundsException이 발생합니다.

예시:

CharAtExample.java

public class CharAtExample {
    public static void main(String[] args) {
        String str = "Hello, World!";
        char ch = str.charAt(7);  // 7번째 인덱스에 해당하는 문자 'W'를 반환
        System.out.println(ch);   // 출력: W
        
        char lastCh = str.charAt(str.length() - 1); // 마지막 문자 얻기
        System.out.println(lastCh);
    }
}
  • 인덱스: "Hello, World!"에서 charAt(7)은 0부터 세기 때문에 7번째 위치에 있는 문자인 'W'를 반환합니다.

indexOf() 메소드

  • 설명: indexOf()는 문자열 내에서 특정 문자 또는 부분 문자열이 처음으로 나타나는 인덱스를 반환하는 메소드입니다. 만약 문자열 내에 해당 문자가 존재하지 않으면 -1 을 반환합니다.

  • 인덱스는 0부터 시작합니다.

구문:

int indexOf(int ch)           // 특정 문자의 첫 번째 인덱스를 반환
int indexOf(String str)       // 부분 문자열의 첫 번째 인덱스를 반환
int indexOf(int ch, int fromIndex)    // 특정 문자 검색을 시작할 위치를 지정
int indexOf(String str, int fromIndex)  // 특정 부분 문자열 검색 시작 위치를 지정

예시:

String str = "Hello, World!";
int index1 = str.indexOf('o');  // 첫 번째 'o'의 인덱스 (4)
int index2 = str.indexOf("World");  // "World"의 시작 인덱스 (7)
System.out.println(index1);  // 출력: 4
System.out.println(index2);  // 출력: 7
  • indexOf('o'): 처음 나타나는 문자 'o'의 인덱스는 4입니다.

  • indexOf("World"): 부분 문자열 "World"는 인덱스 7에서 시작합니다.

주의사항:

  • 만약 찾는 문자나 문자열이 존재하지 않으면 -1 을 반환합니다.

int index = str.indexOf('x');  // 'x'는 없으므로 -1 반환
System.out.println(index);  // 출력: -1

lastIndexOf() 메소드

  • 설명: lastIndexOf()는 문자열 내에서 특정 문자 또는 부분 문자열이 마지막으로 나타나는 인덱스를 반환하는 메소드입니다. 만약 문자열 내에 해당 문자가 존재하지 않으면 -1 을 반환합니다.

  • 인덱스는 0부터 시작합니다.

구문:

int lastIndexOf(int ch)           // 특정 문자의 마지막 인덱스를 반환
int lastIndexOf(String str)       // 부분 문자열의 마지막 인덱스를 반환
int lastIndexOf(int ch, int fromIndex)  // 검색을 특정 인덱스부터 역순으로 검색
int lastIndexOf(String str, int fromIndex)  // 부분 문자열을 역순으로 검색 시작 위치 지정

예시:

String str = "Hello, World!";
int lastIndex1 = str.lastIndexOf('o');  // 마지막 'o'의 인덱스 (8)
int lastIndex2 = str.lastIndexOf("World");  // "World"의 시작 인덱스 (7)
System.out.println(lastIndex1);  // 출력: 8
System.out.println(lastIndex2);  // 출력: 7
  • lastIndexOf('o'): 문자열에서 마지막으로 나타나는 'o'의 인덱스는 8입니다.

  • lastIndexOf("World"): 부분 문자열 "World"는 인덱스 7에서 시작하므로 반환 값은 7입니다.

주의사항:

  • 찾는 문자가 없으면 -1 을 반환합니다.

int lastIndex = str.lastIndexOf('x');  // 'x'는 없으므로 -1 반환
System.out.println(lastIndex);  // 출력: -1

차이점:

  • indexOf(): 문자열의 앞에서부터 첫 번째로 나타나는 위치를 반환합니다.

  • lastIndexOf(): 문자열의 뒤에서부터 마지막으로 나타나는 위치를 반환합니다.

equals() 메소드

  • 설명: equals()는 두 객체가 내용적으로 같은지 비교하는 메소드입니다. String 클래스에서 equals()는 문자열의 값을 비교하여, 두 문자열의 내용이 같으면 true, 그렇지 않으면 false를 반환합니다. 이는 참조(메모리 주소)가 아닌 값(내용)을 비교하는 중요한 메소드입니다.

구문:

public boolean equals(Object obj)

예시:

EqualsExample.java

public class EqualsExample {
    public static void main(String[] args) {
        String str1 = "Hello";
        String str2 = "Hello";
        String str3 = new String("Hello"); // 추후 배우겠지만 String 객체 생성
        String str4 = "hello";

        System.out.println(str1.equals(str2));  // true (값이 같음)
        System.out.println(str1.equals(str3));  // true (값이 같음)
        System.out.println(str1.equals(str4));  // false (대소문자 다름)
    }
}

결과:

  1. str1.equals(str2): 문자열 "Hello"는 값이 같기 때문에 true를 반환합니다.

  2. str1.equals(str3): str3은 new 키워드를 사용해 새로운 객체로 생성되었지만, 내용은 같으므로 true를 반환합니다.

  3. str1.equals(str4): "Hello"와 "hello"는 대소문자가 다르기 때문에 false를 반환합니다.

주요 특징:

  1. 대소문자 구분: equals()는 대소문자를 구분하여 비교합니다.

  2. 참조가 아닌 값 비교: equals()는 참조값이 아닌 내용을 비교합니다. == 연산자는 두 객체가 동일한 참조를 가지고 있는지 확인할 때 사용되지만, equals()는 두 객체의 값을 비교합니다.

대소문자 무시 비교: equalsIgnoreCase()

  • 대소문자를 구분하지 않고 문자열을 비교하고 싶을 경우, equalsIgnoreCase() 메소드를 사용할 수 있습니다.

System.out.println(str1.equalsIgnoreCase(str4));  // true (대소문자 무시)

equals()와 ==의 차이:

  • equals(): 두 객체의 내용을 비교합니다.

  • ==: 두 객체가 같은 메모리 주소를 참조하고 있는지 비교합니다.

String strA = new String("Hello");
String strB = new String("Hello");

System.out.println(strA == strB);        // false (다른 객체)
System.out.println(strA.equals(strB));   // true (내용이 동일)

equals() 메소드는 자바에서 객체나 문자열을 비교할 때 기본적으로 많이 사용되는 메소드로, 특히 값의 일치 여부를 확인할 때 중요합니다.

contains() 메소드

  • 설명: contains() 메소드는 문자열에 특정 문자열이 포함되어 있는지를 확인합니다. 만약 해당 문자열이 포함되어 있으면 true, 그렇지 않으면 false를 반환합니다. 대소문자를 구분하며, 부분 문자열을 찾을 때 유용합니다.

구문:

boolean contains(CharSequence sequence)
  • 찾고자 하는 문자열 또는 문자의 서열 (ex: "abc")

  • 반환값: true 또는 false

startsWith() 메소드

  • 설명: startsWith() 메소드는 문자열이 특정 접두사로 시작하는지 확인합니다. 지정한 접두사로 시작하면 true, 그렇지 않으면 false를 반환합니다. 또한, 문자열의 특정 인덱스부터 검색을 시작할 수도 있습니다.

구문:

boolean startsWith(String prefix)
boolean startsWith(String prefix, int toffset)
  • prefix: 찾을 접두사 문자열

  • toffset: 검색을 시작할 위치 (선택 사항)

  • 반환값: true 또는 false

endsWith() 메소드

  • 설명: endsWith() 메소드는 문자열이 특정 접미사로 끝나는지 확인합니다. 지정한 접미사로 끝나면 true, 그렇지 않으면 false를 반환합니다. 문자열의 끝 부분을 검사하는 데 유용합니다.

구문:

boolean endsWith(String suffix)
  • suffix - 찾을 접미사 문자열

  • 반환값: true 또는 false

contains(), startsWith(), endsWith() 메소드를 사용한 예제

StringMethodsExample.java

public class StringMethodsExample {
    public static void main(String[] args) {
        String str = "Hello, World!";

        // contains() 사용: "World"가 포함되어 있는지 확인
        System.out.println("contains 'World': " + str.contains("World"));

        // startsWith() 사용: "Hello"로 시작하는지 확인
        System.out.println("startsWith 'Hello': " + str.startsWith("Hello"));

        // endsWith() 사용: "World!"로 끝나는지 확인
        System.out.println("endsWith 'World!': " + str.endsWith("World!"));
    }
}

출력 결과:

contains 'World': true
startsWith 'Hello': true
endsWith 'World!': true

설명:

  • contains("World"): 문자열 "Hello, World!"에 "World"가 포함되어 있으므로 true를 반환합니다.

  • startsWith("Hello"): 문자열이 "Hello"로 시작하므로 true를 반환합니다.

  • endsWith("World!"): 문자열이 "World!"로 끝나므로 true를 반환합니다.

추가예제 (offset 활용)

// indexOf() 사용: "World"의 시작 위치(offset) 찾기
int offset = str.indexOf("World");
System.out.println("indexOf 'World': " + offset);

// substring() 사용: offset을 기준으로 부분 문자열 추출
if (offset != -1) {
    String substring = str.substring(offset);
    System.out.println("substring from 'World': " + substring);
}

// 특정 위치에서 startsWith() 사용: "World"가 offset 위치에서 시작하는지 확인
System.out.println("startsWith 'World' from offset 7: " + str.startsWith("World", 7));

compareTo() 메소드

  • 설명: compareTo() 메소드는 문자열을 사전순으로 비교하는 메소드입니다. 두 문자열의 유니코드 값을 기준으로 문자열을 비교하여, 두 문자열이 동일하면 0, 호출한 문자열이 사전순으로 더 앞에 있으면 음수, 더 뒤에 있으면 양수를 반환합니다.

구문:

int compareTo(String anotherString)
  • anotherString: 비교할 문자열

  • 반환값:

    • 0: 두 문자열이 동일할 때 반환.

    • 음수: 호출한 문자열이 사전순으로 비교 문자열보다 앞에 있을 때.

    • 양수: 호출한 문자열이 사전순으로 비교 문자열보다 뒤에 있을 때.

예시:

CompareToExample.java

public class CompareToExample {
    public static void main(String[] args) {
        String str1 = "apple";
        String str2 = "banana";
        String str3 = "apple";

        // str1과 str2 비교
        System.out.println(str1.compareTo(str2));  
        // 출력: 음수 (str1이 str2보다 앞에 있음)

        // str1과 str3 비교
        System.out.println(str1.compareTo(str3));  // 출력: 0 (두 문자열이 같음)

        // str2와 str1 비교
        System.out.println(str2.compareTo(str1));  
        // 출력: 양수 (str2가 str1보다 뒤에 있음)
    }
}

출력:

-1
0
1

설명:

  1. str1.compareTo(str2): "apple"과 "banana"를 비교하면 "apple"이 사전순으로 앞에 있으므로 음수가 반환됩니다.

  2. str1.compareTo(str3): "apple"과 "apple"은 동일한 문자열이므로 0이 반환됩니다.

  3. str2.compareTo(str1): "banana"가 "apple"보다 사전순으로 뒤에 있으므로 양수가 반환됩니다.

주요 특징:

  • 대소문자를 구분합니다. 예를 들어, "Apple"은 "apple"보다 사전순으로 앞에 위치합니다.

예시:

System.out.println("Apple".compareTo("apple"));  // 출력: 음수 ('A' < 'a')

활용

  • 문자열을 정렬하거나 사전순으로 비교할 때 유용합니다.

toUpperCase()

  • 설명: 문자열의 모든 문자를 대문자로 변환합니다. 원본 문자열은 변경되지 않으며, 대문자로 변환된 새로운 문자열을 반환합니다.

  • 구문:

    String toUpperCase()
  • 예시:

    String str = "hello world";
    String upperStr = str.toUpperCase();  // "HELLO WORLD"
    System.out.println(upperStr);

toLowerCase()

  • 설명: 문자열의 모든 문자를 소문자로 변환합니다. 원본 문자열은 변경되지 않으며, 소문자로 변환된 새로운 문자열을 반환합니다.

  • 구문:

    String toLowerCase()
  • 예시:

    String str = "HELLO WORLD";
    String lowerStr = str.toLowerCase();  // "hello world"
    System.out.println(lowerStr);

주요 특징:

  • 불변성: String 클래스는 불변(immutable)이기 때문에, toUpperCase()나 toLowerCase()는 원본 문자열을 수정하지 않고 변환된 새로운 문자열을 반환합니다.

결론:

  • toUpperCase(): 문자열을 대문자로 변환.

  • toLowerCase(): 문자열을 소문자로 변환.

null

  • 정의: null은 참조형 변수가 아무런 객체도 가리키고 있지 않을 때 사용되는 값입니다. 이는 메모리 상에서 아무 것도 가리키지 않는 빈 참조를 의미합니다. 즉, 변수가 객체를 참조하지 않을 때 null로 초기화될 수 있습니다.

  • 특징:

    • null은 메모리상에서 아무 객체도 존재하지 않음을 나타냅니다.

    • null 상태의 변수에 메소드를 호출하면 NullPointerException이 발생합니다.

예시:

String str = null;
System.out.println(str.length());  // NullPointerException 발생

비어있는 문자열 ("")

  • 정의: ""는 길이가 0인 문자열, 즉 빈 문자열입니다. 이 문자열은 존재하지만, 아무 문자도 포함하고 있지 않습니다.

  • 특징:

    • 빈 문자열은 유효한 문자열 객체이지만, 그 길이가 0입니다.

    • 빈 문자열에 대해 메소드를 호출하는 것은 안전하며, NullPointerException이 발생하지 않습니다.

예시:

String emptyStr = "";
System.out.println(emptyStr.length());  // 출력: 0

NullExample.java

public class NullExample {
    public static void main(String[] args) {
        String nullStr = null;  // null 참조
        String emptyStr = "";   // 비어있는 문자열

        // nullStr 결과 출력
        System.out.println("nullStr은 " 
                + (nullStr == null ? "null입니다." : "비어있는 문자열이 아닙니다."));

        // emptyStr 결과 출력
        System.out.println("emptyStr은 " 
                + (emptyStr.isEmpty() ? "비어있는 문자열입니다." : "null입니다."));
    }
}

배열

배열(Array)은 동일한 자료형의 여러 값을 하나의 변수에 저장할 수 있는 자료 구조입니다. 배열은 정해진 크기와 특정 타입의 데이터를 연속적으로 저장하며, 인덱스를 사용해 각 요소에 접근할 수 있습니다. 인덱스는 0부터 시작합니다.

특징

  1. 고정된 크기: 배열은 한 번 생성되면 크기를 변경할 수 없습니다. 배열의 크기는 초기화할 때 결정됩니다.

  2. 동일한 자료형: 배열은 단일 자료형(예: int, double, String 등)의 값만 저장할 수 있습니다. 서로 다른 자료형의 값을 배열에 저장할 수 없습니다.

  3. 0 기반 인덱싱: 배열의 인덱스는 0부터 시작하며, array[0]은 배열의 첫 번째 요소를 의미합니다.

배열 선언 및 초기화

배열은 선언 후 초기화하거나, 선언과 동시에 초기화할 수 있습니다.

1. 배열 선언

int[] numbers;  // 정수형 배열 선언
String[] names; // 문자열 배열 선언

2. 배열 초기화

배열은 정적 크기로 초기화됩니다.

// 배열 생성 및 초기화
numbers = new int[5];  // 크기가 5인 정수형 배열
names = new String[3]; // 크기가 3인 문자열 배열

3. 선언과 동시에 초기화

int[] numbers = {1, 2, 3, 4, 5};  // 값 할당과 동시에 초기화
String[] names = {"Alice", "Bob", "Charlie"};

배열 요소 접근

배열의 각 요소는 인덱스를 통해 접근합니다.

int[] numbers = {10, 20, 30, 40};
int firstElement = numbers[0];  // 첫 번째 요소 (10)
int secondElement = numbers[1]; // 두 번째 요소 (20)

// 배열 요소 변경
numbers[2] = 50;  // 세 번째 요소를 50으로 변경

배열의 길이

배열의 길이는 length 속성을 통해 확인할 수 있습니다.

int[] numbers = {1, 2, 3};
System.out.println(numbers.length);  // 출력: 3

다차원 배열

Java는 다차원 배열도 지원합니다. 가장 일반적인 다차원 배열은 2차원 배열로, 행과 열의 구조로 데이터를 저장합니다.

2차원 배열 선언 및 초기화:

boolean[][] dblBoolAry = new boolean[3][3];

int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

int[][] dblIntAry = new int[][] {
        {1, 2, 3},
        {4, 5},
        {6, 7, 8, 9},
};

2차원 배열 요소 접근:

int value = matrix[0][1];  // 첫 번째 행, 두 번째 열의 값 (2)
matrix[2][2] = 10;  // 세 번째 행, 세 번째 열의 값을 10으로 변경

배열의 장단점

장점:

  • 빠른 접근: 인덱스를 이용해 배열 요소에 빠르게 접근할 수 있습니다.

  • 연속적인 메모리 할당: 메모리에 연속적으로 저장되어 효율적인 데이터 접근이 가능합니다.

단점:

  • 고정된 크기: 배열의 크기는 한 번 설정되면 변경할 수 없습니다.

  • 동일한 자료형: 배열은 같은 타입의 데이터만 저장할 수 있습니다.

예제 코드

ArrayExample.java

public class ArrayExample {
    public static void main(String[] args) {
        // 1차원 배열
        int[] numbers = {1, 2, 3, 4, 5};
        System.out.println("First element: " + numbers[0]);
        System.out.println("Array length: " + numbers.length);

        // 2차원 배열
        int[][] matrix = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };
        System.out.println("Matrix[1][2]: " + matrix[1][2]);
        
        // 3차원 배열
        char[][][] trpChrAry = {
                {{'자', '축'}, {'인', '묘'}},
                {{'진', '사'}, {'오', '미'}},
                {{'신', '유'}, {'술', '해'}},
        };
        System.out.println(trpChrAry[1][1][1]);
    }
}

출력:

First element: 1
Array length: 5
Matrix[1][2]: 6

배열의 참조형 특성

Java에서 배열은 참조형 자료형입니다. 이는 배열 변수 자체가 배열 데이터를 직접 저장하는 것이 아니라, 배열이 위치한 메모리 주소를 참조한다는 것을 의미합니다. 이러한 참조형 특성은 배열을 다른 변수에 할당하거나 메소드에 전달할 때, 해당 배열의 참조(메모리 주소)가 전달된다는 점에서 중요합니다.

배열의 참조형 특성 주요 개념

  1. 참조 저장: 배열 변수가 저장하는 것은 실제 배열이 저장된 메모리 주소입니다. 즉, 배열 변수는 배열 객체의 참조(Reference) 역할을 합니다.

    int[] arr = {1, 2, 3};

    여기서 arr은 실제 배열 데이터 {1, 2, 3}을 직접 저장하는 것이 아니라, 배열이 메모리에 위치한 주소를 참조합니다.

  2. 참조의 복사: 배열을 다른 변수에 할당하면 배열의 참조가 복사됩니다. 즉, 배열의 데이터가 복사되는 것이 아니라 같은 메모리 주소를 참조하게 됩니다. 따라서 한 변수에서 배열의 내용을 수정하면, 다른 변수에서도 그 변경이 반영됩니다.

    int[] originalArray = {1, 2, 3};
    int[] newArray = originalArray;  // 참조 복사
    
    newArray[0] = 100;  // originalArray도 변경됨
    System.out.println(Arrays.toString(originalArray));  // 출력: [100, 2, 3]

    newArray[0]의 값을 수정하면 originalArray도 함께 변경됩니다. 이는 두 배열 변수가 동일한 배열 객체를 참조하고 있기 때문입니다.

  3. 메소드로 배열 전달: 배열을 메소드의 매개변수로 전달할 때도 배열의 참조가 전달됩니다. 메소드 내부에서 배열의 값을 수정하면, 원래 배열도 함께 수정됩니다.

    import java.util.Arrays;
    
    public class Main {
        public static void main(String[] args) {
            int[] arr = {1, 2, 3};
            modifyArray(arr);
            System.out.println(Arrays.toString(arr));  // 메소드에서 배열 수정 시 반영됨
        }
    
        public static void modifyArray(int[] arr) {    // 배열의 길이에 맞춰 값을 수정
             for (int i = 0; i < arr.length; i++) {
             arr[i] += 1;  // 각 요소에 1을 더함
             }
        }
    }

    이 경우, 배열이 메소드에 전달될 때 복사된 참조가 전달되기 때문에, 메소드 내부에서 배열을 수정하면 원본 배열도 수정됩니다.

  4. 참조 비교: 배열끼리의 비교에서 == 연산자는 두 배열이 같은 메모리 주소를 참조하는지 비교합니다. 배열의 내용을 비교하려면 Arrays.equals() 메소드를 사용해야 합니다.

    int[] arr1 = {1, 2, 3};
    int[] arr2 = {1, 2, 3};
    
    System.out.println(arr1 == arr2);  // false (참조가 다름)
    System.out.println(Arrays.equals(arr1, arr2));  // true (내용이 같음)

배열의 참조형 특성의 장단점

  • 장점:

    • 참조를 사용함으로써 메모리 효율성을 높일 수 있습니다. 배열을 복사하지 않고 참조만 전달하므로 대용량 배열 처리 시 성능에 이점이 있습니다.

  • 단점:

    • 여러 변수가 같은 배열을 참조할 경우, 의도하지 않은 데이터 변경이 발생할 수 있습니다. 하나의 변수를 통해 배열의 값을 수정하면, 다른 모든 참조에도 영향을 미칩니다.

배열 복사 (Array Copy)

배열의 참조형 특성으로 인해 배열을 복사하려면 참조를 복사하는 방식과 값을 복사하는 방식을 구분해야 합니다. 참조를 복사하면 동일한 배열을 참조하게 되지만, 값을 복사하면 새 배열이 생성되어 원본 배열과 독립적으로 동작합니다.

배열 복사의 종류

1. 얕은 복사 (Shallow Copy)

얕은 복사는 배열의 참조만 복사합니다. 원본 배열과 복사된 배열은 동일한 배열 객체를 참조하므로, 하나를 수정하면 다른 배열에도 변경이 반영됩니다.

java코드 복사int[] originalArray = {1, 2, 3};
int[] shallowCopy = originalArray; // 참조 복사

shallowCopy[0] = 100; // 원본 배열도 수정됨
System.out.println(Arrays.toString(originalArray)); // 출력: [100, 2, 3]

특징:

  • 메모리 효율적이지만, 원본 데이터와 독립적으로 동작하지 않음.

  • 의도하지 않은 데이터 변경이 발생할 수 있음.

2. 깊은 복사 (Deep Copy)

깊은 복사는 배열의 값 자체를 복사하여 새로운 배열을 생성합니다. 복사된 배열은 원본 배열과 독립적으로 동작하므로, 하나를 수정해도 다른 배열에 영향을 주지 않습니다.

깊은 복사 방법:

  1. System.arraycopy 사용

int[] originalArray = {1, 2, 3};
int[] deepCopy = new int[originalArray.length];

System.arraycopy(originalArray, 0, deepCopy, 0, originalArray.length);

deepCopy[0] = 100; // 원본 배열에는 영향을 주지 않음
System.out.println(Arrays.toString(originalArray)); // 출력: [1, 2, 3]
System.out.println(Arrays.toString(deepCopy));      // 출력: [100, 2, 3]
  1. Arrays.copyOf 사용

int[] originalArray = {1, 2, 3};
int[] deepCopy = Arrays.copyOf(originalArray, originalArray.length);

deepCopy[0] = 100; // 원본 배열에는 영향을 주지 않음
System.out.println(Arrays.toString(originalArray)); // 출력: [1, 2, 3]
System.out.println(Arrays.toString(deepCopy));      // 출력: [100, 2, 3]
  1. 반복문을 사용한 수동 복사

int[] originalArray = {1, 2, 3};
int[] deepCopy = new int[originalArray.length];

for (int i = 0; i < originalArray.length; i++) {
    deepCopy[i] = originalArray[i];
}

deepCopy[0] = 100; // 원본 배열에는 영향을 주지 않음
System.out.println(Arrays.toString(originalArray)); // 출력: [1, 2, 3]
System.out.println(Arrays.toString(deepCopy));      // 출력: [100, 2, 3]
  1. clone 메서드 사용

int[] originalArray = {1, 2, 3};
int[] deepCopy = originalArray.clone();

deepCopy[0] = 100; // 원본 배열에는 영향을 주지 않음
System.out.println(Arrays.toString(originalArray)); // 출력: [1, 2, 3]
System.out.println(Arrays.toString(deepCopy));      // 출력: [100, 2, 3]

타입추론

타입 추론(Type Inference)은 자바 컴파일러가 변수의 자료형을 개발자가 명시하지 않아도 자동으로 추론하는 기능입니다. 이는 코드의 간결성을 높이고, 특히 제네릭(generic)이나 컬렉션(Collection)과 같은 복잡한 자료형을 사용할 때 유용합니다.

var 키워드

  • Java 10 이상에서 사용 가능하며, 지역 변수의 타입을 자동으로 추론합니다.

  • 주의: var는 컴파일 타임에 결정되는 타입을 추론할 뿐, 변수에 다양한 타입을 넣을 수 있는 동적 타입이 아닙니다.

예시 : 타입 추론을 사용한 변수 선언

TypeInferenceExample.java

public class TypeInferenceExample {
    public static void main(String[] args) {
        // 타입 추론을 사용한 변수 선언
        var number = 10;        // int로 추론
        var text = "Hello";     // String으로 추론
        var decimal = 3.14;     // double로 추론

        System.out.println("Number: " + number);
        System.out.println("Text: " + text);
        System.out.println("Decimal: " + decimal);
    }
}
  • number는 int로, text는 String으로, decimal은 double로 컴파일러가 자동으로 타입을 추론합니다.

제약사항

  • var는 지역 변수에서만 사용 가능하며, 필드 변수나 메소드 파라미터로는 사용할 수 없습니다.

  • 타입을 추론할 수 없는 경우에는 var를 사용할 수 없습니다. 예를 들어, 초기화하지 않은 변수를 var로 선언할 수 없습니다.

예시: 잘못된 타입 추론 사용

var uninitialized;  // 컴파일 오류: 초기값이 없어서 타입을 추론할 수 없음

배열의 경우 초기화시 명시

배열을 선언할 때 var 키워드를 사용할 수 있지만, 배열의 선언과 초기화에서 몇 가지 중요한 규칙이 있습니다. 특히, var를 사용하여 배열을 선언할 때는 배열 생성자가 명시되어야 합니다.

불가능한 방식

var arrayNum = {1, 2, 3};  // 컴파일 오류 발생

이와 같은 방식으로 배열을 선언하는 것은 불가능합니다. 그 이유는 var는 컴파일러가 변수의 타입을 추론하기 위해 명시적인 초기화가 필요하기 때문입니다. {1, 2, 3}과 같은 배열 리터럴은 컴파일러가 타입을 추론하기에 충분한 정보가 아닙니다.

왜 불가능한가?

  • {1, 2, 3}은 단순한 배열 리터럴이며, 배열의 타입이나 구조가 명확하게 지정되지 않았기 때문에 var는 타입을 추론할 수 없습니다.

  • var는 초기화된 값의 타입을 추론해야 하므로, 배열의 생성자를 사용하여 타입을 명시적으로 제공해야 합니다.

올바른 방식

var arrayNum = new int[]{1, 2, 3};  // int[]로 타입 추론

이와 같은 방식으로 배열 생성자를 명시하면, var는 배열의 타입을 추론할 수 있습니다. new int[]{} 구문을 통해 배열의 타입이 int[]라는 것을 명확하게 제공하여, 컴파일러가 이를 기반으로 추론합니다.

불가능한 또 다른 예

또한, var 키워드를 사용할 때, 선언만 하고 초기화하지 않으면 컴파일 오류가 발생합니다.

var array;  // 컴파일 오류 발생: 초기화되지 않은 상태에서는 타입을 추론할 수 없음

왜 불가능한가?

  • var는 변수를 선언과 동시에 초기화해야만 타입을 추론할 수 있습니다. 따라서 초기화 없이 변수를 선언하는 것은 불가능합니다.

정리

  1. 불가능한 방식: var arrayNum = {1, 2, 3};

    • 배열 리터럴만으로는 타입을 추론할 수 없기 때문에 배열 생성자를 명시해야 합니다.

  2. 가능한 방식: var arrayNum = new int[]{1, 2, 3};

    • 배열 생성자를 사용하여 배열의 타입을 명시적으로 지정해야 var가 작동합니다.

  3. 초기화 없이 사용 불가: var array; (초기화 없이 타입을 추론할 수 없음).

Previous02 자바 시작하기Next04 제어문

Last updated 5 months ago

https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html