클래스

  • Java
  • 2021년 2월 1일

객체 지향의 중심 객체를 정의하는 일종의 틀 같은 것으로 상태(변수) / 행동(메서드)이 있을 수 있다.

이로 인해 추상화, 캡슐화, 상속, 다형성 등을 가능하게 하여 개발 / 유지보수를 쉽게 해준다.



1. 클래스 정의하는 방법

class키워드를 통해 클래스를 새로 정의할 수 있다.

class Fruit{
    private String name;

    Fruit(String name){this.name = name;}

    public String getName(){
        return name;
    }
}

1) 필드

변수를 뜻하며 두가지 종류가 존재한다.

  • 인스턴스 변수 : Fruit이라는 객체를 새로 생성할때마다 각각 독립적인 값을 갖는 변수로 heap 영역에 저장 된다.
  • 클래스 변수 : 인스턴스 변수 앞에 static키워드를 붙여 선언한 변수이다. 딱 한번만 선언되는 변수로 static 영역에 할당되어 Fruit이라는 객체는 이 변수를 모두 공유한다.

2) 메서드

어떠한 행동을 정의한 형태로, 필드들을 수정하거나 참조, 반환을 할 수 있다.


3) 생성자

객체를 생성했을때 사용되는 일종의 메서드로 필드들을 초기화하는데 사용된다.


4) 접근 제어자

객체 내 정의된 필드, 메서드, 생성자들을 외부에서 접근을 제어하기 위한 키워드로 아래와 같이 4가지가 존재한다.

default는 생략이 가능하다.

접근 제어자동일 클래스동일 패키지자손 클래스그 외
public접근 가능접근가능접근가능접근가능
protected접근가능접근가능접근가능X
default접근가능접근가능XX
private접근가능XXX

5) 키워드 종류

필드, 메서드, 클래스 앞에 붙을수 있는 키워드들로 해당 키워드의 종류에 따라 기능이나 권한이 달라진다.

키워드목적
static메모리 할당을 한번만 한다. (클래스에 속한다.)
final클래스에 붙을 경우 상속이 불가능하고, 필드/메서드에 붙을 경우 상수로써 수정이 불가능하다.
abstract클래스 붙을 경우 객체 생성이 불가능하고, 이를 상속받아서만 이용이 가능하다. ( 메서드도 추상 클래스에서만 붙을 수 있고 선언만 가능하다.)
synchronized한개의 스레드만 접근이 가능하다.
volatile변수 접근을 캐시가 아닌 메모리로 접근한다.
transient객체 직렬화시 무시한다.



2. 객체 만드는 방법

public class ClassExample{
    public static void main(String[] args){
        Fruit apple = new Fruit("apple");
    }
}

new키워드를 이용하여 클래스의 생성자중 적절한 생성자로 객체를 만들어(heap 영역에 할당) 그 주소를 클래스 변수에 저장하는 방식으로 생성이 가능하다.

이 과정을 인스턴스화한다고 하고 이 클래스 변수(객체)를 인스턴스라고 한다.



3. 메소드 정의하는 방법

public String getName(){
    return name;
}

위 와 같이 접근 제어자 / (키워드) / 반환 타입 / 메서드 이름 / 매개변수로 선언 할 수 있고 코드 블럭( {} )를 통해 행동을 정의, 구현 할 수 있다.

  • 접근 제어자 : 위에서 설명한 접근제어자 4가지 중 한개가 올 수 있다.
  • 키워드 : 이도 마찬가지로 위에서 설명한 키워드중 여러개가 올 수 있으며 없을 수도 있다.
  • 반환 타입 : 함수의 구현부가 종료될때 반환하는 값의 타입을 지정해야 한다.
  • 메서드 이름 : 메서드를 구분하는 이름
  • 매개변수 : 함수에 사용할 매개변수를 정의 할 수 있으며 없을 수도 있고 여러개가 올수도 있다.



4. 생성자 정의하는 방법

class Fruit{
    private String name;

    //Fruit(){}

    Fruit(String name){this.name = name;}
}

반환타입을 빼고 클래스명을 이름으로한 메서드같이 정의할 수 있다.

이를 정의 하지 않는다면 주석과 같은 기본생성자를 컴파일러가 자동으로 생성해주지만, 매개변수가 있는 타입만 정의시 매개변수가 없는 기본생성자를 자동으로 생성해주지 않으니 기본생성자도 직접 생성해주어야한다.



5. this 키워드 이해하기

class Fruit{
    private String name;
    private int price;

    Fruit(){}
    Fruit(String name){this.name = name;}

    Fruit(String name, int price){
        this(name);
        this.price = price;
    }

    public String getName(){
        return name;
    }

    public static exStaticMethod(){
        System.out.println(this.name); //error
    }
}

this는 인스턴스된 객체 자기 자신을 가르키는 키워드로 Fruit이라는 생성자를 보면 name으로 변수명이 중복되지만 this키워드를 통해 객체내의 인스턴스 변수와 지역변수를 구분이 가능하게 한다.

이런 이유로 static 메서드에서 this를 통한 접근은 불가능하다.
static으로 선언하면 클래스에 종속되기 때문에 인스턴스를 갖지 않기 때문이다.

this()를 통해 클래스내의 생성자를 호출할 수도 있다.


6. 과제

Binary Tree와 BFS, DFS 구현

  • int value, Node left, right를 가지고 있어야 합니다.
  • BinrayTree라는 클래스를 정의하고 주어진 노드를 기준으로 출력하는 bfs(Node node)와 dfs(Node node) 메소드를 구현하세요.
  • DFS는 왼쪽, 루트, 오른쪽 순으로 순회하세요.

Node.java

package javaStudy.BinaryTree;

public class Node {
    private int value;
    private Node left;
    private Node right;

    public Node(int value) {
        this.value = value;
        this.left = null;
        this.right = null;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public Node getLeft() {
        return left;
    }

    public void setLeft(Node left) {
        this.left = left;
    }

    public Node getRight() {
        return right;
    }

    public void setRight(Node right) {
        this.right = right;
    }
}

BinaryTree.java

package javaStudy.BinaryTree;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class BinaryTree{
    private Node root;
    private List<Integer> bfsList;
    private List<Integer> dfsList;

    public BinaryTree(Node root) {
        this.root = root;
        this.bfsList = new ArrayList<>();
        this.dfsList = new ArrayList<>();
    }

    public void bfs(Node node){
        Queue<Node> q = new LinkedList<>();
        q.offer(node);

        while(!q.isEmpty()){
            Node n = q.poll();
            bfsList.add(n.getValue());

            if(n.getLeft() != null){
                q.offer(n.getLeft());
            }
            if(n.getRight() != null){
                q.offer(n.getRight());
            }
        }
    }

    public void dfs(Node node){
        if(node == null) return;
        dfsList.add(node.getValue());
        dfs(node.getLeft());
        dfs(node.getRight());
    }

    public void addNode(int value){
        Node node = root;
        Node newNode = new Node(value);

        if(node == null){
            root = newNode;
            return;
        }

        Node p = node;
        while(node != null){
            p = node;
            node = (node.getValue() > value) ? node.getLeft() : node.getRight();
        }
        if(p.getValue() > value){
            p.setLeft(newNode);
        }else{
            p.setRight(newNode);
        }
    }

    public List<Integer> getBfsList() {
        return bfsList;
    }

    public List<Integer> getDfsList() {
        return dfsList;
    }
}

BinaryTreeTest.java

package test.BinaryTree;

import javaStudy.BinaryTree.BinaryTree;
import javaStudy.BinaryTree.Node;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.List;

public class BinaryTreeTest {

    BinaryTree binaryTree;
    Node root;

    @BeforeEach
    void init(){
        root = new Node(2);
        binaryTree = new BinaryTree(root);
        binaryTree.addNode(1);
        binaryTree.addNode(22);
        binaryTree.addNode(12);
        binaryTree.addNode(23);
        binaryTree.addNode(24);
        binaryTree.addNode(13);
        binaryTree.addNode(5);
    }

    @Test
    void bfsTest(){
        binaryTree.bfs(root);
        List<Integer> arrayList = Arrays.asList(2,1,22,12,23,5,13,24);
        Assertions.assertEquals(arrayList,binaryTree.getBfsList());
    }
    @Test
    void dfsTest(){
        binaryTree.dfs(root);
        List<Integer> arrayList = Arrays.asList(2,1,22,12,5,13,23,24);
        Assertions.assertEquals(arrayList,binaryTree.getDfsList());
    }
}

Tags :

Related Posts

Spring boot와 EK스택 연결하기

Spring boot와 EK스택 연결하기

현재 진행하고있는 spring boot 프로젝트에 쿼리 통계를 위해 ElasticSearch와 Kibana를 도입하기로 했고 이에 맞게 로깅방법이나 세팅 방법을 기록하기 위해 글을 작성하게 됬다. diagram 구성은 다음과 같은데 서버로 EC2 프리티어를 사용하고 있어 사양이 안좋기 때문에 서버 내부에 logstash없이 filebeat를 이용하여 로그를 전송하기로 했다. ELK스택으로는 Elastic Cloud 프리티어를 이용해 빠르게 구축하는 것을 테스트해볼 생각이다....

Read More
[WSL2] Mysql 자동실행 설정하기

[WSL2] Mysql 자동실행 설정하기

[wsl2 설치가 안된 분은 여기를 참고하자 ] 나는 이번년도에 wsl2를 알게 되어 wsl2을 통해 편하게 개발을 진행하였다. 그런데, wsl2가 아직 여럿 불편한 점이 있었고 그 중 하나가 wsl2의 자동 실행 미지원이다. wsl2는 컴퓨터 시작시 자동 실행을 지원하지 않아 수동으로 ssh나 mysql, nginx와 같은 프로그램들을 실행시켜줘야하는 불편함이 있었다....

Read More
인터페이스

인터페이스

  • Java
  • 2021년 12월 8일

1. 인터페이스란? 자바의 다형성을 극대화하여 개발코드 수정을 줄이고 유지보수를 용이하게 하기 위함 다형성? 동일한 메시지를 수신했을 때 객체의 타입에 따라 다르게 응답할 수 있는 능력 1) 추상클래스와 인터페이스 차이 추상메서드를 가짐으로써 다형성을 극대화하면서 어떤 역할을 구현하는 방법(객체들이 따라야 하는 책임의 집합을 서술한 것)이라는 공통점이 있다....

Read More