Java

Ssong94·2022년 7월 17일
0

📌 Java

목록 보기
1/4
post-thumbnail
post-custom-banner

🌀 Java


✅ 자바 시작하기

바이트코드

  1. 소스파일(.java)을 작성한 후 컴파일한다.
  2. javac (java compiler)명령어는 소스를 컴파일한다.
  3. 컴파일 결과는 확장명이 .class인 바이트코드 파일로 생성된다.

자바 가상 머신 (JVM)

  • 바이트코드 파일(~.class)을 특정 운영체제가 이해하는 기계어로 번역하고 실행시키는 명령어는 java이다.
  • java 명령어는 JDK와 함께 설치된 자바 가상 머신(JVM)을 구동시켜 바이트코드 파일을 완전한 기계어로 번역하고 실행시킨다.
  • 바이트코드 파일은 운영체제와 상관없이 모두 동일한 내용으로 생성된다.
  • JVM은 각 운영체제에서 이해하는 기계어로 번역해야 하므로 운영체제별로 다르게 설치된다.

✅ 자바의 특징

  • 운영체제에 독립적 (JVM 위에서 돌아간다.)
  • 객체지향 언어
  • 고급 프로그래밍 언어 (사람이 이해하기 쉽다)
  • 자동 메모리 관리 (Garbage Collection)
  • 네트워크와 분산처리 지원
  • 멀티쓰레드 지원
  • 동적 로딩 (Dynamic Loading) 지원

✅ JDK, JRE

  • JDK (Java Development Kit) : 자바 개발 도구 (개발 도구에 중점)
    • JRE + 개발에 필요한 실행 파일 (javac, exe 등)
  • JRE (Java Runtime Evironment) : 자바로 작성된 응용프로그램이 실행되기 위한 최소 조건 (실행 환경에 중점)
    • JVM + 클래스 라이브러리 (java API)
  • Java-SE

✅ 변수 (variable)

  • 기본형 (Primitive type) : 실제 값을 저장
    • 논리형 (Boolean)
    • 문자형 (Char)
    • 정수형 (byte, short, int, long)
    • 실수형 (float, double)
  • 참조형 (Reference type) : 주소를 저장
    • 기본형을 제외한 나머지 타입

✅ 배열 (array)

배열(Array)리스트(List)
크기고정적
(선언할 때 크기가 고정적)
동적
(데이터를 삽입할 때마다 증가)
주소순차적랜덤
접근속도인덱스만 안다면 접근 가능
(속도 빠름)
하나하나 위치를 따라가서 접근
(배열에 비해 속도 느림)
삽입/삭제삽입 시, 기존의 데이터들의 위치를 뒤로 이동시킴.
삭제 시 기존의 데이터들의 위치를 앞으로 이동시킴.
(비효율적)
삽입 시, 리스트에 연결되어 있는 위치에 접근한 우 리스트 추가.
삭제 시, 리스트에 연결되어 있는 위치에 접근하여 삭제 후, 기존의 리스트들을 연결.
삽입/삭제 시 메모리를 할당/해제할 필요가 있음.
(효율적)

✅ 객체지향 프로그래밍 (Object-oriented Programming)

👍 장점

  • 코드의 재사용성이 높다.
    • 새로운 코드를 작성 시 기존의 코드를 이용하여 쉽게 작성
  • 유지보수가 용이
    • 코드간의 관계를 이용해서 적은 노력으로 쉽게 코드를 변경
  • 중복 코드 제거
  • 신뢰성 높은 프로그래밍
    • 제어자, 메서드를 이용해서 데이터를 보호하고, 코드의 중복을 제거하여 코드 블일치로 인한 오작동을 방지

객체지향 설계 5원칙 - SOLID 알아보기

✅ 클래스 (class)

  • 클래스의 정의 : 객체를 정의해 놓은 것 (그릇, 틀)
  • 클래스의 용도 : 객체를 생성하는데 사용 (음식)
  • 클래스를 실체화 시키는 것 : 인스턴스화

1. 변수의 종류

// 클래스 영역에 선언된 변수를 멤버변수라고 부른다.
class Variables {
	int iv;				// 인스턴스 변수
	static int cv;		// 클래스 변수 (static 변수, 공유 변수)
    
	void method() {		
		int lv = 0;		// 지역 변수
	}
}

2. 변수의 특징

변수의 종류선언위치생성시기
클래스변수
(Class Variable)
클래스영역클래스가 메모리에 올라갔을 때
인스턴스변수
(Instance Variable)
클래스영역인스턴스가 생성되었을 때
지역변수
(Local Variable)
클래스 영역 이외의 영역
(메서드, 생성자, 초기화 블럭 내부
변수 선언문이 수행되었을 때
  • 변수 -> 하나의 데이터를 저장할 수 있는 공간
  • 배열 -> 같은 종류의 여러 데이터를 하나의 집합으로 저장할 수 있는 공간
  • 구조체 -> 서로 관련된 여러 데이터를 종류에 관계없이 하나의 집합으로 저장할 수 있는 공간
  • 클래스 -> 데이터와 함수의 결합(구조체 + 함수)

✅ 오버로딩 (Overloading)

하나의 메서드 이름으로 비슷한 여러 기능을 구현할 때 쓴다.

  • 메서드의 이름이 같아야 한다.
  • 매개변수의 개수 또는 타입이 달라야 한다.

✅ 가변인자 (variable arguments)

  • JDK1.5부터 지원
  • 가변인자 사용 시 메서드는 오버로딩하지 않는 것이 좋다.
// '타입... 변수명'
public void variableArguments(String a, int b, Object... obj) {}

✅ 생성자 (Constructor)

인스턴스가 생성될 때 호출되는 '인스턴스 초기화 메서드'

  • 생성자의 이름은 클래스의 이름과 같아야 한다.
  • 생성자는 리턴값이 없다.
  • 생성자가 정의되어 있지 않다면 컴파일러가 기본 생성자를 제공한다.
    그러나 생성자가 한 개 이상 존재한다면 기본 생성자를 추가해야 한다.
  • 기본 생성자가 컴파일러에 의해서 추가되는 경우는 클래스에 정의된 생성자가 하나도 없을 때 뿐이다.

1. 매개변수가 있는 생성자

class Car {
	String color;
	String gearType;
	int door;
	
	Car() { } // 생성자
	
	Car(String c, String g, int d) { // 매개변수가 있는 생성자
		this.color = c;
		this.gearType = g;
		this.door = d;
	}
}
->
Car c = new Car("white", "auto", 4)

2. 생성자에서 다른 생성자 호출하기 - this, this()

  • 생성자의 이름으로 클래스 이름 대신에 this를 사용한다.
  • 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능하다.
Car(String color) {
	door = 5;				// 첫 번째 줄
    Car(color, "auto", 4);	// 에러1. 생성자의 두 번째 줄에서 다른 생성자 호출
}							// 에러2. this(color, "auto", 4); 로 해야 함 
  • this ➡ 인스턴스 자신을 가리키는 참조변수, 인스턴스 주소가 저장되어 있다.
  • this(), this(매개변수) ➡ 생성자, 같은 클래스의 다른 생성자를 호출할 때 사용

3. 생성자를 이용한 인스턴스 복사

class Car {
	String color;
	String gearType;
	int door;
	
	Car() {
		this("white", "auto", 4);
	}
	
	Car(String color, String gearType, int door) {
		this.color = color;
		this.gearType = gearType;
		this.door = door;
	}
    
    Car(Car c) { // 인스턴스 복사를 위한 생성자
		this(c.color, c.gearType, c.door);
	}
}

// 인스턴스 복사
Car c1 = new Car();
Car c2 = new Car(c1); // c1의 복사본 c2를 생성

✅ 변수의 초기화

class Car {
	int x;      // 인스턴스 변수
	int y = x;  // 인스턴스 변수
	
	void method() {
		int i;      // 지역 변수
		int j = i;  // 에러. 지역변수를 초기화하지 않고 사용
	}
}

멤버변수(클래스, 인스턴스 변수)와 배열의 초기화는 선택적이지만, 지역변수의 초기화는 필수

1. 각 타입의 기본값(default value)

자료형기본값
booleanfalse
char'\u0000'
byte, short, int0
long0L
float0.0f
double0.0d 또는 0.0
참조형 변수null

2. 명시적 초기화(explicit initialization)

변수의 선언과 동시에 초기화하는 것을 명시적 초기화라고 한다.
가장 기본적이면서도 간단한 초기화 방법으로 여러 초기화 방법 중에서 가장 우선적으로 고려되어야 한다.

class Car {
	int door = 4;			 // 기본형(primitive type) 변수의 초기화
    Engine e = new Engine(); // 참조형(reference type) 변수의 초기화
    //...
}

3. 초기화 블럭(initialization block)

class InitBlock {
	static { /* 클래스 초기화 블럭 */ }
	{ /* 인스턴스 초기화 블럭 */}
}

4. 멤버변수의 초기화 시기와 순서

초기화 시점초기화 순서
클래스 변수클래스가 처음 로딩될 때 단 한 번 초기화된다.기본값 ➡ 명시적 초기화 ➡ 클래스 초기화 블럭
인스턴스 변수인스턴스가 생성될 때마다 각 인스턴스별로 초기화된다.기본값 ➡ 명시적 초기화 ➡ 인스턴스 초기화 블럭 ➡ 생성자

✅ 상속 (inheritance)

1. 상속의 정의와 장점

상속의 정의

기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것

👍 상속의 장점

  • 적은 양의 코드로 새로운 클래스를 작성
  • 코드를 콩통적으로 관리할 수 있기 때문에 코드의 추가 및 변경이 용이
  • 코드의 재사용성을 높이고 코드의 중복을 제거하여 프로그램의 생산성과 유지보수에 기여

상속의 특징

  • 생성자와 초기화 블럭은 상속되지 않는다. 멤버만 상속된다.
  • 자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다.
    ❗접근 제어자가 private 또는 default인 멤버들은 상속은 받지만 자손 클래스로부터의 접근이 제한된다.

2. 상속의 종류

자바는 단일 상속만을 허용한다. (C++은 다중상속 허용)

2.1 단일 상속 (single inheritance)

class TVCR extends TV, VCR {} // 에러. 조상은 하나만 허용

2.2 다중 상속 (multiple inheritance)

class TVCR : public TV, public VCR {}

다중 상속의 장단점

👍 장점

  • 다중 상속을 허용하면 여러 클래스로부터 상속받을 수 있기 때문에 복합적인 기능을 가진 클래스를 쉽게 작성할 수 있다.

👎 단점

  • 클래스간의 관계가 매우 복잡해진다.
  • 서로 다른 클래스로부터 상속받은 멤버간의 이름이 같은 경우 구별할 수 있는 방법이 없다.

Object클래스 - 모든 클래스의 조상

Object클래스는 모든 클래스 상속계층도의 최상위에 있는 조상클래스이다.

상속을 받지 않은 Tv클래스를 정의해보자.

class TV {}

위의 코드를 컴파일하면 컴파일러는 위의 코드를 다음과 같이 자동적으로 'extends Object'를 추가해준다.

class Tv extends Object {}

❗ 이미 어떤 클래스로부터 상속받도록 작성된 클래스에 대해서는 컴파일러가 'extends Object'를 추가하지 않는다.

결론

class Tv {}
class CaptionTv extends TV {}

위와 같은 클래스 관계의 상속 계층도는 아래 그림과 같다.

모든 상속계층도의 최상위에는 Object클래스가 위치한다.
그래서 자바의 모든 클래스들은 Object클래스에 정의된 멤버들을 사용할 수 있다.
그동안 toString()이나 equals(Object o)와 같은 메서드를 따로 정의하지 않고도 사용할 수 있었던 이유는 이 메서드들이 Object클래스에 정의된 것들이기 때문이다.

✅ 오버라이딩 (overriding)

조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것을 오버라이딩이라고 한다.
상속받은 메서드를 그대로 사용하기도 하지만, 자손 클래스 자신에 맞게 변경해야 하는 경우가 많다.
이럴 때 오버라이딩을 한다.

오버라이딩의 조건

  • 이름이 같아야 한다.
  • 매개변수가 같아야 한다.
  • 반환타입이 같아야 한다.

오버라이딩 시 주의점

  • 접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
    • public ➡ protected ➡ default ➡ private
  • 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다.
  • 인스턴스 메서드를 static메서드 또는 그 반대로 변경할 수 없다.

Q. 조상 클래스에 정의된 static 메서드를 자손 클래스에서 똑같은 이름의 static메서드로 정의할 수 있나요?
A. 가능하지만 오버라이딩이 아니다. static멤버들은 자신들이 정의된 클래스에 묶여있다고 생각해야 함.

super

  • 객체 자신을 갈리키는 참조변수.
  • 상속받은 멤버와 자신의 클래스에 정의된 멤버의 이름이 같을 때 super를 붙여서 구별한다.
  • 조상 클래스의 멤버와 자손클래스의 멤버가 중복 정의되어 서로 구별해야 하는 경우에만 super를 사용하는 것이 좋다.
class SuperTest {
    public static void main(String[] args) {
        Child c = new Child();
        c.method();
    }
}

class Parent{
	int x =10; // super.x 
}

class Child extends Parent{
    int x = 20;
    void method() {
        System.out.println("x=" + x);
        System.out.println("this.x=" + this.x);
        System.out.println("super.x="+super.x);
    }
}

/** 결과
  * x=20
  * this.x=20
  * super.x=10
 **/

super() - 조상 클래스의 생성자

  • 조상의 생성자를 호출할 때 사용
  • 조상의 멤버는 조상의 생성자를 호출해서 초기화 (조상이 먼저 실행되어야 함)
class JavaApp {
	public static void main(String[] args) {
		Point3D point3d = new Point3D();    // Point3D() 생성자로 초기화 및 인스턴스 생성
		System.out.println("point3d.x=" + point3d.x);
		System.out.println("point3d.y=" + point3d.y);
		System.out.println("point3d.z=" + point3d.z);
	}
}

class Point {
	int x = 10;
	int y = 20;
    
#1	Point() {
		this(0, 0);
    }
    
	Point(int x, int y) {
		// 생성자의 첫줄에 다른 생성자를 호출하지 않았기 때문에,
		// 컴파일러가 이 부분에 super()를 호출합니다.
		// 부모 클래스이므로 Object 클래스의 super()가 호출됩니다.
		this.x = x;
		this.y = y;
	}
}

class Point3D extends Point {
	int z = 30;

	Point3D() {
		this(100, 200, 300);	// 자신의 클래스의 또다른 생성자 호출
	}

	Point3D(int x, int y, int z) {
		super(x, y); 	// 부모 클래스 생성자 호출 or #1번을 넣어야 함
		this.z = z;
	}	
}

/** 결과
 * p3.x=100
 * p3.y=200
 * p3.z=300
**/

✅ 제어자 (modifier)

1. 제어자

제어자는 클래스, 변수 또는 메서드의 선언부에 함께 사용되어 부가적인 의미를 부여한다.
제어자의 종류는 크게 접근 제어자와 그 외의 제어자로 나눌 수 있다.

  • 접근 제어자 - public, protected, default, private
  • 그ㅤㅤㅤ 외 - static, final, abstract, native, transient, sysnchronized, volatile, strictfp

2. static - 클래스의, 공통적인

인스턴스 변수는 하나의 클래스로부터 생성되었더라도 각기 다른 값을 유지하지만, 클래스변수(static멤버변수)는 인스턴스에 관계없이 같은 값을 갖는다.

static이 사용될 수 있는 곳 - 멤버변수, 메서드, 초기화 블럭

대상의미
멤버변수- 모든 인스턴스에 공통적으로 사용되는 클래스변수가 된다.
- 클래스 변수는 인스턴스를 생성하지 않고도 사용이 가능하다.
- 클래스가 메모리에 로드될 때 생성된다.
메서드- 인스턴스를 생성하지 않고도 호출이 가능한 static 메서드가 된다.
- static메서드 내에서는 인스턴스 멤버들을 직접 사용할 수 없다.

✡ static초기화 블럭은 클래스가 메모리에 로드될 때 단 한번만 수행되며, 주로 클래스변수 (static변수)를 초기화할 때 주로 사용된다.

class StaticTest {
	static int width = 200;	// 클래스 변수 (static변수)
    static int height = 120;// 클래스 변수 (static변수)
    static {
    	// static변수의 복잡한 초기화 수행
    }
    static int max(int a, int b) { // 클래스 메서드 (static 메서드)
    	return a > b ? a : b;
	}
}

3. final - 마지막의, 변경될 수 없는

  1. 변수에 사용하면 값을 변경할 수 없는 상수가 된다
  2. 메서드에 사용하면 오버라이딩을 할 수 없게 된다.
  3. 클래스에 사용하게 되면 자신을 확장하는 자손클래스를 정의하지 못하게 된다.

final이 사용될 수 있는 곳 - 클래스, 메서드, 멤버변수, 지역변수

대상의미
클래스변경될 수 없는 클래스, 확장될 수 없는 클래스가 된다.
그래서 final로 지정된 클래스는 다른 클래스의 조상이 될 수 없다.
메서드변경될 수 없는 메서드, final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다.
멤버변수변수 앞에 final이 붙으면 값을 변경할 수 없는 상수가 된다.
지역변수""

✡ 대표적인 final클래스로는 String과 Math가 있다

final class FinalTest {				// 조상이 될 수 없는 클래스
	final int MAX_SIZE = 10;		// 값을 변경할 수 없는 멤버변수 (상수)
    
    final void getMaxSize() {		// 오버라이딩할 수 ㅇ벗는 메서드 (변경 불가)
    	final int LV = MAX_SIZE;	// 값을 변경할 수 없는 지역변수 (상수)
        return MAX_SIZE;
	}
}

4. abstract - 추상의, 미완성의

메서드의 선언부만 작성하고 실제 수행내용은 구현하지 않은 추상 메서드를 선언하는데 사용한다.

abstract가 사용될 수 있는 곳 - 클래스, 메서드

대상의미
클래스클래스 내에 추상 메서드가 선언되어 있음을 의미한다.
메서드선언부만 작성하고 구현부는 작성하지 않은 추상 메서드임을 알린다.
abstract class AbstractTest {	// 추상 클래스 (추상 메서드를 포함한 클래스)
	abstract void move();		// 추상 메서드 (구현부가 없는 메서드)
}

5. 접근 제어자 (access modifier)

  • 멤버 또는 클래스에 사용되어, 해당하는 멤버 또는 클래스를 외부에서 접근하지 못하도록 제한하는 역할을 한다.
  • 접근 제어자가 default임을 알리기 위해 실제로 default를 붙이지는 않는다. 클래스나 멤버변수, 메서드, 생성자에 접근 제어자가 있지 않다면, 접근 제어자가 default임을 뜻한다.
제어자같은 클래스같은 패키지자손 클래스전체
public
protectedX
defaultXX
privateXXX

접근 범위

public > protected > default > private

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

클래스나 멤버, 주로 멤버에 접근 제어자를 사용하는 이유는 클래스 내부에 있는 선언된 데이터를 보호하기 위해서이다.
데이터를 외부에서 함부로 변경하지 못하도록 하기 위해서 외부로부터 접근을 제한하는 것이 필요하다.
이것을 데이터 감추기(data hiding)라고 하고 하며, 객체지향개념의 캡슐화(encapsulation)에 해당하는 내용이다.

접근 제어자를 사용하는 이유

  • 외부로부터 데이터를 보호하기 위해서
  • 외부에는 불필요한, 내부적으로만 사용되는, 부분을 감추기 위해서
public class Time {
	public int hour;
    public int minute;
    public int second;
}

	// 인스턴스 생성
	Time t = new Time();
	t.hour = 123456;

위와 같이 접근제어자를 크게 열어두게 되면 외부에서 데이터를 아무렇게 변경할 수 있어서 개발시 매우 치명적이다.
보통은 멤버변수를 private, protected로 제한하고 멤버변수를 읽고 쓸 변경할 수 있는 public 메서드를 제공함으로써 간접적으로 멤버변수 값을 다룰 수 있도록 하는 것이 바람직하다.
✡ 쉽게 getter, setter를 생각하면 된다.

생성자의 접근 제어자

생성자에 접근 제어자를 사용함으로써 인스턴스의 생성을 제한할 수 있다.
생성자의 접근 제어자를 private으로 지정하면, 외부에서 생성자에 접근할 수 없으므로 인스턴스를 생성할 수 없게 된다.

final class Singleton {	// final 키워드 추가해서 상속할 수 없는 클래스라는 것을 명시
	private static Singleton s = new Singleton();
    // 기본 생성자를 private으로 지정하여 외부에서 접근할 수 없게 한다.
    private Singleton() { ... } 
    // 인스턴스를 생성하지 않고도 호출할 수 있어야 하므로 static이어야 한다.
    public static Songleton getInstance() { 
    	if(s == null) {
        	s = new Singleton();
        }
        
        return s;
    }

생성자가 private인 클래스는 다른 클래스의 조상이 될 수 없다.
왜냐하면, 자손클래스의 인스턴스를 생성할 때 조상클래스의 생성자를 호출해야만 하는데, 생성자의 접근 제어자가 private이므로 자손 클래스에서 호출하는 것이 불가능하기 때문이다.
그래서 클래스 앞에 final을 더 추가하여 상속할 수 없는 클래스라는 것을 알리는 것이 좋다.
✡ 시간이 나면 Sngleton에 대해서도 공부해보자.

6. 요약

대상사용가능한 제어자
클래스public, default, final, abstract
메서드모든 접근 제어자, final, abstract, static
멤버변수모든 접근 제어자, final, static
지역변수final

주의사항

  1. 메서드에 static과 abstract를 함께 사용할 수 없다.
    • static메서드는 몸통이 있는 메서드에만 사용할 수 있기 때문이다.
  2. 클래스에 abstract와 final을 동시에 사용할 수 없다.
    • 클래스에 사용되는 final은 클래스를 확장할 수 없다는 의미이고 abstract는 상속을 통해서 완성되어야 한다는 의미이므로 서로 모순이 되기 때문이다.
  3. abstract메서드의 접근 제어자가 private일 수 없다.
    • abstract메서드는 자손클래스에서 구현해주어야 하는데 접근 제어자가 private이면, 자손 클래스에서 접근할 수 없기 때문이다.
  4. 메서드에 private와 final을 같이 사용할 필요는 없다.
    • 접근 제어자가 private인 메서드는 오버라이딩 될 수 없기 때문이다.
      이 둘 중 하나만 사용해도 의미가 충분하다.

✅ 다형성 (polymorphism)

다형성이란?

'여러 가지 형태를 가질 수 있는 능력'을 의미하며, 자바에서는 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 하는 것이다.
조금 더 구체적으로 말하면, 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있는는 것.

profile
내가 볼라고 씀.
post-custom-banner

0개의 댓글