반응형

* 형변환

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Main {
    public static void main(String[] args) throws Exception {
        int a = 65;
        System.out.println("Integer to Character : " + (char) a);           //A
        System.out.println("Integer to String : " + String.valueOf(a));     //65
 
        char ch = '3';
        char[] ch2 = {'a','b'};
        System.out.println("Character to Integer : " + ((int) ch - '0'));   //3
        System.out.println("Character to String : " + String.valueOf(ch));  //3
        System.out.println("Character to String : " + String.valueOf(ch2)); //ab
 
        String s = "9";
        String s2 = "123";
        System.out.println("String to Integer : " + Integer.parseInt(s));   //9
        System.out.println("String to Character : " + s.charAt(0));         //9
        System.out.println("String to Character : " + Arrays.toString(s2.toCharArray()));   // [1, 2, 3]
    }
}
cs

 

스텍

Stack<Integer> stack = new Stack<>(); //int형 스택 선언

push
pop

Queue<Integer> queue = new LinkedList<>();

add
poll

우선순위 큐

PriorityQueue<Integer> pq = new PriorityQueue<>(); 

add 
pop
peek

Array

int[] arr = new int[4];

Arrays.sort();
Arrays.sort(arr, Collections.reverseOrder());
arr.length

 

ArrayList

ArrayList<Integer> alist = new ArrayList<>();

add
remove
get
alist.size();

String[] array = arrayList.toArray(new String[arrayList.size()]);	// ArrayList -> Array
ArrayList<String> arrayList = new ArrayList<>(Arrays.asList(array));	// Array -> ArrayList

HashSet

HashSet hs = new HashSet<>();

add(key)
contains(key)


HashMap

HashMap<String, Integer> hm = new HashMap<>();

put(key, value)
get(key)
containsKey(key)

 

 

 

 

반응형
반응형

Java를 사용하다 보면 형변환할 일이 많이 있다.

int <> char <> String 으로의 형변환에 대해 알아보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Main {
    public static void main(String[] args) throws Exception {
        int a = 65;
        System.out.println("Integer to Character : " + (char) a);           //A
        System.out.println("Integer to String : " + String.valueOf(a));     //65
 
        char ch = '3';
        char[] ch2 = {'a','b'};
        System.out.println("Character to Integer : " + ((int) ch - '0'));   //3
        System.out.println("Character to String : " + String.valueOf(ch));  //3
        System.out.println("Character to String : " + String.valueOf(ch2)); //ab
 
        String s = "9";
        String s2 = "123";
        System.out.println("String to Integer : " + Integer.parseInt(s));   //9
        System.out.println("String to Character : " + s.charAt(0));         //9
        System.out.println("String to Character : " + Arrays.toString(s2.toCharArray()));   // [1, 2, 3]
    }
}
cs

< 유의 사항 >

char to int에서 숫자를 넘기는 경우 '0'을 해야 한다. (아스키코드값을 넘기기 때문)

char to string에서 char배열인 경우 String.valueOf를 사용하면 char배열 글자가 서로 붙어서 문자열로 넘어간다.

String to char에서 문자 길이가 1이라면 charAt으로 넘기면 된다.

String to char에서 문자 길이가 2이상이라면 toCharArray를 이용해 char배열로 넘긴다.

반응형
반응형

* 무분별한 if-else 줄이는 코딩 방법(Callback Hell 탈출)

if-else는 프로그래밍을 하면서 필수적으로 사용된다.

하지만 무분별한 if-else문 남용은 가독성을 떨어트려 이해하기 어려운 코드가 된다.

특히, JS에서 많이 사용되는 Callback Hell이라고 불리는 문제를 해결하는 방법을 알아보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Callback Hell
void getConnection() {
    Server server = getServer();
    if (server != null) {
        Client client = server.getClient();
        if (client != null) {
            Connection con = con.getConnection();
            if (con != null) {
                // 실제 처리할 로직
            }
        }
    }
}
 
cs

위 코드는 Callback은 아니지만, 무분별한 if문 남발로 가독성이 떨어지는 코드이다.

이를 해결할 수 있는 방법은 if문에서 예외 처리해야할 부분을 잡아서 처리하는 방법이 좋다.

예외 처리를 미리 해주면 단순 프로그래밍시만 아니라 Backtracking이나 DFS같은 재귀함수를 쓸 때도 무한루프에 빠지지 않을 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void getConnection() {
    Server server = getServer();
    if (server == null) {
        return;
    }
    Client client = server.getClient();
    if (client == null) {
        return;
    }
    Connection con = con.getConnection();
    if (con == null) {
        return;
    }
    // 실제 처리할 로직
}
cs

위와 같이 if문으로 예외 처리를 통해 바로 return으로 함수를 종료하면 가독성이 높아진다.

또한, if문 조건에는 주로 간단한 내용을 조건으로 주로 걸고, 복잡한 내용은 else문에 작성하는 것이 일반적이다.

1
2
3
4
5
6
7
8
9
10
11
public int checkNumber(int inputNumber) {
    if (inputNumber == 1) {
        //처리    
    } else if (inputNumber == 2) {
        //처리
    } else if (inputNumber == 3) {
        //처리
    } else if (inputNumber == 4) {
        //처리
    }
}
cs

위 코드 역시 inputNumber가 1인 경우에도 끝까지 확인을 해야한다는 단점이 있다.

이러한 경우 역시 if문으로 조건을 만족하면 return 시키는 방법이 효율적이라고 할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public int checkNumber(int inputNumber) {
    if (inputNumber == 1) {
        //처리
        return ret;
    }
    if (inputNumber == 2) {
        //처리
        return ret;
    }
    if (inputNumber == 3) {
        //처리
        return ret;
    }
    if (inputNumber == 4) {
        //처리
        return ret;
    }
}
cs


* 참고

Java 성능 좋은 분기문을 쓰는 방법, if문에서 연산 순서 (if문에서 좋은 퍼포먼스를 만들기, && || 연산자 우선 순위)

if문은 가장 필수 적인 요소 하지만 골치 아픈 녀석(if 안쓰는법)

반응형
반응형

* OOP(객체지향 프로그래밍)이란?

프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법

장점         - 코드 재사용이 용이하다.

- 유지보수가 쉽다.

단점         - 처리속도가 상대적으로 느리다.

- 설계시에 많은 시간과 노력이 필요하다.


* 클래스와 인스턴스(객체)

클래스 : 객체의 속성(Attribute)과 행위(Behavior)를 변수와 메소드로 정의한 것

객체 : 클래스에 정의된 내용을 바탕으로 실제 메모리에 할당된 데이터


* OOP(객체지향 프로그래밍) 4가지 특징(캡상추다)

1. 캡슐화

객체의 멤버변수는 private로 설정하여 외부에서 접근을 거부하고, Getter/Setter를 public으로 선언하여 객체의 속성에 접근하도록 사용한다.

그 이유는 객체의 무결성을 보장하기 위함인데, 객체 필드에 직접적인 접근을 거부하고 잘못된 입력에 대해 Getter/Setter는 사전에 처리 및 제한할 수 있기 때문이다.

2. 상속

클래스의 멤버와 함수를 다른 클래스에 물려주거나, 물려 받는 것을 말하며 이를 통해 재사용성이 높아진다.

3. 추상화

중요한 정보만을 표현함으로써 공통의 속성이나 기능을 묶어 이를 하나의 클래스로 다루는 것

4. 다형성

오버로딩과 오버라이딩을 통해 다른 클래스의 객체가 같은 메시지를 받았을 때 각자의 방식으로 동작하는 능력

오버로딩(Overloadding)    : 상위 클래스의 이름과 return값이 같지만, 매개변수를 다른 메소드를 만들어 가독성을 높이는 방법

오버라이딩(Overriding)     : 상위 클래스에 존재하는 메소드를 하위 클래스에서 용도에 맞게 재정의 하여 재사용성을 높이는 방법


* Call by Value vs Call by Reference

# Call by Value (값에 의한 호출)        << Java

함수가 호출될 때, 메모리 공간 안에서는 함수를 위한 별도의 임시 공간이 생성된다.

함수 호출시 인자로 전달되는 변수의 값을 복사하여 함수의 인자로 전달한다.

복사된 인자는 함수 안에서 지역적으로 사용되는 local value의 특성을 가진다.

따라서 함수 안에서 인자의 값이 변경되어도, 외부의 변수의 값은 변경되지 않는다.

# Call by Reference (참조에 의한 호출)

함수가 호출될 때, 메모리 공간 안에서는 함수를 위한 별도의 임시 공간이 생성된다.

함수 호출시 인자로 전달되는 변수의 레퍼런스를 전달한다. (해당 변수를 가리킨다.)

따라서 함수 안에서 인자의 값이 변경되면, 인자로 전달된 변수의 값도 함께 변경된다.

cf) Java는 자료형은(Integer, Long, String, ...) Call by Value이다. 하지만 배열, 클래스는 Call by Reference로 생각하는 것이 편하다.


* StringBuffer vs StringBuilder

StringBuffer    : Multi-Thread 환경에서 동기화가 가능하기 때문에 Thread-Safe하다.

StringBuilder   : 동기화를 지원하지 않기 때문에 멀티쓰레드환경에서는 적합하지 않지만 Single-Thread 환경에서 빠르다.


* Annotation

어노테이션이란 본래 주석이란 뜻으로, 인터페이스를 기반으로 한 문법으로 주석처럼 코드에 달아 클래스에 특별한 의미를 부여하거나 기능을 주입할 수 있다.

컴파일러에게 코드 문법 에러를 체크하도록 정보를 제공 및 실행 시(런타임 시) 특정 기능을 실행하도록 정보를 제공한다.

어노테이션은 컴파일러에게 이 소스코드를 어떻게 처리해야 되는 것인지 표시를 해준다. 

예를들어 내장 어노테이션인 @Override 경우 해당 메소드가 부모클래스를 오버라이딩 한 메소드라고 컴파일러에게 미리 일러주는 것이다. 

따라서 컴파일러는 런타임 이전에 이 메소드가 문제없이 오버라이딩 되었는지 검사한다.


* Generic

제네릭 타입을 이용해서 컴파일 과정에서 타입 체크를 할 수 있다.

제네릭은 클래스와 인터페이스, 메소드를 정의할 때 타입 파라미터로 사용한다.

1. 컴파일할 때 타입을 체크해서 에러를 사전에 잡을 수 있다.

2. 컴파일러가 타입캐스팅을 해주기 때문에 개발자가 편리하다.

3. 타입만 다르고 코드의 내용이 대부분 일치할 때, 코드의 재사용성이 좋아진다.

반응형

'∙Java' 카테고리의 다른 글

[JAVA] int, char, String 형변환 정리  (1) 2019.04.30
[Java] if-else 줄이는 코딩방법  (0) 2019.01.17
[Java] ==와 equals()의 차이  (0) 2019.01.10
[Java] Abstract Class와 Interface  (0) 2019.01.10
반응형

Java를 사용하다 보면 언제 equals를 사용해야 하고, 언제 ==를 사용해야 하는 지 헷갈리는 경우가 있다.

예시를 통해 차이점을 알아보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.io.*;
import java.util.*;
 
public class Main {
    public static void main(String[] args) throws Exception {
        String a = "aaa";
        String b = a;
        String c = new String("aaa");
        String d = new String("aaa");
        System.out.println(System.identityHashCode(a));         //1627674070
        System.out.println(System.identityHashCode(b));         //1627674070
        System.out.println(System.identityHashCode(c));         //1360875712
        System.out.println(System.identityHashCode(d));         //1625635731
        System.out.println("========================");
        System.out.println("a == b : " + (a == b));             //True
        System.out.println("a == c : " + (a == c));             //False
        System.out.println("c == d : " + (c == d));             //False
        System.out.println("a.equals(b) : " + a.equals(b));     //True
        System.out.println("a.equals(c) : " + a.equals(c));     //True
        System.out.println("c.equals(d) : " + b.equals(d));     //True
    }
}
cs

위 코드를 실행한 결과값을 통해 다음과 같은 결론을 얻을 수 있다.

1. String a = "aaa" 와 String b = a는 같은 주소를 가르친다.

2. String c = new String("aaa")와 String d = new String("aaa")는 서로 다른 주소를 가르킨다.

3. == 연산은 같은 주소값인지를 비교한다. 즉, 안에 데이터는 비교하지 않는다.

4. equals 함수는 내부의 값을 비교한다.


여기서 4번 equals 함수 코드를 보면 구체적인 작동 방식을 알 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//String.java
public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}
cs

String에 구현된 equals 함수를 보면 length를 구해 while문으로 각 char 값을 비교하는 것을 확인할 수 있다.

반응형
반응형

* Abstract Class와 Interface의 공통점

추상클래스와 인터페이스는 선언만 있고 구현 내용이 없는 클래스다.

인터페이스와 추상클래스를 가지고 새로운 인스턴스(객체)를 생성할 수 없기 때문에 상속을 통해 자식 클래스에서만 객체를 생성할 수 있다.


* Abstract Class(추상 클래스)

extends 키워드를 통해 추상 클래스를 상속받는다.

추상클래스는 추상메서드(abstract method)가 하나라도 존재하는 클래스를 말한다. 

일부는 구현된 메소드도 있을 수 있고, 일부는 abstract method로 구현이 되어있지 않은 메소드도 있을 수 있다. 

즉, 구현된 메소드가 있을 수 있기 때문에 만들어야할 여러 클래스들의 공통점을 찾아 추상화시켜서 사용한다.


* Interface

implements 키워드를 통해 인터페이스를 상속받는다.

인터페이스는 쉽게 말하면 껍데기라고 말할 수 있고, 설계도 또는 명세라고 생각하면 된다.

모든 메소드가 추상 메소드이기 때문에 인터페이스를 상속받는 자식 클래스는 인터페이스의 모든 메소드를 필수적으로 구현해야 한다.


반응형
반응형

* Stack 영역

프로그램 실행 과정에서 메소드 실행 시 임시로 할당되고 해당 메소드가 끝나면 바로 소멸되는 것들이 저장된다.

Heap 영역에 생성된 Object 타입의 데이터의 참조값이 할당된다.


* Heap 영역

Java에서 new 명령을 통해 생성된 인스턴스 변수가 놓인다.

모든 Object 타입(Integer, String, ArrayList, ...)은 heap 영역에 생성된다.

GC에 의해 지위지지 않는 이상 Heap 영역에 계속 남아있다.


* 예제

1
2
3
4
5
6
public class Main {
    public static void main(String[] args) {
        int port = 4000;
        String host = "localhost";
    }
}
cs

위와 같은 코드가 있다고 가정했을 때, 해당하는 Stack 영역과 Heap 영역은 다음과 같다.


Stack 영역에는 Heap 영역에 생성된 Object 타입의 데이터 참조값이 할당된다.

만약, 여기서 host += :8080 이라는 코드를 추가하면, localhost에 값이 추가되는 것이 아니라 localhost:8080 라는 새로운 String Object가 할당되어 참조하게 된다.

즉, localhost는 unreachable 객체가 되어 GC에 의해 메모리에서 제거된다.


참조 : https://yaboong.github.io/java/2018/05/26/java-memory-management/

반응형
반응형

Java를 처음 시작하는 사람도 Class를 만들면 public static void main 를 쉽게 접할 수 있다.

왜 Java를 시작할 때 public static void main 이여야만 할까?


이러한 형식인 이유는 

하나하나 뜯어보면서 확인해보자.


public    : 모든 클래스에 접근이 가능한 접근 제어자

 >> private, default, protected의 경우 다른 클래스에서 Main을 사용하지 못하기 때문

static    : 프로그램 시작과 동시에 static으로 선언된 것들은 메모리에 호출되는데, 이렇게 호출된 static은 프로그램이 종료되는 시점까지 유지된다.

>> Main 함수의 경우 Java에서의 프로그램의 시작과 끝이기 때문에 Static으로 선언되어야 한다.

>> Singletone 

void      : 프로그램 자체가 종료가 되는 시점에서 어떤 특정 값이 반환되어도 아무 의미가 없다.


즉, 모든 클래스들이 접근 가능하여야 하고, 시작되기 전 메모리에 올려져 있어야 하며, return 값에는 의미가 없기 때문에 public static void main를 사용한다.

반응형

'∙Java' 카테고리의 다른 글

[Java] ==와 equals()의 차이  (0) 2019.01.10
[Java] Abstract Class와 Interface  (0) 2019.01.10
[Java] Stack 영역과 Heap 영역  (0) 2019.01.10
[Java] JVM의 개념과 작동 방식  (0) 2019.01.10