클래스

  • 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

AVL Tree

AVL Tree

BST (이진 탐색 트리)를 기반으로 둔 Tree. 어떤 노드를 기준으로 하더라도 왼쪽자식의 깊이와 오른쪽 자식의 깊이 차이가 1을 넘지 않는 트리 1. 용어 개념 정리 균형치 (Balance factor) : 자식노드의 깊이 차이 ( 왼쪽 서브트리의 높이 – 오른쪽 서브트리의 높이 ) BF는 -1, 0, 1이 기준이며, 이 범위를 벗어난다면, 그 트리의 균형은 깨진것이다. 2. 특징 BST의 모든 특징을 갖는다...

Read More
변수

변수

1. 변수 선언 1) 기본 방법 var a int var a int = 10 var b,c,d int = 1,2,3 //동시에 여러개 변수 선언도 가능하다. var키워드로 변수를 선언하고 변수명 다음 데이터 타입을 명시해주어야 하고, 선언만 하고 초기화를 해주지 않으면 go는 Zero value를 할당한다. Note Zero Value 숫자 = 0 bool = false string = "" 2) 타입 추론 var a = 10 var q,w,e = 1, true, "#" //동시에 여러개 변수 선언을 할때 다른...

Read More
상수

상수

상수는 Immutable(불변)한 특징을 갖으며 한 번 할당된 값을 변경할 수 없는 변수이다. const a int = 1 const b string = "hi" const d = 10 //자료형을 생략가능하다. f := 10 //이는 자동으로 var 형태의 변수로 선언이 되기 때문에 상수가 될 수 없다. var runTimeVar int = 1 const e = runTimeVar * 10 //runTimeVar는 런타임에 값이 할당되기 때문에 컴파일타임에 d의 값을 할...

Read More