[Java] 자바 기초(8)

어정윤·2021년 4월 30일
0

Java 스터디

목록 보기
11/12
post-thumbnail

[Java] 자바 기초(8)

1. 문자와 문자열

1-1. 문자

한 개의 문자 값에 대한 자료형은 char를 사용한다.
문자 한개를 입력할 때는 단일 인용부호('')를 사용한다.

char oneChar = 'a';

1-2. 문자열

문자열에 대한 자료형은 String을 사용한다.
문자열을 입력할 때는 따옴표("")를 사용한다.

문자는 뒤에 \0(널문자)가 없지만, 문자열 끝에는 \=(널문자)가 저장된다.

String 클래스

문자열을 입력받기 위해 사용되는 String은 원시 타입처럼 쓰이나 참조형 객체 클래스이다. 또한 불변 객체로 동일한 객체가 공유되면서 사용된다.

String 클래스 선언 방법
1. 리터럴

String str = "text";

""을 이용해 할당하는 방식은 내부적으로 heap 메모리의 String constant pool에 hashmap 형태의 자료구조에 저장한다.

  1. new를 사용한 선언
String str = new String("text");

new를 이용한 방식의 문자열은 heap 메모리에 객체 형태로 저장한다.

String 클래스 저장공간

두 저장방식의 차이를 다음 예제를 통해 알아보자

String str = "text";
String str2 = "text2";
String str3 = new String("text3");

System.out.println(str == str3); // false
System.out.println(str == str2); // true

2. 업캐스팅(UpCasting) vs 다운캐스팅(DownCasting)

2-1. 캐스팅(Casting)이란

캐스팅이란 타입 변환을 말하며 형변환이라고도 한다. 자바의 상속 관계에 있는 부모와 자식 클래스 간에는 서로 간의 형변환이 가능하다.

부모 클래스인 상속 관계의 상위 클래스는 수퍼 클래스(Super Class), 자식 클래스인 하위 클래스를 서브 클래스(Sub Class)라고 정의한다.

2-2. 업캐스팅(UpCasting)

업캐스팅(Upcasting)이란 서브 클래스의 객체가 수퍼 클래스의 타입으로 형변환되는 것을 말한다.

즉, 수퍼 클래스 레퍼런스 변수가 서브 클래스로 객체화된 인스턴스를 가리킬 수 있게 된다.

자바에서 서브 클래스는 수퍼 클래스의 모든 특성을 상속받는다.

2-3. 다운캐스팅(DownCasting)

다운캐스팅(DownCasting)이란 자신의 고유한 특성을 잃은 서브 클래스의 객체를 다시 복구 시켜주는 것을 말한다.

즉, 업캐스팅된 것을 다시 원상태로 돌리는 것을 의미한다.

이때 업캐스팅과 다른 점은 명시적으로 타입을 지정해야 한다는 점이다. 또한 업캐스팅이 선행이 되어야 한다.
다운캐스팅을 하면서 형변환활 대상을 지정했지만 무분별한 다운캐스팅은 컴파일 시점에는 오류가 발생하지 않아도 런타임 오류를 발생시킬 가능성이 있다.

3. 인터페이스(Interface)

3-1. 인터페이스란

인터페이스(Interface)란 다른 클래스를 작성할 때 기본이 되는 틀을 제공하면서, 다른 클래스 사이으 ㅣ중간 매개 역할까지 담당하는 일종의 추상 클래스를 의미한다.

자바에서 추상 클래스는 추상 메소드뿐만 아니라 생성자, 필드, 일반 메소드도 포함할 수 있다.

3-2. 인터페이스 선언

자바에서 인터페이스를 선언하는 방법은 클래스를 작성하는 방법과 같다.
인터페이스를 선언할 때에는 접근지정자와 함께 interface 키워드를 사용하면 된다.

접근지정자 interface 인터페이스이름 {
	public static final 타입 상수명 =;
    	...
    	public abstract 메소드이름(매개변수목록);
        ...

단, 클래스와 달리 인터페이스의 모든 필드는 public static final이어야 하며, 모든 메소드는 public abstract이어야 한다.
이 부분은 모든 인터페이스에 공통으로 적용되는 부분이므로 이 접근지정자는 생략할 수 있다.
이렇게 생략된 접근지정자는 컴파일 시 자바 컴파일러가 자동으로 추가해준다.

3-3. 인터페이스 구현

인터페이스는 추상 클래스와 마찬가지로 자신이 직접 인스턴스를 생성할 수는 없다.
따라서 인터페이스가 포함하고 있는 추상 메소드를 구현해 줄 클래스를 작성해야만 한다.

자바에서 인터페이스는 다음과 같은 문법을 통해 구현한다.

class 클래스이름 implements 인터페이스이름 { ... }

만약 모든 추상 메소드를 구현하지 않는다면, abstract 키워드를 사용해 추상 클래스로 선언해야 한다.

3-4. 클래스를 이용한 다중 상속의 문제점

클래스를 이용하여 다중 상속을 하면 메소드 출처의 모호성 등의 문제가 발생할 수 있다.

class Animal { 
    public void cry() {
        System.out.println("짖기!");
    }
}
 
class Cat extends Animal {
    public void cry() {
        System.out.println("냐옹냐옹!");
    }
}
 
class Dog extends Animal {
    public void cry() {
        System.out.println("멍멍!");
    }
}class MyPet extends Cat, Dog {}
 
public class Polymorphism {
    public static void main(String[] args) {
        MyPet p = new MyPet();
②      p.cry();
    }
}

위의 예제에서 Cat 클래스와 Dog 클래스는 각각 Animal 클래스를 상속받아 cry() 메소드를 오버라이딩하고 있다.
여기까지는 문제가 없지만, ①번 라인에서 MyPet 클래스가 Cat 클래스와 Dog 클래스를 동시에 상속받게 되면 문제가 발생한다.
②번 라인에서 MyPet 인스턴스인 p가 cry() 메소드를 호출하면, 이 메소드가 Cat 클래스에서 상속받은 cry() 메소드인지 Dog 클래스에서 상속받은 cry() 메소드인지 구분할 수 없는 모호성을 지게 된다.

따라서 자바에서는 클래스를 이용한 다중 상속을 지원하지 않는다.

하지만 인터페이스를 이용하여 다중 상속을 하게 되면, 위와 같은 메소드 호출의 모호성을 방지할 수 있다.

interface Animal { public abstract void cry(); }
 
interface Cat extends Animal { public abstract void cry(); }
interface Dog extends Animal { public abstract void cry(); }
 
class MyPet implements Cat, Dog {
    public void cry() {
        System.out.println("멍멍! 냐옹냐옹!");
    }
}
 
public class Polymorphism05 {
    public static void main(String[] args) {
        MyPet p = new MyPet();
        p.cry();
    }
}

위의 예제에서는 Cat 인터페이스와 Dog 인터페이스를 동시에 구현한 MyPet 클래스에서만 cry() 메소드를 정의하므로, 앞선 예제에서 발생한 메소드 호출의 모호성이 없다.

3-5. 인터페이스의 장점

인터페이스를 사용하면 다중 상속이 가능할 뿐만 아니라 다음과 같은 장점을 가질 수 있다.

  1. 대규모 프로젝트 개발 시 일관되고 정형화된 개발을 위한 표준화가 가능하다.
  2. 클래스의 작성과 인터페이스의 구현을 동시에 진행할 수 있으므로, 개발 시간을 단축할 수 있다.
  3. 클래스와 클래스 간의 관계를 인터페이스로 연결하면, 클래스마다 독립적인 프로그래밍이 가능하다.
profile
성장ing

0개의 댓글