[KOSTA JAVA] #Day 4 (OOP, Object, Class, Field, Constructor, Instance, this, Singleton, package, static, Getter, Setter)

0f1c04·2021년 2월 19일
0

KOSTA JAVA TIL

목록 보기
4/11
post-thumbnail

신용권님의 ''이것이 자바다'' 공부 기록

책을 보면서 내용을 정리했습니다. 이것이 자바다 커뮤니티 : https://cafe.naver.com/thisisjava

#Day 4

  1. 객체 지향 프로그래밍
  2. 객체(Object)와 클래스(Class)
  3. 객체 생성과 클래스 변수
  4. 클래스의 구성 멤버
  5. 필드(Field)
  6. 생성자(Constructor)
  7. 메소드(Method)
  8. 인스턴스 멤버와 this
  9. 정적 멤버와 static
  10. 패키지(package)
  11. Getter와 Setter
  12. 어노테이션(Annotation)

1.객체 지향 프로그래밍

  • OOP: Object Oriented Programming
  • 부품 객체를 먼저 만들고 이것들을 하나씩 조립해 완서오딘 프로그램을 만드는 기법

1-1. 객체(Object)란

  • 물리적으로 존재하는 것
  • 추상적인 것 중에서 자신의 속성과 동작을 가지는 모든 것
  • 객체는 필드(속성)과 메소드(동작)로 구성된 자바 객체로 모델링 가능

1-2. 객체간의 관계

  • 객체 지향 프로그램에서는 객체는 다린 객체와 관계를 맺음
  • 관계의 종류
    • 집합 관계 : 완성품과 부품의 단계
    • 사용 관계 : 객체가 다른 객체를 사용하는 관계
    • 상속 관계 : 종류 객체와 구체적인 사물 객체 관계

1-3. 객체 지향 프로그래밍의 특징

캡슐화

  • 객체의 필드, 메서드를 하나로 묶고 실제 구현 내용을 감추는 것
  • 외부 객체는 객체 내부 구조를 알지 못하며 객체가 노출해 제공하는 필드와 메서드만 이용 가능
  • 필드와 메서드를 캡슐화하여 보호하는 이유는 외부의 잘못된 사용으로 인해 객체가 손상되지 않도록
  • 자바는 캡슐화된 멤버를 노출시킬 것인지 숨길 것인지 결정하기 위해 접근 제한자 사용

상속

  • 상위(부모) 객체의 필드와 메서드를 하위(자식) 객체에게 물려주는 행위
  • 하위(자식) 객체는 상위 객체를 확장해서 추가적인 필드와 메서드를 가질 수 있음
  • 상속 대상: 필드와 메서드
  • 상속의 효과
    • 상위 객체를 재사용해서 하위 객체를 빠른 시간내에 개발 가능
    • 반복된 코드의 중복 최소화
    • 유지 보수의 편리
    • 객체의 다형성 구현

다형성

  • 같은 타입인지만 실행 결과가 다양한 객체를 대입할 수 있는 성질로 부모 타입에는 모든 자식 객체가 대입이고 인터페이스 타입에는 모든 구현 객체가 대입이다.
  • 효과로 객체를 부품화시키는 것이 가능하며 유지보수가 용이하다.

2. 객체와 클래스

  • class : object를 만드는 틀 (template, 설계도) (변수와 메서드들의 묶음)
  • object : class를 이용해서 만든 독립된 개체 = instance
  • instance : object실체 = object

3. 객체 생성과 클래스 변수

3-1. new 연산자

객체 생성 역할로 new 클래스(); 으로 생성할 수 있다. 클래스()은 생성자를 호출하는 코드로 생성된 객체는 힙 메모리 영역에 생성된다.

new 연산자는 객체를 생성 후, 객체 생성 번지를 리턴한다.

3-2. 클래스 변수

new 연산자에 의해 리턴 된 객체의 번지를 저장한다. (참조 타입 변수)

힙 영역의 객체를 사용하기 위해 사용한다.

클래스 변수;
변수 = new 클래스();

클래스 변수 = new 클래스();


4. 클래스의 용도

  • 라이브러리(API: Application Program Interface) 용도
    • 자체적으로 실행되지 않는다.
    • 다른 클래스에서 이용할 목적으로 만든 클래스이다.
  • 실행용도
    • main() 메소드를 가지고 있는 클래스로 실행할 목적으로 만든 클래스

5. 클래스의 구성 멤버

  • 필드(Field) : 객체의 데이터가 저장되는 곳
  • 생성자(Constructor) : 객체 생성시 초기화 역할 담당
  • 메소드(Method) : 객체의 동작에 해당하는 실행 블록
public class ClassName {
    //필드
    int fieldName;
    
    //생성자
    ClassName() {...}
    
    //메서드
    void methodName() {...}
}

6. 필드(field)

6-1. 필드의 내용

  • 객체의 고유 데이터, 객체가 가져야 할 부품 객체, 객체의 현재 상태 데이터 등이 있다.

6-2. 필드 선언

타입 필드 [ = 초기값];

String company = "현대자동차";
String model = "그랜저";
int maxSpeed = 300;
int productionYear;
int currentSpeed;
boolean engineStart;

6-3. 필드의 기본 초기값

  • 초기값 지정되지 않은 필드는 객체 생성시 자동으로 기본값으로 초기화된다.

6-4. 필드 사용

  • 필드값을 읽고, 변경하는 작업, 필드 사용위치는 객체 내부와 외부로 나눠져 있으며 내부에서는 필드이름으로 바로 접근 가능하지만 객체 외부에서는 변수.필드이름 식으로 접근해야한다.
void method() {
    //Car 객체 생성
    Car myCar = new Car();
    //필드 사용
    myCar.speed = 60;
}
  • Person 클래스
//필드
int speed;

//생성자
Car() {
    speed = 0;
}

//메서드
void method(...) {
    speed = 10;
}
  • Car 클래스

  • Person 클래스는 외부객체이므로 "변수.필드이름"식으로 접근해야한다.


7. 생성자

  • new 연산자에 의해 호출되어 객체의 초기화 담당으로 필드의 값을 설정할 수 있고, 메소드를 호출해 객체를 사용할 수 있도록 준비하는 역할을 수행한다.

7-1. 기본 생성자(Default Constructor)

  • 모든 클래스는 생성자가 반드시 존재하며 하나 이상 가질 수 없다.
  • 생성자 선언을 생략하면 컴파일러는 다음과 같은 기본 생성자를 추가한다.
소스 파일(Car.java)
public class Car {...}

바이트 코드 파일(Car.class)
public class Car {
    public Car() {} //기본 생성자 자동 추가
}

소스 파일(CarTest.java)
Car myCar = new Car(); // <-- 기본 생성자

7-2. 생성자 선언

  • 기본 생성자 대신 개발자가 직접 선언
클래스(매개변수선언, ...) {
    //객체의 초기화 코드
}
  • 개발자가 선언한 생성자 존재 시 컴파일러는 기본 생성자를 추가하지 않는다. new 연산자로 객체 생성시 개발자가 선언한 생성자를 반드시 선언한다.
public class Car {
    //생성자
    Car(String model, String color, int maxSpeed) {...}
}

-------------------------------------------------------

Car myCar = new Car("그랜저", "검정", 300);

7-3. 필드 초기화

  • 초기화 없이 선언된 필드는 객체가 생성될 때 기본값으로 자동 설정
  • 다른 값으로 필드 초기화하는 방법
    • 필드 선언할 때 초기값 설정
    • 생성자의 매개값으로 초기값 설정
    • 매개 변수와 필드명 같은 경우 this 사용 (나중에 배움)
//생성자의 매개값으로 초기값 설정
Korean k1 = new Korean("임자바", "900111-1234567");
Korean k2 = new Korean("배자바", "900222-2345678");

7-4. 생성자를 다양화해야 하는 이유

  • 객체 생성할 때 외부 값으로 객체를 초기화할 때 필요하다.
  • 외부 값이 어떤 타입으로 몇 개가 제공될 지 모르므로 생성자도 다양화해야 한다.

7-5. 생성자 오버로딩(Overloading)

  • 매개변수의 타입, 개수, 순서가 다른 생성자를 여러개 선언

7-6. 다른 생성자 호출(this())

  • 생성자 오버로딩되면 생성자 간의 중복된 코드 발생한다.
  • 초기화 내용이 비슷한 생성자들에서 이러한 현상을 많이 볼 수 있다.
    • 초기화 내용을 한 생성자에 몰아 작성할 때 사용한다.
    • 다른 생성자는 초기화 내용을 작성한 생성자를 this(...)로 호출한다.


생성자 예제

package com.kosta.day04;

public class StudentTest {

	public static void main(String[] args) {
            method1();
	}

	private static void method1() {
		Student lim = new Student();
		lim.printStudent();
		
		Student bae = new Student("배대장", "정보보호", "18014016", 23);
		bae.printStudent();
		
		Student kim = new Student("김갑수", "영문과");
		kim.printStudent();
		
		Student park = new Student("박을용", 27);
		park.printStudent();
	}

}
package com.kosta.day04;

//class (object들의 공통된 특성, 행동)
public class Student {
	// 1.멤버변수 선언 (필드)
	String name;	
	String major;
	String no;
	int age;

	// 2.생성자 메서드 선언 (생성시 자동호출 : 초기화 목적)
	// 정의하지않는다면 Default 생성자 제공
	// 정의한다면 Default 생성자 없어짐 (사용불가)
	public Student() {
		//default 생성자 : argument없음
		System.out.println("Default 생성자 생성: No argument");
	}
	public Student(String name, int age) {
		//생성자가 다른모양의 생성자를 호출
		this(name, null, null, age);
	}
	public Student(String name, String major) {
		//생성자가 다른모양의 생성자를 호출
		this(name, major, null, 20);
	}
	public Student(String name, String major, String no, int age) { //오버로딩
		System.out.println("=======================학생 생성");
		this.name = name;
		this.major = major;
		this.no = no;
		this.age = age;
	}

	// 3.메서드(기능,행동)
	void study() {
		System.out.println(name + "공부 중");
	}

	String getMajor() {
		return name + "의 전공은 " + major;
	}

	int getAge() {
		return age;
	}
	
	void printStudent() {
		System.out.println("이름: " + name);
		System.out.println("전공: " + major);
		System.out.println("학번: " + no);
		System.out.println("나이: " + age);
	}
}
  • 학생 정보를 입력 받고 출력하는 생성자 예제

8. 메소드(Method)

  • 객체의 동작(기능)
  • 호출해서 실행할 수 있는 중괄호 {}블록
  • 메소드 호출하면 중괄호 {} 블록에 있는 모든 코드 일괄 실행

8-1. 메소드 선언

8-2. 메소드 리턴 타입

  • 메소드가 실행된 후 리턴하는 값의 타입
  • 메소드는 리턴값이 있을 수도 없을 수도 있다.
메소드 선언
void powerOn() {...}
double divide(int x, int y) {...}

메소드 호출
powerOn();
double result = divide(10, 20);

8-3 메소드 매개변수 선언

  • 매개변수는 메소드를 실행할 때 필요한 데이터를 외부에서 받기 위해 사용한다.
  • 매겨변수도 필요 없을 수 있다.
메소드 선언
void powerOn() {...}
double divide(int x, int y) {...}

메소드 호출
powerOn();

#1
double result = divide(10, 20);

#2
byte b1 = 10;
byte b2 = 20;
double result = devide(b1, b2);

8-4. 리턴(return) 문

  • 메소드 실행을 중지하고 리턴값을 지정하는 역할이다.
  • 리턴값이 없는 메소드는 메소드 실행을 강제 종료하는 역할이다.
  • 리턴값이 있는 메소드는 반드시 리턴(return)문을 사용해서 리턴값을 지정해야한다. return문 뒤에는 실행문이 올 수 없다.
int plus(int x, int y) {
    int result = x + y;
    return result;
}

boolean isLeftGas() {
    if(gas == 0) {
    	System.out.println("gas가 없습니다.");
        return false;
    }
   	System.out.println("gas가 있습니다.");
    return true;
}

8-5. 메소드 호출

  • 메소드는 클래스 내,외부의 호출에 의해 실행된다.
  • 클래스 내부는 메소드 이름으로 호출하고 클래스 외부는 객체 생성 후, 참조 변수를 이용하여 호출한다.
외부호출
void 외부메소드() {
    Car car = new Car();
    car.run();
    car.stop();
    car.sound();
}

내부호출
메소드 선언
void run() {...}
void stop() {...}
void sound() {...}

void 내부메소드() {
    run();
    stop();
    sound();
}

8-6. 메소드 오버로딩

  • 클래스 내에 같은 이름의 메소드를 여러개 선언하는 것을 말한다.
  • 하나의 메소드 이름으로 다양한 매개값을 받기 위해 메소드 오버로딩을 사용한다.
  • 오버로딩의 조건: 매개변수의 타입, 개수, 순서가 달라야 한다.
class 클래스 {
리턴타입 메소드이름 (타입 변수, ...) {...}
(무관)  (동일)   (매개변수의 타입, 개수, 순서가 달라야한다.)
리턴타입 메소드이름 (타입 변수, ...) {...}

ex)
//plus(10, 20)
int plus(int x, int y) {
    int result = x + y;
    return result;
}

//plus(10.5, 20.3)
double plus(double x, double y) {
    double result = x + y;
    return result;
}

9. 인스턴스 멤버와 this

9-1. 인스턴스 멤버란

  • 객체(인스턴스)마다 가지고 있는 필드와 메소드를 말한다. 이들을 각각 인스턴스 필드, 인스턴스 메소드라 부른다.
  • 인스턴스 멤버는 객체 소속된 멤버이기 때문에 객체가 없이 사용 불가하다.

public class Car {
    //필드
    int gas;
    
    //메소드
    void setSpeed(int speed) {...}
}
Car myCar = new Car();
myCar.gas = 10;
myCar.setSpeed(60);

Car yourCar = new Car();
yourCar.gas = 20;
yourCar.setSpeed(80);

9-2. this

객체(인스턴스) 자신의 참조(번지)를 가지고 있는 키워드

객체 내부에서 인스턴스 멤버임을 명확히 하기 위해 this. 사용

매개변수와 필드명이 동일할 때 인스턴스 필드임을 명확히 하기 위해 사용

Car(String model) {
    this.model = model;
}

void setModel(String model) {
    this.model = model;
}

10. 정적 멤버와 static

10-1. 정적(static) 멤버란

  • 클래스에 고정된 필드와 메소드(정적필드, 정적메소드)를 말한다.
  • 정적 멤버는 클래스에 소속된 멤버로 객체 내부에 존재하지 않고, 메소드 영역에 존재하며 정적 멤버는 객체를 생성하지 않고 클래스로 바로 접근해 사용한다.

10-2. 정적 멤버 선언

  • 필드 또는 메소드 선언할 때 앞에 static 키워드를 붙인다.
public class 클래스 {
    //정적 필드
    static 타입 필드 [= 초기값];
    
    //정적 메소드
    static 리턴타입 메소드(매개변수선언, ...) {...}
}

10-3. 정적 멤버 사용

  • 클래스 이름과 함께 도트(.) 연산자로 접근한다.
클래스.필드;
클래스.메소드(매개값, ...);

public class Calculator {
    static double pi = 3.141592;
    static int plus(int x, int y) {...}
    static int minus(int x, int y) {...}
}

바람직한 사용
double result1 = 10 * 10 * Calculator.pi;
int result2 = Calculator.plus(10, 5);
int result3 = Calculator.minus(10, 5);

바람직하지 못한 사용
Calculator myCalcu = new Calculator();
double result1 = 10 * 10 * myCalcu.pi;
int result2 = myCalcu.plus(10, 5);
int result3 = myCalcu.minus(10,5);

10-4. 인스턴스 멤버 선언 vs 정적 멤버 선언의 기준

  • 필드
    • 객체마다 가지고 있어야 할 데이터는 인스턴스 필드
    • 공용적인 데이터는 정적 필드
public class Calculator {
    String color;				 //계산기 별로 색이 다를 수 있음
    static double pi = 3.141592; //계산기에서 사용하는 파이값은 동일
}
  • 메소드
    • 인스턴스 필드로 작업해야 할 메소드는 인스턴스 메소드
    • 인스턴스 필드로 작업하지 않는 메소드는 정적 메소드
public Calculator {
    String color;
    void setColor(String color) {this.color = color;}
    static int plus(int x, int y) {return x + y;}
    static int minus(int x, int y) {return x = y;}
}

10-5. 정적 초기화 블록

  • 클래스가 메소드 영역으로 로딩될 때 자동으로 실행하는 블록이다.
  • 정적 필드의 복잡한 초기화 작업과 정적 메소드 호출이 가능하다.
  • 클래스 내부에 여러 개가 선언되면 선언된 순서대로 실행
public class Television {
    static String company = "Samsung";
    static String model = "LCD";
    static String info;
    
    static {
        info = company + "-" + model;
    }
}

10-6. 정적 메소드와 정적 블록 작성시 주의점

  • 객체가 없어도 실행이 가능하다.
  • 블록 내부에 인스턴스 필드나 인스턴스 메소드는 사용 불가하다.
  • 객체 자신의 참조인 this의 사용이 불가하다.
//인스턴스 필드와 메소드
int field1;
void method1() {...}

//정적 필드와 메소드
static int field2;
static void method2() {...}

//정적 블록
static {
    field1 = 10;		// x 컴파일에러
    method1();			// x 컴파일에러
    field2 = 10;		// o
    method2();			// o
}

//정적 메소드
static void Method3 {
    this.field1 = 10;   // x 컴파일에러
    this.method1();		// x 컴파일에러
    field2 = 10;		// o
    method2()			// o
}

static void Method3() {
    ClassName obj = new ClassName();
    obj.field1 = 10;
    obj.method1();
}

10-7. 싱글톤(Singleton)

  • 하나의 애플리케이션 내에서 단 하나만 생성되는 객체

10-8. 싱글톤 만드는 방법

  • 외부에서 new 연산자로 생성자를 호출할 수 없도록 막기
    • private 접근 제한자를 생성자 앞에 붙임
  • 클래스 자신의 타입으로 정적 필드 선언
    • 자신의 객체를 생성해 초기화
    • private 접근 제한자를 붙여 외부에서 필드 값을 변경 불가하도록 선언
  • 외부에서 호출할 수 있는 정적 메소드인 getInstance() 선언
    • 정적 필드에서 참조하고 있는 자신의 객체 리턴

10-9. 싱글톤 얻는 방법

클래스 변수 1 = 클래스.getInstance();
클래스 변수 2 = 클래스.getInstance();

/*
Singleton obj1 = new Singleton(); //컴파일 에러
Singleton obj2 = new Singleton(); //컴파일 에러
*/

Singleton obj1 = Singleton.getInstance();
Singleton obj2 = Singleton.getInstance();

if(obj1 == obj2) {
    System.out.println("같은 Singleton 객체입니다.");
} else {
    System.out.println("다른 Singleton 객체입니다.");
}

11. 패키지(package)

11-1. 패키지란

  • 클래스를 기능별로 묶어서 그룹 이름을 붙여 놓은 것을 말한다.
    • 파일들을 관리하기 위해 사용하는 폴더(디렉토리)와 비슷한 개념이다.
    • 패키지의 물리적인 형태는 파일 시스템의 폴더이다.
  • 클래스 이름의 일부
    • 클래스를 유일하게 만들어주는 식별자이다.
    • 전체 클래스 이름은 상위패키지.하위패키지.클래스 형태로 되어있다.
    • 클래스명이 같아도 패키지명이 다르면 다른 클래스로 취급된다.
  • 클래스 선언할 때 패키지 변경
    • 클래스 선언할 때 포함될 패키지를 선언한다.
    • 클래스 파일은(~.class) 선언된 패키지와 동일한 폴더 안에서만 동작한다.
    • 클래스 파일은(~.class) 다른 폴더 안에 넣으면 동작하지 않는다.

11-2. Import 문

  • 패키지 내에 같이 포함된 클래스간 클래스 이름으로 사용 가능하다.
  • 패키지가 다른 클래스를 사용해야 할 경우
  • 패키지명이 포함된 전체 클래스 이름으로 사용한다.
package com.mycompany;

public class Car {
    com.hankook.Tire tire = new.com.hankook.Tire();
}
  • Import 문으로 패키지를 지정하고 사용한다.
package com.mycompany;

import com.hankook.Tire;
[or import com.hankook.*;]

public class Car {
	Tire tire = new Tire();
}

12. Getter와 Setter

클래스 선언할 때 필드는 일반적으로 private 접근 제한

  • 읽기 전용 필드가 있을 수 있다.(Getter의 필요성)
  • 외부에서 엉뚱한 값으로 변경할 수 없도록 한다.(Setter의 필요성)

12-1. Getter

  • private 필드의 값을 리턴하는 역할이다. 필요할 경우 필드 값을 가공할 수 있다.
  • getFieldName() 또는 isFieldName() 메소드 (필드 타입이 boolean일 경우 is를 붙임)

12-2. Setter

  • 외부에서 주어진 값을 필드 값으로 수정, 필요할 경우 외부의 값을 유효성 검사
  • setFieldName(타입 변수) 메소드 (매개 변수 타입은 필드의 타입과 동일)

확인문제 풀이

package com.kosta.day04;

public class Person {
	private static int numberOfPersons;
	int age;
	String name;
	
	Person() {
		this(12, "Anonymous");
	}
	Person(int age, String name) {
		this.age = age;
		this.name = name;
		numberOfPersons++;
	}
	
	void selfIntroduce() {
		System.out.println("내 이름은 " + name + "이며, 나이는 " + age + "살 입니다.");
	}
	static int getPopulation() {
		return numberOfPersons;
	}
	
	public static void main(String[] args) {
		Person anonymous = new Person();
		anonymous.selfIntroduce();
		Person lim = new Person(25, "임덕배");
		lim.selfIntroduce();
		
		System.out.println(Person.getPopulation() + "명의 인구수가 있습니다.");
	}
}
profile
라면 먹고 싶다. 두 개 끓여서 혼자 먹고 싶다. - 임덕배 (1997. 06 ~ )

0개의 댓글