728x90

접근 제어자

  • 접근제어자는 멤버 또는 클래스를 외부에서 접근하지 못하도록 제한하는 역할
  • 접근제어자는 생략 가능하며 생략했을 때는 자동으로 default를 뜻하게 된다.
  • 접근제어자가 default일 경우 접근제어자를 지정하지 않는다.
  • 접근제어자가 사용될 수 있는 곳 - 클래스, 멤버변수, 메소드, 생성자
    • private - 같은 클래스 내에서만 접근 가능
    • default - 같은 패키지 내에서만 접근 가능
    • protected - 같은 패키지 내에서, 그리고 다른 패키지의 자손 클래스에서 접근 가능
    • public - 접근 제한이 없다.
  • 접근 범위 - private < default < protected < public

 

접근 제어자를 이용한 캡슐화(encapsulation)

  • 접근 제어자를 사용하는 이유는 클래스의 내부에 선언된 데이터를 보호하기 위해.
  • 데이터가 유효한 값을 유지 또는 데이터를 외부에서 함부로 변경하지 못하도록 하기 위해 외부 접근 제한이 필요.
  • 이것을 객체지향 개념에서 캡슐화(encapsulation)이라 한다.

 

728x90
728x90

Overloading

  • overloading은 같은 이름의 메소드를 중복하여 정의하는 것
  • 매개변수의 개수나 타입을 다르게 하면, 하나의 이름으로 메소드를 작성할 수 있다
  • overloading은 서로 다른 시그니처를 갖는 여러 메소드를 같은 이름으로 정의하는 것
  • overloading은 사용되는 이름을 절약할 수 있다
  • 메소드를 호출할 때 전달해야 할 매개변수의 타입이나 개수에 대해 크게 신경 쓰지 않고 호출할 수 있다
  • overloading은 다형성(polymorphism)을 구현하는 방법 중 하나

 

Overloading 조건

  • 메소드의 이름이 같아야 한다.
  • 메소드의 시그치처, 즉 매개변수의 개수 또는 타입이 달라야 한다.

 

Overloading 예제

class Calc {

    static void display(int num1) { System.out.println(num1); }

    static void display(int num1, double num2) { System.out.println(num1 + num2); }

}

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

        Calc myCalc = new Calc();

        myCalc.display(10);
        myCalc.display(10, 3.14);

    }
}

// 10
// 13.14
728x90
728x90

Overriding

  • 부모 클래스로부터 상속받은 메소드를 자식 클래스에서 재정의하여 사용.
  • 상속의 관계에 있는 클래스 간에 하위 클래스가 상위 클래스와 완전 동일한 메소드를 덮어쓴다.
  • 이름과 반환형이 같으면서 매개변수의 개수와 타입까지 같은 메소드
  • 자식 클래스는 부모 클래스의 private 멤버를 제외한 모든 메소드를 상속 받는다.

 

Overriding 조건

  • 오버라이딩이란 메소드의 동작만을 재정의 하는 것. 메소드의 선언부는 기존 메소드와 완전히 동일해야 한다.
  • 메소드의 반환 타입은 부모 클래스의 반환 타입으로 변환할 수 있는 타입이라면 변경 가능.
  • 부모 클래스의 메소드보다 접근 제어자를 더 좁은 범위로 변경할 수 없다.
  • 부모 클래스의 메소드보다 더 큰 범위의 예외를 선언할 수 없다.

 

Overriding 예제

class Parent {
    void display() { System.out.println("부모 클래스의 display() 메소드입니다."); }
}

class Child extends Parent {
    void display() { System.out.println("자식 클래스의 display() 메소드입니다."); }
}
 

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

        Parent pa = new Parent();

        pa.display();

        Child ch = new Child();

        ch.display();

        Parent pc = new Child();

        pc.display(); 
        
    }
}

// 부모 클래스의 display() 메소드입니다.
// 자식 클래스의 display() 메소드입니다.
// 자식 클래스의 display() 메소드입니다.
728x90
728x90

Immutable Object

  • 불변객체란 한번 객체가 생성되면 그 상태를 바꿀 수 없는 객체
  • JAVA의 대표적인 불변객체는 String이 있다.

 

JAVA의 String

// ex)
String str = "abc";
str = "def";

위 예제는 str변수의 값이 바뀐 것이라고 착각하기 쉽다.

하지만 "def"라는 새로운 객체가 생성되고 str변수가 "def"를 참조 한 것이다.

원래 "abc"객체의 값은 그대로 "abc"로 남아있다. 더이상 참조되지 않는 것이다.

불변객체는 new 인스턴스로 재할당하는 것 외에는 값을 바꿀 수 없다.

 

Immutable Object 정의 방법

  • "setter" 메소드를 사용하지 않는다.
  • 모든 필드(field)를 final, private 사용.
  • 상속 받는 subclass가 해당 메소드를 오버라이딩하게 하지 않는다.(간단한 방법은 final 클래스로 선언)
  • 인스턴스 필드가 가변 객체에 포함되어 참조 되면 해당 객체가 변하게 하지 말 것.(가변 객체에 제공 하지 않는다)

 

Immutable Object 장단점

장점

  • 불변이기에 객체에 대한 신뢰도가 높아진다(객체가 안전하다).
  • 생성자, 접근 메소드에 대한 방어 복사가 필요 없다.
  • 멀티 스레드 환경에서 동기화 처리 없이 객체를 공유 할 수 있다.

단점

  • 객체가 가지는 값마다 새로운 객체가 필요하다.
  • 메모리 누수와 새로운 객체를 계속 생성하기 때문에 성능 저하를 발생시킬 수 있다.
728x90
728x90

String, StringBuilder, StringBuffer 차이점

  • String 객체는 한번 생성되면 할당된 공간이 변하지 않는다.
  • String 객체는 concat 또는 + 연산자를 통해 기존 생성된 String 객체 문자열에 다른 문자열을 붙여도 기존 문자열에 새로운 문자열을 붙이는 것이 아닌, 새로운 String 객체를 만든 후 문자열을 저장하고 그 객체를 참조한다.
  • 즉 String 객체는 concat 또는 + 연산자를 많이 사용 할 수록 String 객체의 수가 늘어나기 때문에 성능이 느려진다.
  • StringBuffer나 StringBuilder의 경우 객체의 공간이 부족해 지는 경우 버퍼의 크기를 유연하게 늘려준다.
  • 이러한 특징을 String은 불변(immutable)하고 StringBuffer와 StringBuilder는 가변(mutable)하다.

 

StringBuilder, StringBuffer 같은점, 차이점

같은점

  • StringBuilder와 StringBuffer는 둘 다 크기가 유연하게 변하는 가변적인 특성을 가진다.
  • 제공하는 메소드도 같고 사용하는 방법도 동일하다.

 

차이점

  • 두 클래스는 동기화 지원의 유무가 다르다.
  • StringBuffer는 각 메소드 별로 synchronized keyword가 존재하여 멀티 스레드 상태에서 동기화 지원.
  • StringBuilder는 단일 스레드 환경에서만 사용하도록 설계되어 있다.
  • StringBuffer는 멀티 스레드 환경에서도 안전하게 동작할 수 있다.

 

정리

  • String
    • 짧은 문자열을 더할 경우
    • 문자열 연산이 적고 멀티 스레드 환경일 경우
  • StringBuffer
    • 스레드에 안전한 프로그램이 필요하거나, 개발 중인 시스템의 부분이 스레드에 안전하지 모를 경우
    • 문자열 연산이 많고 멀티 스레드 환경일 경우
  • StringBuilder
    • 스레드에 안전한지 여부가 전혀 관계 없는 프로그램을 개발할 경우
    • 문자열 연산이 많고 단일 스레드이거나 동기화를 고려하지 않아도 되는 경우

 

728x90
728x90

StringBuilder

  • StringBuilder는 문자열을 변경하거나 이어붙이는 경우 추가 메모리 생성 없이 기존 문자열이 확장.
  • String과 다르게 문자열이 빈번하게 변경될 때 사용하면 성능이 좋다.
  • StringBuilder는 멀티쓰레드 환경에서 문자열의 안전한 변경을 보장해주지 않는 특징이 있다.
  • 즉, 여러 쓰레드가 문자열에 동시 접근, 변경이 이루어지면 수행결과가 올바르지 않는 것을 의미.

 

StringBuilder 사용법

public class Main
{
    public static void main(String[] args)
    {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("문자열 ").append("연결");
        // String str = stringBuilder; // String에 StringBuilder를 그대로 넣을 순 없다. 
        String str = stringBuilder.toString(); // toString()사용
        // 두 println()은 같은 값을 출력한다
        System.out.println(stringBuilder);
        System.out.println(str);
    }
}

 

StringBuilder 주요 메소드

  • append() - 문자열 추가
  • capacity() - 현재 char[] 배열이 가진 사이즈 정보를 반환
  • delete() - 매개변수로 전달받은 인덱스 사이의 문자열 제거
  • deleteCharAt() - 특정 인덱스의 한 문자만 삭제
  • insert() - 특정 위치에 문자열 삽입
  • reverse() - 문자열을 거꾸로 뒤집어 반환
  • setCharAt() - 특정 위치의 문자 변경
  • setLength() - 문자열 길이 조정
  • trimToSize() - 문자열이 저장된 char[] 배열 사이즈를 현재 문자열 길이와 동일하게 조정

 

728x90
728x90

contains()

  • boolean contains(CharSequence s)
  • contains()는 대상 문자열에 특정 문자열이 포함되어 있는지 확인
  • 대소문자를 구분
  • 특정 문자열이 포함되어 있다면 true, 없다면 false 반환

 

contains() 예제

public class Main {
	public static void main(String[] args) {
        String str = "Hello World";

        System.out.println(str.contains("Hello")); // true  
        System.out.println(str.contains("hello")); // false  
        System.out.println(str.contains(" Hello")); // false  
        System.out.println(str.contains(" World")); // true  
        System.out.println(str.contains("Hello World")); // true  
        
	}
}
728x90
728x90

compareToIgnoreCase()

  • compareToIgnoreCase()는 대소문자 구분 없이 두 문자열을 비교.
  • compareTo()와 동일한 결과 값을 리턴
  • 이전글 compareTo() 참고
public class Main {
	public static void main(String[] args) {
        String str = "abcd";

        System.out.println( str.compareToIgnoreCase("AB") ); // 2 
        System.out.println( str.compareToIgnoreCase("zefd") ); // -25 
        System.out.println( str.compareToIgnoreCase("ABFe") ); // -3        
        System.out.println( str.compareToIgnoreCase("abcd") ); // 0
        System.out.println( str.compareToIgnoreCase("ABCD") ); // 0

	}
}
728x90

+ Recent posts