bonggyulim 님의 블로그
Java 기초 문법 본문
1) 자료형
자바의 자료형은 크게 Primitive type(기본자료형)과 Reference type(참조자료형)으로 구분
1 - 1. Primitive Type (기본 자료형)
실제 값을 직접 저장, 메모리 효율이 높고 빠름
| 자료형 | 크기 | 설명 |
| byte | 1 byte (8bit) | -128 ~ 127 |
| short | 2 byte | -32,768 ~ 32,767 |
| int | 4 byte | 정수 기본형. -21억 ~ 21억 |
| long | 8 byte | 더 큰 정수 처리 가능 |
| float | 4 byte | 소수점 이하 숫자 (단정도, 정밀도 낮음) |
| double | 8 byte | 소수점 이하 숫자 (배정도, 기본형) |
| char | 2 byte | 유니코드 문자 1개 (예: 'A', '가') |
| boolean | 1 byte (이론상) | true 또는 false |
1 - 2. Reference Type (참조 자료형)
실제 값을 직접 저장하지 않고, **메모리 주소(참조값)**를 저장하는 형태
- String (문자열 클래스)
- 배열 (int[], String[])
- 사용자 정의 클래스 (Student, Person 등)
- ArrayList, HashMap (컬렉션 클래스들)
- 인터페이스, 열거형 등도 포함
String name = "Java";
int[] numbers = {1, 2, 3};
2) 조건문
2 - 1. if, else if, else
조건이 참(true) 일 때만 특정 코드를 실행
int score = 85;
if (score >= 90) {
System.out.println("A학점");
} else if (score >= 80) {
System.out.println("B학점");
} else {
System.out.println("C학점 이하");
}
2 - 2. switch 문
변수의 값을 기준으로 하나를 선택
int day = 3;
switch (day) {
case 1:
System.out.println("월요일");
break;
case 2:
System.out.println("화요일");
break;
case 3:
System.out.println("수요일");
break;
default:
System.out.println("주말");
}
3) 반복문
3 - 1. for 문
정해진 횟수만큼 반복
for (int i = 0; i < 5; i++) {
System.out.println("i = " + i);
}
3 - 2. for-each 문
배열이나 컬렉션 등에서 요소를 하나씩 꺼낼 때 사용
int[] arr = {1, 2, 3, 4, 5};
for (int num : arr) {
System.out.println(num);
}
3 - 3. label
반복문 앞에 붙일 수 있는 식별자(이름)
labelName: for (...) {
for (...) {
if (조건) break labelName; // label이 붙은 바깥 for문 종료
}
}
3 - 3 - 1. while 문
조건이 참일 동안 반복
int i = 0;
while (i < 5) {
System.out.println("i = " + i);
i++;
}
3 - 3 - 2. do - while 문
무조건 한번 실행 후 조건이 참일 동안 반복
int num = 0;
do {
System.out.println("한 번은 무조건 실행");
num++;
} while (num < 1);
3 - 3 - 2. 제어문
break : 반복문 종료
continue : 현재 반복 건너뛰고 다음 반복 실행
for (int i = 0; i < 5; i++) {
if (i == 2) continue; // i=2는 건너뜀
if (i == 4) break; // i=4일 때 반복 종료
System.out.println(i);
}
4) 메서드, 클래스, 인스턴스, 생성자
4 - 1. 메서드
객체의 동작을 정의하는 함수
반환타입
리턴타입 메서드이름(매개변수들) {
// 실행할 코드
return 결과값;
}
void 메서드이름(매개변수들) {
// 실행할 코드
}
4 - 2. 클래스
클래스는 속성(변수) 과 동작(메서드) 을 정의하는 틀
현실 세계의 사물을 코드로 표현
public class Dog {
String name; // 속성 (필드)
int age;
void bark() { // 동작 (메서드)
System.out.println(name + "가 짖습니다!");
}
}
- Dog 라는 클래스는 name, age 라는 정보를 가짐
- bark() 라는 행동도 정의
4 - 3. 인스턴스
클래스를 실제로 메모리에 생성한 것
클래스는 설계도, 인스턴스는 설계도로 만든 물건
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog(); // 인스턴스 생성
myDog.name = "진도";
myDog.age = 3;
myDog.bark(); // "진도가 짖습니다!"
}
}
}
클래스에 선언된 변수는 인스턴스가 생성될 때 값이 초기화 된다.
초기화 하지 않는 다면 각 자료형의 디폴트 값이 할당되고 참조 자료형은 null이 할당
4 - 4. 생성자
클래스의 인스턴스를 초기화하기 위해 사용하는 메서드
- 클래스 이름과 같아야함
- 반환형이 없음
- 생성자 오버로딩(여러 개 만들기)도 가능
public class Dog {
String name; // 속성 (필드)
int age;
public Dog(int age) {
this.name = "이름없음";
this.age = age;
}
public Dog(String name, int age) {
this.name = name; // this.name = 객체의 멤버변수, name = 메서드의 매개변수
this.age = age;
}
void bark() { // 동작 (메서드)
System.out.println(name + "가 짖습니다!");
}
}
5) 상속
부모 클래스의 속성과 메서드를 자식 클래스가 물려받는것
코드 재사용 가능
공통 기능은 상속받고, 특수한 기능은 자식 클래스에서 추가/재정의
- extends → 상속할 때 사용
- super → 부모 클래스 참조
- @Override → 메서드 재정의 시 사용
public class Animal {
String name;
public Animal(String name) {
this.name = name;
}
void eat() {
System.out.println(name + "이(가) 먹고 있어요.");
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name); // 부모 생성자 호출
}
void bark() {
System.out.println(name + "가 짖습니다!");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("초코");
dog.eat(); // Animal에서 상속받은 메서드
dog.bark(); // Dog에서 정의한 메서드
}
}
5 - 1. 오버로딩 (Overloading)
한 클래스 안에서 같은 이름의 메서드를 여러개 정의 할 수 있음
매개변수는 다르게 리턴값은 같게 해야 함
5 - 2. 오버라이딩 (Overriding)
상속 받은 메서드를 자식 클래스에서 재정의 하는 것
class Animal {
void speak() {
System.out.println("동물이 소리를 냅니다.");
}
}
class Dog extends Animal {
@Override
void speak() {
System.out.println("강아지가 멍멍 짖습니다.");
}
}
6) 접근제어자
- public 접근 제어자: 어디서나 접근 가능
- protected 접근 제어자: 같은 패키지 + 상속 관계에서 접근 가능
- default 접근 제어자: 같은 패키지 내에서 사용
- private 접근 제어자: 클래스 내부에서만 접근
public class Dog {
// 은닉된 멤버변수 -> 현재 클래스 내에서만 접근 가능
private String name;
private int age;
public void Dog(String name, int age){
this.name = name;
this.age = age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
}
7) 추상 클래스, 인터페이스
7 - 1. 추상 클래스
공통 속성과 동작을 공유하는 "부모 클래스" 역할
ex) 동물이라는 공통 틀, abstract 메서드는 그 틀이 반드시 행해야하는 동작
- abstract 메서드를 선언 할 수 있는 클래스
- 직접 인스턴스를 만들 수 없음
- extends 로 구현 (단일 상속)
abstract class Animal {
abstract void speak(); // 반드시 자식이 구현해야 함
void eat() {
System.out.println("먹는다.");
}
}
class Cat extends Animal {
@Override
void speak() {
System.out.println("야옹!");
}
}
7 - 2. 인터페이스
인터페이스는 클래스가 반드시 해야하는 기능을 정의
여러 기능의 인터페이스 구현 후 여러 클래스에서 사용 (다형성)
- 인터페이스는 함수의 접근 제어자, 리턴 타입, 메서드 이름만 정의
- 모든 메서드는 public abstract, 변수는 public static final
- implements로 구현 (다중 구현 가능)
interface Flyable {
void fly();
}
interface Swimmable {
void swim();
}
class Duck implements Flyable, Swimmable {
public void fly() {
System.out.println("오리가 난다!");
}
public void swim() {
System.out.println("오리가 수영한다!");
}
}
8) 배열, 컬렉션
8 - 1. 배열
같은 종류의 여러 데이터를 크기가 고정된 공간에 저장
int[] arr = new int[3];
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
System.out.println(arr.length); // 3
8 - 2. 컬렉션
📦 컬렉션의 3가지 큰 분류
| 분류 | 특징 | 주요 클래스 |
| List | 순서 O, 중복 O | ArrayList, LinkedList |
| Set | 순서 X, 중복 X | HashSet, TreeSet |
| Map | 키-값 쌍 저장 | HashMap, TreeMap |
8 - 2 - 1. List
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("apple"); // 중복 허용
System.out.println(list); // [apple, banana, apple]
8 - 2 - 2. Set
Set<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
set.add("apple"); // 무시됨
System.out.println(set); // [banana, apple] (순서 랜덤)
8 - 2 - 3. Map
Map<String, Integer> map = new HashMap<>();
map.put("apple", 3);
map.put("banana", 5);
map.put("apple", 10); // 키가 같으면 값이 덮어씀
System.out.println(map.get("apple")); // 10
컬렉션의 다양한 메서드
- add(E e) : 데이터를 추가
- put(E key, E value)
- remove(Object o) : 데이터를 삭제
- get(int index) : 지정된 인덱스에 해당하는 데이터 반환
- set(int index, E e) : 지정된 인덱스에 해당하는 데이터 변경
- size() : 저장된 데이터의 개수 반환
- contains(Object o) : 지정된 데이터 포함되어 있는지 확인
- isEmpty() : 비어있는 상태인지 확인 boolean값 반환
9) 제네릭
데이터 타입을 파라미터화하여 컴파일 시 타입 안정성을 제공
제네릭을 사용하지 않으면
List list = new ArrayList();
list.add("hello");
list.add(123); // 오류는 안 나지만 타입 섞임
String str = (String) list.get(0); // 형변환 필요
제네릭을 사용하면
List<String> list = new ArrayList<>();
list.add("hello");
// list.add(123); // 컴파일 오류 발생! 안전함
String str = list.get(0); // 형변환 없이 바로 사용 가능
클래스에서 제네릭 사용
class Box<T> {
private T value;
public void set(T value) {
this.value = value;
}
public T get() {
return value;
}
}
10) 스택과 큐
10 - 1.스택(Stack)
LIFO 구조 (Last In, First Out)
→ 마지막에 넣은 데이터가 제일 먼저 나옴
| push() | 데이터 넣기 |
| pop() | 데이터 꺼내기 (제거됨) |
| peek() | 맨 위 데이터 보기 (제거 안됨) |
| isEmpty() | 비었는지 확인 |
public class Main {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(10);
stack.push(20);
stack.push(30);
System.out.println(stack.pop()); // 30
System.out.println(stack.peek()); // 20
System.out.println(stack.isEmpty()); // false
}
}
10 - 2. 큐(Queue)
FIFO 구조 (First In, First Out)
→ 먼저 넣은 데이터가 제일 먼저 나옴
| offer() | 데이터 넣기 |
| poll() | 데이터 꺼내기 (제거됨) |
| peek() | 맨 앞 데이터 보기 |
| isEmpty() | 비었는지 확인 |
public class Main {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
queue.offer("A");
queue.offer("B");
queue.offer("C");
System.out.println(queue.poll()); // A
System.out.println(queue.peek()); // B
System.out.println(queue.isEmpty()); // false
}
}
11) 람다식
익명 함수를 간결하게 표현하는 방식
기본 문법
(매개변수) -> { 실행문 }
ex)
(a, b) -> a + b
예제 비교
전통 방식 (익명 클래스)
Runnable r = new Runnable() {
public void run() {
System.out.println("Hello!");
}
};
람다식 방식
Runnable r = () -> System.out.println("Hello!");
람다식을 쓰기위한 조건
하나의 메서드만 가진 인터페이스에서 사용
ex)
@FunctionalInterface
interface Calculator {
int calculate(int a, int b);
}
public class Main {
public static void main(String[] args) {
// 람다식으로 함수 구현
Calculator add = (a, b) -> a + b;
Calculator multiply = (a, b) -> a * b;
System.out.println(add.calculate(3, 5)); // 8
System.out.println(multiply.calculate(3, 5)); // 15
}
}
람다식의 사용 예시
| 상황 | 예시 |
| 콜백 함수 | 버튼 클릭 이벤트 |
| 반복 처리 | 리스트 순회 (forEach) |
| 정렬 기준 | Collections.sort() |
| 필터링 | stream().filter() |
| 익명 클래스가 너무 길어질 때 | Runnable, Comparator, 등등 |
ex) 반복 처리
public class Main {
public static void main(String[] args) {
List<String> names = Arrays.asList("Kim", "Lee", "Park");
names.forEach(name -> System.out.println("Hello, " + name));
}
}
Stream 이란?
데이터의 흐름을 간편하게 처리할 수 있는 API
Stream의 기본 흐름
collection.stream()
.중간연산()
.중간연산()
.최종연산();
자주 쓰이는 중간 연산과 최종 연산
| 중간연산 | filter() | 조건에 맞는 값만 통과 |
| map() | 값 변형 | |
| sorted() | 정렬 | |
| distinct() | 중복 제거 | |
| 최종연산 | collect() | 리스트 등으로 수집 |
| forEach() | 하나씩 출력 또는 처리 | |
| count() | 개수 세기 | |
| anyMatch() | 하나라도 조건 만족하는지 확인 |
람다식, 스트림의 실전 예제
ex) 숫자 리스트에서 짝수만 제곱해서 리스트화
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> result = numbers.stream()
.filter(n -> n % 2 == 0) // 짝수만
.map(n -> n * n) // 제곱
.collect(Collectors.toList()); // 리스트로 변환
System.out.println(result); // [4, 16, 36]
ex) 문자열 리스트에서 길이 4 이상만 뽑기
List<String> words = Arrays.asList("java", "ai", "stream", "lambda");
words.stream()
.filter(word -> word.length() >= 4)
.forEach(System.out::println);
'Language & Framework > Java' 카테고리의 다른 글
| Java 수학 관련 함수 (0) | 2025.09.15 |
|---|---|
| Java 문자열 관련 함수 (0) | 2025.09.12 |
| Java 컬렉션 주요 함수 (0) | 2025.09.12 |