Java

자바(Java) - 객체지향 프로그래밍 2-2(Object - oriented Programming)

신동편 2023. 4. 4. 01:17
728x90

import문

 

Java에서 import문은 다른 패키지에 속하는 클래스나 인터페이스를 현재 소스 파일에서 사용할 수 있도록 가져오는 기능을 한다.

 

import문은 클래스의 전체 이름(패키지 이름과 클래스 이름)을 사용하지 않고 클래스 이름만으로 해당 클래스를 사용할 수 있게 한다.

 

Java에서는 패키지 이름과 클래스 이름이 중복되지 않는 한, 패키지 이름을 생략할 수 있다.

이 경우 클래스 이름만을 사용하여 해당 클래스를 찾게 된다.

 

예를 들어, java.util 패키지에 속한 Arrays 클래스를 사용하려면 다음과 같이 import문을 작성한다.

import java.util.Arrays;
//또는
import java.util.*;

위의 코드에서 import java.util.Arrays; 문장을 작성하면, MyClass 클래스 내에서 Arrays 클래스를 패키지 이름 없이 바로 사용할 수 있다.

 


static import문

 

Java에서 static import문은 다른 클래스에서 static 멤버를 호출할 때, 해당 멤버의 이름만으로 접근 가능하게 하는 기능이다.

일반적으로, 다른 클래스의 static 멤버를 사용하려면 해당 멤버가 선언된 클래스 이름을 포함하 ClassName.staticMember와 같은 형식으로 호출해야 한다.

 

그러나 static import문을 사용하면, 다른 클래스의 static 멤버를 직접 호출할 수 있다.

예를 들어, java.lang.Math 클래스의 PI 상수를 사용하고자 할 때, Math.PI와 같은 형식으로 호출해야 한다.

 

하지만 static import문을 사용하면,

 

import static java.lang.Math.PI;

와 같이 선언한 뒤, PI 상수를 직접 호출할 수 있다.

 

static import 문은 코드의 가독성을 높이고, 코드를 더 간결하게 작성할 수 있게 해 준다. 

 


제어자(modifier)

 

Java에서 제어자(modifier)는 클래스, 메서드, 변수 등의 선언 부분에 사용되어 해당 선언 부분의 속성을 변경하거나 제한하는 역할을 한다.

 

Java에서 사용되는 제어자는 다음과 같다.

접근 제어자(access modifier) : public, protected, private가 있으며, 해당 멤버의 접근 범위를 지정한다.

public : 모든 클래스에서 접근 가능
protected : 같은 패키지 내부 또는 상속 받은 클래스에서 접근 가능
private : 해당 클래스 내부에서만 접근 가능

 

 

그 외 제어자 :

final : 해당 변수, 메서드, 클래스가 변경 불가능한 상태가 됨
static : 해당 변수, 메서드, 클래스가 정적 멤버가 됨
abstract : 해당 클래스, 메서드가 추상적인 성격을 가짐
synchronized : 다중 스레드 환경에서 동기화를 보장함
transient : 해당 변수가 직렬화 대상에서 제외됨
volatile : 해당 변수가 다중 스레드에서 사용될 때 메모리 일관성을 보장함

 

제어자를 사용하여 클래스, 메서드, 변수 등의 속성을 변경하거나 제한함으로써, 보다 안정적이고 안전한 코드를 작성할 수 있다.

 


static

 

Java에서 static은 클래스의 멤버인 필드, 메서드, 내부 클래스 등을 정적 멤버로 만들어주는 키워드이다.

 

static 멤버는 객체 생성 없이 클래스 이름으로 직접 접근 가능하며, 객체마다 새로운 복사본을 만들지 않고 하나의 인스턴스만 생성됩니다. 이로 인해, static 멤버는 메모리 사용과 성능 개선에 유용하다.

 

주로 사용되는 static 멤버는 다음과 같다.

 

static 필드 : 클래스 변수라고도 불리며, 객체마다 생성되지 않고 프로그램 실행 시 메모리에 딱 한 번만 생성됩니다. 클래스 내부 또는 클래스 외부에서 클래스이름.필드이름으로 접근할 수 있다.

 

static 메서드 : 클래스 메서드라고도 불리며, 객체 생성 없이 클래스 이름으로 직접 호출할 수 있습니다. static 메서드는 인스턴스 멤버에 접근할 수 없으며, 주로 객체를 생성하지 않아도 사용할 수 있는 유틸리티 메서드나 팩토리 메서드 등을 구현할 때 사용된다.

 

static 블록 : 클래스가 로드될 때 실행되는 블록으로, static 필드의 초기화나 static 메서드 호출 등을 수행할 수 있다.

 

static 멤버는 클래스에 속하는 것으로 객체 생성과 무관하게 사용할 수 있다. 따라서, 객체를 생성하지 않고도 프로그램 전반에서 공유해야 하는 정보나 기능을 구현하는 데 유용하다.

 


final

 

final은 거의 모든 대상에 사용될 수 있다. 변수에 사용되면 값을 변경할 수 없는 상수가 되며, 메서드에 사용하면 오버라이딩을 할 수 없게 되고, 클래스에 사용하면 자신을 확장하는 자손 클래스를 정의하지 못하게 된다.

 

final 클래스 : 변경될 수 없는 클래스, 확장될 수 없는 클래스가 된다. 그래서 final로 지정된 클래스는 다른 클래스의 조상이 될 수 없다.

 

final 메서드 : 변경될 수 없는 메서드, final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다.

 

final 멤버변수, 지역변수 : 변수 앞에 final이 붙으면 값을 변경할 수 없는 상수가 된다.

 


abstract

 

메서드의 선언부만 작성하고 실제 수행 내용은 구현하지 않은 추상 메서드를 선언하는데 사용된다. 그래서 클래스에 사용되어 클래스 내에 추상메서드가 존재한다는 것을 쉽게 알 수 있게 한다.

 

abstract 클래스 : 클래스 내에 추상 메서드가 선언되어 있음을 의미한다.

 

abstract 메서드 : 선언부만 작성하고 구현부는 작성하지 않는 추상 메서드임을 알린다.

 

추상 클래스는 아직 완성되지 않은 메서드가 존재하는 '미완성 설계도'이므로 인스턴스를 생성할 수 있다.

 


캡슐화와 접근 제어자

 

클래스나 멤버, 주로 멤버에 접근 제어자를 사용하는 이유는  클래스의 내부에  선언된 데이터를 보호하기 위해서이다.

데이터가 유효한 값을 유지하도록, 또는 비밀번호와 같은 데이터를 외부에서 함부로 변경하지 못하도록 하기 위해서는 외부로부터의 접근을 제한하는 것이 필요하다.

 

이것을 데이터 감추기라고 하며, 객체지향개념의 캡슐화에 해당하는 내용이다.

 

클래스 내에서만 사용되는, 내부 작업을 위해 임시로 사용되는 멤버변수나 부분작업을 처리하기 위한 메서드 등의 멤버들을 클래스 내부에 감추기 위해서이다.

 

외부에서 접근할 필요가 없는 멤버들을 private으로 지정하여 외부에 노출시키지 않음으로써 복잡성을 줄일 수 있다.

이것 역시 캡슐화에 해당할 수 있다.

 


getter, setter

 

멤버변수의 값을 읽는 메서드의 이름을 'get멤버변수이름'으로 하고,

멤버변수 값을 변경하는 메서드의 이름을 'set멤버변수이름'으로 한다.

 

반드시 그렇게 해야만 하는 것은 아니지만 암묵적인 규칙이므로 특별한 이유가 없는한 이에 따른다.

 

그리고 get으로 시작하는 메서드를 '겟터(getter)', set으로 시작하는 메서드를 '셋터(setter)'라고 부른다.

 


다형성

 

다형성이란 '여러 가지 형태를 가질 수 있는 능력'을 의미하며, 자바에서는 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 함으로써 다형성을 프로그램적으로 구현하였다.

 

조상 클래스 타입의 참조변수로 자손 클래스의 인스턴스를 참조할 수 있도록 한 것이다.

 

생성된 인스턴스를 다루기 위해서, 인스턴스의 타입과 일치하는 타입의 참조변수만 사용할 수 있을 뿐만 아니라 조상 클래스 타입의 참조변수로 자손 클래스의 인스턴스를 참조하도록 하는 것도 가능하다.

 

같은 타입의 인스턴스라도 참조변수의 타입에 따라 사용할 수 있는 멤버의 개수가 달라진다.

 

조상타입의 참조변수로 자손타입의 인스턴스를 참조할 수 있다.
반대로 자손타입의 참조변수로 조상타입의 인스턴스를 참조할 수는 없다.

 


참조변수의 형변환

 

서로 상속관계에 있는 클래스 사이에서만 형변환이 가능하기 때문에 자손타입의 참조변수를 조상타입의 참조변수로, 조상타입의 참조변수를 자손타입의 참조변수로 형변환만 가능하다.

 

기본형의 형변환과 달리 참조형의 형변환은 변수에 저장된 값(주소값)이 변환되는 것이 아니다.

참조변수의 형변환은 그저 참조변수를 다른 종류의 것으로 바꾸는 것 뿐이다.

 

조상타입으로 형변환하면 다룰 수 있는 멤버의 개수가 줄어들기 때문에 항상 안전하다. 따라서 조상타입으로의 형변환을 생략할 수 있다.

 

서로 상속관계에 있는 타입 간의 형변환은 양방향으로 자유롭게 수행될 수 있으나, 참조변수가 가리키는 인스턴스의 자손타입으로 형변환은 허용되지 않는다.
그래서 참조변수가 가이키는 인스턴스의 타입이 무엇인지 먼저 확인하는 것이 중요하다.

 


instanceof

 

instanceof 연산자는 객체가 특정 클래스나 인터페이스의 인스턴스인지를 확인할 수 있다. 연산자는 이항 연산자로, 객체와 클래스 또는 인터페이스를 비교한다. 결과는 true 또는 false로 반환된다.

 

instanceof 연산자는 상속 관계에서도 사용될 수 있다. 예를 들어, MyClass가 다른 클래스의 하위 클래스인 경우, instanceof 연산자를 사용하여 해당 클래스의 인스턴스 여부를 확인할 수 있다.

 

instanceof 연산자는 객체의 타입을 확인하여 객체의 타입에 따라 다른 동작을 수행할 때 유용하게 사용된다. 또한, 객체의 타입을 확인하여 적절한 캐스팅을 수행할 때에도 유용하게 사용된다.

 

어떤 타입에 대한  instanceof 연산의 결과가 참이라는 것은 검사한 타입으로 형변환이 가능하다는 것을 의미한다.

 


매개변수의 다형성

 

상속 관계에서 부모 클래스의 변수에 자식 클래스의 객체를 할당할 수 있음을 의미한다. 따라서 매개변수의 타입으로 부모 클래스를 사용하면 자식 클래스의 객체를 매개변수로 전달할 수 있게 된다.

 

예를 들어, 동물(Animal) 클래스와 이를 상속받은 개(Dog) 클래스가 있다면, 매개변수의 다형성을 이용하여 다음과 같은 메서드를 만들 수 있다.

public void speak(Animal animal) {
	animal.speak(); 
}

이 메서드는 Animal 객체를 매개변수로 받아 speak() 메서드를 호출한다. 그리고 Animal을 상속한 Dog 클래스의 객체를 매개변수로 전달할 수 있다.

Dog dog = new Dog(); 
speak(dog);

 

위와 같이 매개변수의 다형성을 이용하면, 코드의 재사용성과 유연성을 높이며, 다양한 자료형을 처리하는 메서드를 만드는 데 도움을 준다.

 


여러 종류의 객체를 배열로 다루기

 

조상타입의 참조변수로 자손타입의 객체를 참조하는 것이 가능하므로, 조상타입의 참조변수 배열을 사용하면, 공통의 조상을 가진 서로 다른 종류의 객체를 배열로 묶어서 다룰 수 있다.

 

묶어서 다루고 싶은 객체들의 상속관계를 따져서 가장 가까운 공통조상 클래스 타입의 참조변수 배열을 생성해서 객체들을 저장하면 된다.

 

배열의 크기를 10으로 한다면 11개 이상의 객체를 담을 수 없다. 하지만 배열의 크기를 무조건 크게 설정할 수만도 없는 일이다.

 

이런 경우 Vector클래스를 사용하면 된다. Vector클래스는 내부적으로 Object타입의 배열을 가지고 있어서, 이 배열에 객체를 추가하거나 제거할 수 있게 작성되어 있다. 그리고 배열의 크기를 알아서 관리해 주기 때문에 저장할 인스턴스의 개수에 신경 쓰지 않아도 된다.

 

Vector클래스는 동적으로 크기가 관리되는 객체 배열이다.

 


John K - Sometimes

728x90