원래 해당 강의를 너무 좋게 잘 봤었다. 하지만 강의를 학습한지 꽤 지나다보니 몇몇 지식들이 흐릿해지고 잊혀졌다. 그래서 해당 강의에서 잘 기억이 안나서 흐릿한 지식들을 다시 정리하려하고 한다.
자바는 기본형과 참조형, 크게 두 가지로 자료형이 구분된다.
new라는 키워드를 통해서 객체를 메모리에 올려줄 수 있다. 이렇게 메모리에 올라간 객체를 인스턴스라고 한다.
String str = new String("Study!");
이 경우 str은 메모리에 올라간 인스턴스를 가리키는 변수이다. 이것을 참조, 레퍼런스하는 변수라고 한다. 즉 str은 해당 인스턴스의 메모리 위치값이 저장된다.
자바에서 문자열을 표현하려할 때 가장 많이 사용하는 클래스이다. 두 가지 방식으로 사용할 수 있다.
String str1 = "Study";
String str2 = "Study";
String str3 = new("Study");
String str4 = new("Study");
1번의 경우 new를 사용하지 않는 경우로 "Study"가 메모리의 상수 영역에 저장되고 그 메모리를 가리킨다. 이때 str2도 동일한 "Study"이기에 str1이 참조하는 인스턴스를 동일하게 참조하게 된다.
2번의 경우 new를 사용한 경우로 str3, str4모두 "Study"이지만 new를 통해 새롭게 인스턴스가 메모리에 올라가므로 str3, str4는 서로 다른 인스턴스를 참조한다. 이때 str3,str4는 기존의 str1과 str2가 가리키고 있는 인스턴스와도 다른 인스턴스를 참조한다.(새로 만들어서 가리키고 있으니까!)
또한 String은 불변(Immutable) 클래스이다. 즉 인스턴스가 될 때 가지고 있던 값을 변경할 수 없다. 중간에 String의 값을 메서드로 변경하거나 새로 넣는 것은 사실 값을 변경하는 것이 아니라 새로운 String 인스턴스를 생성하고 그것을 가리키는 것이다. 이럴 경우 기존의 인스턴스는 가비지 콜렉터(Garbage Collector)에 의해 알아서 정리된다.
static이라는 키워드는 클래스가 로드되어 메모리에 올라갈 때 같이 생성되어지게하는 키워드이다. 그렇기에 static이 붙은 필드나 메서드는 인스턴스를 생성하지 않아도 사용할 수 있다는 장점이 있다. 또한 static 변수들은 이미 로드되어 메모리에 올라가고 모든 인스턴스에서 해당 변수를 동일하게 사용하므로 여러 인스턴스가 동일한 값을 유지하고 공유할 수 있게 할 수 있다. 물론 final을 사용하지 않으면 변경도 가능하다.
이렇게 static한 필드를 클래스 변수라하고 인스턴스가 생성될 때 생성되는 일반적인 필드를 인스턴스 변수라고 한다.
그리고 주의할 점이 있는데 위에서 static은 클래스가 로드되어 메모리에 올라갈 때 자동으로 생성되어 메모리에 올라가게 된다고 했다. 즉 static 메서드의 경우, 그 안에서 인스턴스 변수를 사용할 수 없다. 인스턴스 변수는 말 그대로 인스턴스가 생성되어야 따라서 생성되는데 static 메서드는 인스턴스를 만들지 않고도 호출하여 사용할 수 있기에 그 내에서 인스턴스 변수의 생성을 확신할 수 없기 때문이다.
이런 static을 잘 사용할 경우 동일한 값을 공유 할 때, 동일한 static 변수를 참조하여 메모리 측면에서도 이득을 볼 수 있고 메서드도 static 메서드의 경우 호출시간도 더 빨라서 효율적이라고 한다.(static 메서드가 아닌 경우 해당 메서드를 찾는 시간이 필요하다고 한다. -> Ref : https://vaert.tistory.com/101)
기존에는 고정된 값을 사용하고 싶을 때, final을 주로 사용하였다.
public class A {
public static final String NAME = "SEUNGJAE";
public static void main(String[] args) {
String me;
me = A.NAME;
// me = "WHO?"
}
}
하지만 이 경우 주석처럼 사용할 위험도 존재한다. 이 때 확정적으로 원하는 값만 사용하기 위해 열거형 Enum을 사용할 수 있다.
enum Me {
SEUNGJAE;
}
public class A {
public static void main(String[] args) {
Me me = Me.SEUNGJAE;
}
}
이 경우 Me 타입 변수에는 SEUNGJAE만 대입이 가능하다. 즉 특정값만 사용해야할 경우 열거형을 사용하는 것이 좋다.
구체적이지 않은 클래스를 의미한다. 포유류, 파충류 등... 추상클래스는 미완성의 추상 메서드를 포함할 수 있다. 그리고 추상 클래스는 인스턴스를 생성할 수 없다. 그래서 추상 클래스를 상속하고 미완성된 추상 메서드를 구현하여 사용한다. 이때 *상속한 클래스도 추상 메서드를 구현하지 않을 경우 해당 클래스도 추상 클래스가 된다.
인터페이스란 "서로 관계가 없는 물체들이 상호 작용을 하기 위해서 사용하는 장치나 시스템"을 뜻한다. 해당 인터페이스는 java에서 인터페이스를 implement하는 클래스들이 동일한 기능을 하게하는 역할을 한다. 물론 해당 기능에 대한 세부 구현은 다양할 수 있다는 것이 인터페이스의 큰 장점이다. 그리고 클래스와 달리 인터페이스는 다중 상속 또한 가능하다는 것 또한 장점이다.
인터페이스에서는 추상메서드와 상수를 정의할 수 있다. 인터페이스 내의 정의된 변수들은 컴파일 시 자동으로 모두 static final 키워드가 붙게 되고, 메서드들은 모두 abstract가 붙어 추상 메서드가 된다.
물론 예외도 있다. 인터페이스 내에서 static을 사용하여 정적 메서드도 만들어 활용할 수 있고 default 키워드로 default 메서드(해당 메서드는 일반적인 비어있는 인터페이스 내의 메서드가 아닌 구현된 메서드이다.)를 만들어서 인터페이스를 구현하는 모든 객체들에게 동일한 기능을 가진 메서드도 제공할 수 있다.
throws 키워드는 Method throws Exception
식으로 사용한다. 이렇게 할 경우 Method 내에서 Exception이 발생시, Method를 호출한 쪽에서 해당 예외를 처리해야 한다.
java에서 함수의 호출은 stack에 쌓이고 해당 내의 기본형 변수 및 Obejct타입을 가리키는 변수의 메모리가 할당되며 실행되고, 객체의 인스턴스는 Heap메모리에 생성되어 인스턴스내 변수의 메모리가 할당된다. 또한 Static의 경우에는 또 static 메모리 영역이 존재한다. 해당 영역의 데이터는 프로그램의 시작부터 종료까지 메모리가 해제되지 않고 유지된다고 한다. 따라서 적절한 static의 사용은 효율적이지만 너무 부분별하게 막 사용해서는 안될 것 같다.