자바는 객체 지향 프로그래밍이 가능한 언어이다.
클래스란? 객체를 만들기전에 우리가 필요한 속성과 기능을 정의해놓은 하나의 설계도라고 생각하면 된다.
자바에서 제공하는 클래스는 필드(속성), 생성자, 메소드(기능)로 구성된다.
public class Car {
// 필드 혹은 클래스의 멤버 변수라고 부른다.
private String name;
private String color;
private int hp;
// 아무것도 없는 default 생성자
// Ex) new Car();
public Car() {
}
// 파라미터를 가지고 있는 생성자
// Ex) new Car("Benz", "white", 240);
public Car(String name, String color, int hp) {
this.name = name;
this.color = color;
this.hp = hp;
}
// 기능에 역할을 하는 메소드
// Car car = new Car("Benz", "white", 240);
// car.getName() --> "Benz"
// car.getColor() --> "white"
// car.getHp() --> 240
public String getName() {
return name;
}
public String getColor() {
return color;
}
public int getHp() {
return hp;
}
}
클래스, 멤버 변수, 메소드에서 사용될 수 있는 키워드
클래스로부터 객체를 만드는 과정을 클래스의 인스턴화(instantiate)라고 하며, Car 클래스로부터 만들어진 객체를 Car 클래스의 인스턴스(instance)라고 한다. 객체를 만드는 과정은 매우 간단하다.
public static void main(String[] args) {
// write your code here
Car car = new Car("Benz", "white", 210);
}
클래스명 변수명 = new 클래스명();
클래스의 객체를 참조하기 위한 참조변수를 선언한다.
변수에 new 키워드로 생성된 클래스의 주소를 참조변수에 저장한다.
메소드란 클래스내에 존재하는 함수로써 어떤 작업을 수행하기 위한 명령문들의 집합체이다. 주로 어떤 값을 입력받아서 그에 맞는 결과를 되돌려 주는 역할을 수행한다. 사용목적에 따라서 입력받는 값이 없을 수도 있고, 되돌려주는 결과 값이 없을 수도 있고, 둘다 없는 경우도 있다.
해당 객체에 기능을 담당하는 역할도 있지만 단순 반복적인 내용을 하나의 덩어리로 나타내기 위해 사용한다. tunningEngine 이라는 메소드를 보면
멤버 변수의 hs을 10씩 올려주는 메소드이다.
public void tunningEngine() {
int tunning = 10;
this.hp = tunning;
}
메소드는 크게 선언부와 구현부 두 부분으로 나뉘어져있고 선언부의는 리턴타입, 메소드이름, 그리고 괄호()에 매개변수를 선언하고, 구현부에는 메소드가 호출되었을 때 수행되어야 할 코드를 넣어주면 된다.
메소드가 호출될 때 선언부에 작성되어 있는 매개변수를 통해서 메소드가 작업을 수행할 때 필요한 값들을 받아서 처리한다.
괄호()안에 있는 매개변수는 지역변수로 갅되어 메소드 내에서만 사용이 가능하며 메소드가 종료되는 순간 메모리에서 제거되어 사용할 수 없다.
리턴타입은 메소드의 결과에 따라 어떤 타입으로 반환할 것인지에 대해 작성하는 부분이다. 메소드의 반환 값이 없는 경우 선언부에 void라는 키워드를 작성하면 되고, 반환 값이 있는 경우 return 키워드를 사용하여 구현부 맨 마지막에 작성하면 된다.
// 자동차의 엔진 마력을 가져오는 메소드.
public int getHp() {
return hp;
}
getHp 메소드는 int 타입에 hp의 값을 반환해주는 역할을 하는 매소드이다.
변수를 선언하고 초기화하는 것과 같은 개념으로 객체를 생성할 때 객체를 초기화 하기 위해 사용되는 것이 생성자이다.
public class Car {
private String name;
private String color;
private int hp;
// 아무것도 없는 default 생성자
// Ex) new Car();
public Car() {
}
// 파라미터를 가지고 있는 생성자
// Ex) new Car("Benz", "white", 240);
public Car(String name, String color, int hp) {
this.name = name;
this.color = color;
this.hp = hp;
}
}
생성자는 몇가지 특징을 가지고 있다.
클래스가 인스턴스화 되었을때 자기자신의 메모리 주소를 담고있는 키워드이다.
한마디로 저 여기 있어요~! ⭐️ 하는 녀석인거 같다.
클래스의 멤버 변수 이름과 메소드의 매개 변수 이름이 동일한 경우 이를 구분짓기 위해 this 키워드를 이용한다.
public class Car {
private String name;
private String color;
private int hp;
// 메소드에서 사용하는 파라미터의 이름과 클래스의 멤버변수가 동일한 경우
// this 키워드를 이용해 Car 객체의 자기 자신한태 있는 name, color, hp 알려준다.
public Car(String name, String color, int hp) {
this.name = name;
this.color = color;
this.hp = hp;
}
}
this 키워드가 클래스 내에 멤버 변수를 가리킨다 하면 this()는 클래스 내부에 있는 생성자를 의미한다.
자기 자신의 클래스 생성자를 호출한다. 주의할 점은 호출하는 곳의 this() 키워드가 맨 윗줄에 있어야 하며, 파라미터가 있는 생성자인 경우 this()안에 파라미터 타입에 맞게 입력해야 한다.
public class Car {
private String name;
private String color;
private int hp;
public Car(String name, String color, int hp) {
this.name = name;
this.color = color;
this.hp = hp;
}
public Car(int hp) {
this("BMW", "Black", hp);
}
}
Result : Car{engine=false, name='BMW', color='Black', hp=110}
public class Node {
private Node left;
private int value;
private Node right;
public Node(Node left, int value, Node right) {
this.left = left;
this.value = value;
this.right = right;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
}
트리의 예
(1)
↙ ↘
(2) (3)
↙ ↘ ↙
(4) (5) (6)
public class NodeTest {
@Test
@DisplayName("1 ~ 6까지의 노드 생성")
void setUp() {
Node node6 = new Node(null, 6, null);
Node node5 = new Node(null, 5, null);
Node node4 = new Node(null, 4, null);
Node node3 = new Node(node6, 3, null);
Node node2 = new Node(node4, 2, node5);
Node node1 = new Node(node2, 1, node3);
}
@Test
@DisplayName("노드의 child value값 확인")
void check_value_in_child_node() {
Node node6 = new Node(null, 6, null);
Node node5 = new Node(null, 5, null);
Node node4 = new Node(null, 4, null);
Node node3 = new Node(node6, 3, null);
Node node2 = new Node(node4, 2, node5);
Node node1 = new Node(node2, 1, node3);
// Node1의 child node value 확인
assertEquals(2, node1.getLeft().getValue());
assertEquals(3, node1.getRight().getValue());
assertEquals(4, node2.getLeft().getValue());
assertEquals(5, node2.getRight().getValue());
assertEquals(6, node3.getLeft().getValue());
}
}
Full Binary Tree
Perfect Binary Tree
Complete Binary Tree
public void inorder(Node node) {
if (node != null) {
inorder(node.getLeft());
System.out.println(node.getValue());
inorder(node.getRight());
}
}
public void preorder(Node node) {
if (node != null) {
System.out.println(node.getValue());
preorder(node.getLeft());
preorder(node.getRight());
}
}
public void postorder(Node node) {
if (node != null) {
postorder(node.getLeft());
postorder(node.getRight());
System.out.println(node.getValue());
}
}
public void bfs(Node node) {
Queue<Node> queue = new LinkedList<>();
queue.add(node);
while(!queue.isEmpty()){
Node current = queue.poll();
System.out.print(current.getValue() + " ");
if (current.getLeft() != null) queue.add(current.getLeft());
if (current.getRight() != null) queue.add(current.getRight());
}
}
public class Main {
public static void main(String[] args) {
Node node6 = new Node(null, 6, null);
Node node5 = new Node(null, 5, null);
Node node4 = new Node(null, 4, null);
Node node3 = new Node(node6, 3, null);
Node node2 = new Node(node4, 2, node5);
Node node1 = new Node(node2, 1, node3);
BinaryTree binaryTree = new BinaryTree();
binaryTree.setRoot(node1);
binaryTree.inorder(binaryTree.getRoot());
binaryTree.preorder(binaryTree.getRoot());
binaryTree.postorder(binaryTree.getRoot());
binaryTree.bfs(node1);
}
}
inorder : 4 2 5 1 6 3
preorder : 1 2 4 5 3 6
postorder : 4 5 2 6 3 1
bfs : 1 2 3 4 5 6