본문 바로가기
BACK-END/JAVA

JAVA | 20251120

by codechu 2025. 11. 20.

클래스

  • 클래스( CLASS )는 서로 관련있는 멤버( 멤버 변수 및 메서드 등)의 집합이다. 
  • 어떠한 클래스를 포함하는 java 파일은 접근 제한자가 public 이거나 default 이고 그이름이 파일의 이름과 같은 구성요소를 한 개 포함하여야 한다.
  • 명명법 : 파스칼 케이스 PascalCase
  • 클래스의 구조는 아래와 같다.
[접근 제한자] abstract final ? class [class name] [extendes 부모 클래스]? [implements 인터페이스]?{
[멤버]
}
  •  abstract : 해당 클래스를 추상 클래스로 지정한다. 해당 클래스가 추상 메서드를 한개 이상 가지려면 반드시 추상 클래스로 지정하여야 한다. 다만 , 추상메서드가 없어도 클래스는 추상적일 수 있다. 
    • 추상 메서드가 없어도 추상 클래스일 수 있다.
    • 추상 클래스가 아닌데 추상 메서드를 가질 수는 없다.
  • final : 해당 클래스를 최종 클래스로 지정한다. 최종 클래스는 상속 대장(부모)이 될 수 없다.
  • extends : 상속 받을 클래스( 상속 대상, 부모 )를 지정한다.
  • implements : 구현할 인터페이스들을 지정한다.

 

객체

  • 객체(intstance) 는 객체화 연산(new)을 통해 참조 타입이 객체화된 대상을 의미한다.

생성자

  • 생성자(constructor)는 어떠한 타입이 객체화될 때 반드시 호출되는 일종의 특수한 메서드이다.
  • 객체화 연산(new)시 타입 뒤에 적는 괄호는() 생성자 호출이다.
Stirng str = new String("hello");
                         † 생성자 호출

 

  • 생성자의 구조는 아래와 같다.(따로 생성하지 않으면 기본생성자가 있음)
[접근 제한부] [클래스 이름] ([매개 변수,...]?) (...
[구현부]
)
public class Study1{
public study1(){
 sout("hello")

main{

  sout("before")
  Study1 study1 = new Study1(); // hello 출력 생성자 생성
  sout("after")
  
  
}
  • 생성자의 이름은 반드시 클래스의 이름과 일치해야 한다.
  • 생성자는 반환타입을 가지지 않는다.(void 또한 명시하지 않는다. 명시하는 순간 일반 메서드가 됨)
  • 생성자는 추상적(abstract)이거나 최종적(final)이거나, 정적(static)일 수 없다.
  • 객체화 연산 외에는 임의로 호출할 수 없다.
  • 생성자 구현부의 첫 구문은 반드시 부모 클래스의 생성자 호출(super(...))이거나 자산 클래스의 생성자 호출(this(...))이어야 한다. 이를 생략할 경우 첫 구문은 인자를 전달하지 않는 부모 생성자 호출(super())인 것으로 한다. -> 부모가 먼저 호출되고 그 다음 자식이 생성되어야 순서가 맞음 대신 super나 this를 선언하지 않으면 자동으로 자바다 만들어줌
  • 생성자가 가지고 있는 로직이 모두 실행되었을 때 객체화를 완료하였다고 한다.

 


 

캡슐화

  • 캡슐화(Encapsulation)는 주로 엔티티(Entity) 클래스, 값 객체(VO, value object) , 데이터 전달객체 (DTO, data transfer object) 등이 가지는 멤버 변수의 외부 접근을 차단하고, 필요에 따라 해당 멤버 변수를 반환해주기 위한 게터 및 새로운 값을 할당하고 해당 값에 대한 논리를 작성하기 위한 세터 메서드를 별로도 구현하는 방법을 의미한다.
  • 추가적으로 엔티티 클래스 작성시, 대상이 되는 테이블의 기본 키인 열(들)에 대해 equals 및 hashCode 메서드를 재정의한다.
  • 필요에 따라 아무런 인자도 전달 받지 않는 생성자와 모든 멤버 변수에 대응하는 전달인자를 전달 받는 생성자를 생성해 활용하기도 한다.

 

상속

  • 상속(inheritance)은 어떠한 클래스가 다른 클래스로 하여금 다른 클래스의 기능을 그대로 돌려받아 추가적인 기능을 확장시키기 위해 사용한다.
  • 어떠한 클래스에게상속 받을 클래스를 명시하지 않을 경우 모든 클래스는 자동으로 Object (java.lang.object) 클래스를 상속 받는다.
  • 상속 받을 클래스를 명시하는 것이 보다 상위 계층의 상속 클래스에 대한 기능 확장을 상실하는 것을 의미하지 않는다.
  • 다중 상속 관계는 허용되지 않으며 한 개의 클래스를 상속 받아야 한다.

다형성

  • 다형성(polymorphism)은 어떠한 타입을 가지는 객체가 다른 타입으로 변할 수 있는 성질을 의미한다.
  • 어떠한 객체가 다른 타입으로 형변환될 경우 해당 객체가 가지고 있는 멤버에 대한 접근(일시적으로)제한되고, 변환된 타입의 멤버까지만 접근할 수 있게 된다.
  • 클래스간의 상속 관계
    • 자식 객체는 부모 타입에 묵시적 형변환을 통해 할당될 수 있다.
    • 부모 객체는 자식 타입에 묵시적 형변환을 통해 할당될 수 없다.

  • 클래스와 인터페이스의 구현 관계
    • 특정 인터페이스를 구현하는 클래스 객체는인터페이스 타입에 할당될 수 있다. // 형변환이 가능한지 확인을 하고 싶으면 instance of = true 가 나오면 형 변환 가능
class Human {
    void walk() {
        System.out.println("사람이 걷는다");
    }
}

class Worm {
    void crawl() {
        System.out.println("애벌레가 기어간다");
    }
}

public class Example {
    public static void main(String[] args) {

        Object humen1 = new Human(); // 실제로는 Human 객체
        Object humen2 = new Worm();  // 실제로는 Worm 객체

        checkType(humen1);
        checkType(humen2);
    }

    static void checkType(Object obj) {

        if (obj instanceof Human) {
            Human h = (Human) obj;  // 형변환 성공
            System.out.println("Human 타입이 맞음 → 형변환 OK");
            h.walk();
        }

        else if (obj instanceof Worm) {
            Worm w = (Worm) obj;    // 형변환 성공
            System.out.println("Worm 타입이 맞음 → 형변환 OK");
            w.crawl();
        }

        else {
            System.out.println("형변환 불가능한 타입입니다.");
        }
    }
}

 

패키지

  • 패키지(Package)는 동일한 이름을 가지는 클래스(등의 구성요소) 가 동일한 프로젝트에 존재할 수 없는 문제를 해결하기 위해 존재하는 디렉토리이다.
  • 주로 구성요소를 종류별, 목적별로 구분해 위치시키기 위해 사용한다.
  • 루트 패키지(root package)의 경로는 주로 [ 소유하고 있는 도메인의 역순]. [ 아티팩트 ID] 형식으로 구성된다.
  • 명명법 : 전체 소문자 , 단어 구분하지 않음.

접근 제한자

  • 접근 제한자(Access Modifier) 는 특징 멤버에 접근할 수 있는 대상을 제한하기 위해 사용한다.
  • public : 제약 없음
  • protected : 동일한 패키지 경로에 있거나, 상속 관계에 있는 대상만 접근 가능.
  • (default) : 동일한 패키지 경로에 있는 대상만 접근 가능.
  • private : 동일한 클래스 내에서만 접근 가능.

 

 

인터페이스 (' 규칙(약속)’을 만들고, ‘여러 클래스가 같은 방식으로 행동하도록 강제하기 위해' )

  • 인터페이스(interface)는 특징(직렬)계통에 공통적으로 적용되는 사람이 아닌, 특정 클래스에 대한 속성이나 부분적으로 특화되어 있는 기능의 집합에 대한 틀을 제공하기 위해 사용한다.
  • 명명법 : 파스칼 케이스
  • 인터페이스의 구조는 아래와 같다.
[접근 제한자] interface [인터페이스 이름] [extends 상속 인터페이스,...] {
[멤버]
}
  • 인터페이스는 여러개의 인터페이스를 상속(다중상속 가능) 받을 수 있지만, 클래스를 상속받을 수는 없다.
  • 인터페이스가 가지는 모든 멤버의 접근 제한자는 기본적으로 public 이다.
  • 인터페이스가 가지는 모든 메서드는 기본적으로 추상적(abstract)이다. (인터페이스가 가지는 메서드는 모두 구현 해야함 -> private ,defualt 는 예외)
  • 단, 인터페이스가 가지는 메서드의 접근 제한자가 private 일 경우, 그 메서드는 추상적이지 않아야 하며 구현부를 가져야 한다.
  • 인터페이스가 가지는 모든 멤버 변수는 정적이고 읽기 전용(static final)이다. 
  • 단, 메서드의 반환 타입 앞에 default 라는 키워드를 추가해 해당 메서드가 기본 동작 방식을 가진다고 정의하고, 구현부를 정의할 수 있다. 이때, default 는 접근 제한자와 상관이 없음에 유의한다. 
// ================================================
// 인터페이스 : "해야 할 기능 이름만 정의하는 설계도"
 ex ) 움직인다는 공통적인 기능은 있으나 각 동물마다 움직이는 세부사항은 다르기 때문에 
 인터페이스로 공동의 '움직인다'를 구현하고 기어간다 뛴다를 
 각각의 클래스에 세부구현 하는거임
// ================================================
interface Movable {
    // 모든 인터페이스 메서드는 기본적으로 public abstract
    void move();  
}
// ================================================
// 구현 클래스 1 : Dog
// move()를 Dog만의 방식으로 구현(오버라이딩)
// ================================================
class Dog implements Movable {
    @Override
    public void move() {
        System.out.println("강아지가 네 발로 빠르게 뛴다!");
    }
}
// ================================================
// 구현 클래스 2 : Cat
// ================================================
class Cat implements Movable {
    @Override
    public void move() {
        System.out.println("고양이가 살금살금 걷는다!");
    }
}
// ================================================
// 구현 클래스 3 : Robot
// ================================================
class Robot implements Movable {
    @Override
    public void move() {
        System.out.println("로봇이 바퀴로 굴러간다!");
    }
}
// ================================================
// Main 클래스 — 다형성(polymorphism) 핵심 예제
// 부모 타입(Movable) 하나로 여러 자식 객체를 다룰 수 있음
// ================================================
public class Main {
    public static void main(String[] args) {

        // 인터페이스 타입으로 선언 → 자식 객체를 담을 수 있다.
        Movable m1 = new Dog();   // Dog는 Movable을 구현했기 때문에 가능
        Movable m2 = new Cat();
        Movable m3 = new Robot();

        // 다형성: 같은 move() 메서드를 호출하지만 결과는 다르게 나온다.
        m1.move();   // 강아지가 네 발로 빠르게 뛴다!
        m2.move();   // 고양이가 살금살금 걷는다!
        m3.move();   // 로봇이 바퀴로 굴러간다!

        // ----------------------------------------------
        // instanceof 예제 : 실제 객체 타입 확인
        // ----------------------------------------------
        if (m1 instanceof Dog) {
            System.out.println("m1은 Dog 객체가 맞습니다!");
        }

        if (m3 instanceof Robot) {
            System.out.println("m3은 Robot 객체입니다!");
        }
    }
}

 

'BACK-END > JAVA' 카테고리의 다른 글

JAVA | 251119  (1) 2025.11.20
JAVA | 20251118 연산자  (0) 2025.11.19
JAVA | 20251117  (0) 2025.11.17
[자바] 계산기 과제 TIL  (0) 2025.04.23
[자바 프로그래밍 기초] 예외(Exception)와 예외처리 (try- catch)  (0) 2025.04.17