-
221212. 자바 4 {생성자 (접근제한자, this, super, 상속) }스타터스 백엔드 3기 2022. 12. 12. 15:47
하루입니다.
chap6/src/constructor 패키지 생성, EmployeeTestI(생성자!), VarInitTest(값초기화)
chap7 - ManagerTest(상속), SuperTest / sba - A, academy - B, board - OneBoard
복습!!!
자바는?
표현하려는 현실 객체의 특성을 파악하고, 클래스로 정의하고, 원하는 만큼 인스턴스를 생성하자.
main 메소드의 선언부는 정해져 있다. 객체 생성, 실행을 시작하는 메소드라는 뜻이다.
변수
static 변수 멤버변수 메소드 외부 선언
클래스명.static변수 로 선언한다.
객체생성 이전 시점에서 클래스 메모리 영역 하나를 공유한다.final 변수 멤버변수, 지역변수 메소드 내부 / 외부에서 사용 가능하다. "상수"
final int i = 10; 이라고 하면,
i++ 이런 건 에러이다. 변하지 못한다.static 안 붙은 변수 멤버변수 메소드 외부 선언
객체생성 이후 시점에서 생성되며, heap 메모리 영역 여러개를 사용한다.final 안 붙은 변수 멤버변수 메소드 외부 선언 지역변수 지역변수 메소드 내부에 선언한다. 메소드 내부에 국한되어 사용된다. 메소드
[modifier] 리턴타입 메소드이름 (매개변수(있을수도 없을수도)) {
return ... ; (있을수도 없을수도)
}
매개변수
- 외부로부터 전달받는 방식이다.
- call by value
- 값을 복사하여 전달한다.
- 기본형은 실제값을 복사하여 전달한다. 메소드의 매개변수값이 변경되어도 원래 전달된 인수값이 변경되지 않는다.
- 참조형은 주소값을 복사하여 전달한다. 같은 객체를 동일하게 참조하기에, 같은 객체 내부값을 변경하면 영향을 받는다.
void a( ) {
return 키워드는 메소드를 중단하겠다는 뜻이다.
있어도 되고 없어도 된다.
}String b( ) {
}void + 기본형 8개 + 참조형(배열, String, class) static 메소드
1. 객체가 생성되기 이전에 메모리에 할당된다.
2. 객체가 생성되기 이전에 메모리에 할당되는 변수만 사용 가능하다. static 변수만 사용 가능하다는 뜻이다.
메소드의 overloding
- 1개 클래스에 같은 이름의 메소드를 여러개 정의하는 구문이다.
- 매개변수의 갯수, 타입, 순서 등 중 1개 이상이 다르게 정의되어야 한다.
- 의미적으로는 유사한 기능을 구현하기 위해 사용한다.
- 매개변수에 따라 여러가지 방법이 제공된다는 뜻이기도 하다. 다형성!!!
생성자
오늘 배우는 내용은 생성자와 관련된 내용들이다.

생성자란?
- 클래스 내부에 선언되는 구성 요소 중 하나이다.
- constructor는 객체가 생성되도록 호출한다.
- new 키워드 뒤에서 호출된다. 객체가 생성되는 시점에서 호출된다.
- 클래스명과 같다.
- 자바의 모든 클래스에는 기본 생성자가 자동으로 정의되어 있다.
- 매개변수 없고 super(); 라는 내용이 구현되어 있다.
- 클래스명() {super();}
- 사용자가 생성자를 정의하며면 기존에 정의된 생성자가 사라진다.
- 객체를 생성하고 변수값을 초기화하기 위한 용도이다.
- 1개 클래스에 여러개의 생성자를 정의할 수 있으나, 매개변수의 리스트는 다르게 정의해야 한다. (overloading) 생성자를 오버로딩하는 것이다. 같은 객체를 생성하는 방법을 여러 개 제공한다.
Employee e1 = new Employee(); Employee e1 = new Employee(); 클래스명 객체주소참조변수명 객체생성연산자 클래스명();생성자호출(); - stack 영역에 e1변수가 할당된다. (null이다.)
- new가 실행되며 heap영역의 1000번지에 Employee(변수 + 메소드를 복사한)가 할당된다.
- Employee() 에 정의된 내용이 실행된다.
- = 대입연산자가 실행되며, e1은 1000번지를 참조하게 된다.
생성자 호출을 살펴보자

class Employee { Employee() { System.out.println("employee 생성자를 호출합니다."); } int id; String name; String title; String dept; double salary; void printInform() { System.out.printf("사번 %d번, 이름 %s, 직급 %s, 부서명 %s, 급여 %.2f입니다. \n", this.id, name, title, dept, salary); } } public class EmployeeTest { public static void main(String[] args) { Employee arr[] = new Employee[10]; Employee e1 = new Employee(); // 객체에 값 할당 Employee e2 = new Employee(); // 객체에 값 할당 } } ------------------------------------------------------------------ employee 생성자를 호출합니다. 사번 100번, 이름 이사원, 직급 사원, 부서명 it개발부, 급여 10000.00입니다. employee 생성자를 호출합니다. 사번 200번, 이름 박사원, 직급 대리, 부서명 인재개발부, 급여 15000.00입니다.매개변수 받는 생성자를 만들자
class Employee { // 자바에서 자동으로 실행되는 것을 보자. 아래 코드가 항상 자동으로 실행된다. Employee(int id, String name, String title, String dept , int s) { this.id = id; this.name = name; this.title = title; this.dept = dept; salary = s; } int id; String name; String title; String dept; double salary; } public class EmployeeTest { public static void main(String[] args) { Employee arr[] = new Employee[10]; Employee e1 = new Employee(100, "김가가", "사원", "it개발부", 10000); e1.printInform(); Employee e2 = new Employee(200, "김나나", "대리", "인재개발부", 15000); // 생성자를 만들었기에 기존 생성자가 사라진다. 매개변수 없는 생성자는 오류난다. e2.printInform(); } }
멤버변수의 초기화
- 객체변수를 선언하면 자동으로 초기화된다.
- int - 0, String - null, double = 0.000000, boolean - false
- 객체변수는 자동으로 초기화된다. (int a; ==> a는 0이다.)
- 지역변수는 자동으로 초기회되지 않는다. 사용자가 초기화해야 한다. (int a; 오류 발생)
- 생성자 ... 생성자를 사용해서 멤버변수를 초기화하자.
- 모든 객체변수들은 처음에 선언과 함께 자동으로 초기화된 값을 가진다. 객체가 생성ㅇ될 때는 생성자를 호출하고, 생성자를 호출하자마자 내부의 값은 초기화된다(바뀐다).

실행 순서. 초기화블럭이 생성자보다 먼저 실행된다.
객체지향언어의 조건
1. 캡슐화(연관 데이터 + 기능 = 클래스) + 정보은닉
2. 상속
3. 다형성 - 메소드와 생성자 overloading
+. 썼던 코드 또 쓰지 말자!!! 있던 거 불러서 쓰자!!!
상속
- 자손 클래스는 조상 클래스의 모든 멤버를 상속받는다. (생성자와 초기화 블록은 상속받지 않는다.)
- 자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다.
class 사람 {
이름 나이
잠자다 밥먹다
}부모클래스
상위클래스
super class
base class
class 회사원 extends 사람 {
이름 나이 급여 직급 사번
잠자다 밥먹다 일하다 출퇴근하다
}- 회사원 클래스는 사람 클래스를 상속받았다.
- 이는 사람 안의 데이터가 회사원 클래스 안으로 자동 포함됨을 뜻한다.
class 학생 extends 사람 {
이름 나이 학번 성적
잠자다 밥먹다 공부하다 통학하다
}- 학생 클래스는 사람 클래스를 상속받았다.
- 이는 사람 안의 데이터가 학생 클래스 안으로 자동 포함됨을 뜻한다.
- 사람 클래스의 자식 클래스이다.
- 초등학생 클래스의 부모 클래스이다.
학생과 회사원의 속성을 모두 가지는 조교 클래스가 있다.
class 조교 extends 회사원, 학생 {
이름 나이 학번 성적 급여 직급 사번
잠자다 밥먹다 공부하다 통학하다 일하다 출퇴근하다
}불가하다.
- extends 1개 클래스 상속 : 단일상속
- extends 2개 클래스 상속 : errorclass 초등학생 extends 학생 {
현장체험가다
}- 사람 클래스, 학생 클래스를 상속받는다. 객체를 만들어야 할까, 상속받아야 할까?
class A {
int i
void a( ) { }
}1. 객체를 만드는 경우
class B {
A a1 = new A();
a1.i;
}2. 상속받는 경우
class C extends A {
// 상속, 변수 자동 포함
}class 학생 extends 사람 학생은 사람"이다"
is a relatiionship이다.
'is a'라면 상속 관계이다.class Car {
전진하다();
정지하다();
}
class Driver {
운전하다();
전진하다();
정지하다();
Car car = new Car() {
car.전진하다();
car.정지하다();
}
}운전자는 자동차 "이다" ?
운전자는 자동차"를 가지다".
'has a'라면 소유 관계이다.
has a relationship이라면 객체를 생성하는 것이 맞다.class Employee { int id; String name; String dept; double salary; void calcSalary(int salary) { this.salary = salary*2; } void printAll() { System.out.printf("사번 %d, 이름 %s, 부서 %s, 급여 %.2f", id, name, dept, salary); } } class Manager extends Employee{ String job; // Employee(부모 클래스)에서 정의한 대로 calcSalary();와 printAll(); 메소드를 상속받아서 사용했다. // 직업까지 출력하고 싶기에 메소드 내용 수정이 필요하다. // 상속 후에 하위클래스에서 메소드 내용을 재정의하는 것을 메소드 overriding이라고 한다. @Override void printAll() { System.out.printf("사번 %d, 이름 %s, 부서 %s, 급여 %.2f, 직종 %s\n", id, name, dept, salary, job); } } public class ManagerTest { public static void main(String[] args) { Manager m = new Manager(); m.id = 100; // 상속 m.name = "김가가"; // 상속 m.dept = "영업부"; // 상속 m.job = "영업관리"; // 자식 m.calcSalary(40000); // 상속받은 그대로 사용한다. m.printAll(); // 상속받은 후 메소드를 재정의(오버라이드) 했다. } }다중상속이 불가한 이유
class A { int i = 10; } class B { int i = 20; } class C extends A, B { // int i, int i, int k를 가지게 된다. 둘 중 뭘 사용해야 할지 모른다. int k = 30; }java.lang.Object
- java.lang.Object라는 클래스의 라이브러리가 있다.
- 자바가 자동으로 실행하는 것이 있는데, class A 라고만 적는다면 뒤에 자동으로 extends Object를 붙인다. 즉, class의 최고 조상은 java.lang.Object이다.
- java.lang.Object에 있는 클래스 변수, 메소드 등은 자바의 모든 클래스가 사용할 수 있다.
오버로딩과 오버라이딩
오버로딩 overloading 오버라이딩 overriding 1개 클래스를 같은 이름의 메소드로 정의한다. 상,하위 클래스를 같은 이름의 메소드로 정의한다. 매개변수를 다르게 정의한다. 매개변수 동일해야 한다. 리턴타입 무관하다. 리턴타입 동일해야 한다. modifier 무관하다. 접근제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다. modifier 같거나 더 넓어야 한다.
부모가 class => 자식은 최소 class, public, protect
priavte 안 된다.유사한 기능을 매개변수 유형에 따라 여러개 사용하기 위한 목적이다. 상위 클래스를 사용자가 원하는 모습으로 수정해서 하위클래스로 사용하기 위한 목적이다. 오버라이딩을 위해서는 반드시 상속해야 한다. 재정의된 메소드가 우선순위이다. // 매개변수를 잘못 주면 오버로딩처럼 인식한다. printAll 이라는 메소드를 오버로딩 했다고 생각한다. // 그래서 @Overriding 적어줘야 한다. @Override void printAll() { System.out.printf("사번 %d, 이름 %s, 부서 %s, 급여 %.2f, 직종 %s\n", id, name, dept, salary, job); } void printAll(int i) { System.out.printf("사번 %d, 이름 %s, 부서 %s, 급여 %.2f, 직종 %s\n", id, name, dept, salary, job); }
접근자
- package는 클래스(.class)의 폴더이다. 유사한 성격의 클래스를 분류해서 모은 것이다.
- board는 게시물 연관 클래스들, product는 상품 관리 연관 클래스들 ...
다른 패키지의 class 들고 오는 법
- 만약 작성하는 클래스와 같은 패키지에 속하는 클래스는 자동 import된다.
- java.lang.패키지에 속한 클래스는 자동 import된다.
1. 패키지명.클래스명 sba.A a1 = new sba.A();2. import 하기 import sba.A; A a1 = new A();접근자
클래스, 변수, 메소드, 생성자를 다른 클래스에서 호출할 때 사용 권한을 제한하는 것이다.
public protected default(no modifier) private 모든 클래스에 무제한 현재 패키지 + 나를 상속받은 다른 패키지의 하위 클래스만 사용 가능 현재 패키지 안의 다른 클래스에서만 사용 가능 현재 클래스 내부에서만 사용 가능 package p;
class A {
int i = 10;
void ma() {
syso(i);
}
}
class b{
A a1 = new A();
syso(a1.i);
}package q;
class C{
A a1 = new A();
syso(a1.i);
}
classD extends A {
syso(i);
}package p;
class A {
private int i = 10;
void ma() {
syso(i);
}
}
class b{
A a1 = new A();
syso(a1.i); 같은 클래스 아니라서 접근 불가
}package q;
class C{
A a1 = new A();
syso(a1.i); 같은 클래스 아니라서 접근 불가
}
classD extends A {
syso(i); 같은 클래스 아니라서 접근 불가
}package p;
class A {
protected int i = 10;
void ma() {
syso(i);
}
}
class b{
A a1 = new A();
syso(a1.i);
}package q;
class C{
A a1 = new A();
syso(a1.i); 다른 패키지라 접근 부락
}
classD extends A {
syso(i); 다른 패키지지만 상속받아서 i 사용 가능하다.
}package p;
public class A {
int i = 10;
void ma() {
syso(i);
}
}
class b{
A a1 = new A();
syso(a1.i);
}package q;
class C{
A a1 = new A();
syso(a1.i);
}
classD extends A {
syso(i);
}
굳이 modifier를 사용하는 이유는?
- 정보를 은닉하기 위해서이다.
- 외부로부터 데이터를 보호하기 위해서이다.
- 캡슐화(연관 데이터 + 기능단위 = 클래스) + 정보은닉
- 변수 앞에 private이 붙으면 철저히 내 클래스 안에서만 은닉하겠다 라는 뜻임.
- 보통 변수는 private, 메소드는 public 을 사용한다. 변수는 은닉, 변수에 접근 가능한 메소드는 public을 사용하는 것.
예시
class 계좌 {
암호;
계좌번호;
입금 ( ) { };
출금 ( ) { };
암호변경( ) { };
}계좌 acc1 = new 계좌("123-456", 1234);
acc1.암호 = 4321;
이렇게 되면 모르는 사람이 내 계좌의 암호 상태를 변경한 것이다.class 계좌 {
private int 암호 = 1234;
계좌번호;
입금 ( ) { };
출금 ( ) { };
public 암호변경( ) { };
}계좌 acc1 = new 계좌("123-456", 1234);
acc1.암호변경();
암호를 직접 변경하는 게 아닌, 메소드를 사용해서 접근한다.
this
현재 자신 객체를 의미하는 자바 키워드이다.
사용법 1. 매개변수/지역변수 이름이 객체변수의 이름과 같다면 구분하기 위해 사용한다. this.객체변수
의미 구분을 명확히 하기 위해 사용한다.
생성자 뿐 아니라 메소드에서도 사용한다.
사용법 2. 현재 객체에 다른 생성자를 호출할 때 사용한다. 반드시 생성자가 오버로딩 되었을 때 사용해야 한다.
반복해서 정의하지 않고 재사용하기 위해서 사용한다.
생성자 내부 첫 문장에서 사용해야 한다. !!!

사용법 1 예시

사용법 2 예시
Employee(int id, String name, String title, String dept , int s) { this.id = id; this.name = name; this.title = title; this.dept = dept; salary = s; } Employee(int id, String name) { this(id, name, "직급미정", "배치이전", -1); } Employee() { this(-1, "미상", "직급미정", "배치이전", -1); } _______________________________________________________________________________________________ 사번 100번, 이름 김가가, 직급 사원, 부서명 it개발부, 급여 10000.00입니다. 사번 200번, 이름 대리, 직급 직급미정, 부서명 배치이전, 급여 -1.00입니다. 사번 -1번, 이름 미상, 직급 직급미정, 부서명 배치이전, 급여 -1.00입니다.
super
- 상위클래스 객체를 의미하는 키워드이다.
- 클래스 생성자의 첫문장에는 super(); 가 먼저 호출된다. 부모 객체의 기본 생성자를 호출한다.
- 이 말은 부모 객체가 먼저 생성된다는 뜻이다.
- super.상속메소드명 : 오버라이딩된 하위 메소드 말고 상위메소드를 호출한다.
- super() : 부모 기본 생성자 호출, 첫 문장에 자동 포함된다.
- super(매개변수) : 부모의 매개변수를 정의한 생성자 호출. 자동 생성이 아니며, 첫문장에 명시하는 문장을 작성해야 한다.
- this : 자신 말고 다른 생성자 호출. 생성자 첫 문장. (??)
- super, this를 1개 생성자에서 내부 동시선언이 불가하다.
상속에서 부모 클래스, 자식 클래스에 같은 이름의 변수가 존재한다면?
- 자식 클래스의 변수를 먼저 사용한다.
- 부모클래스에서 상속받은 변수를 사용하기 위해서는 super.상속변수명 으로 사용해야 한다.
- 만약 상속받으려는 변수가 private라면, 아예 접근이 불가하다. super를 붙일 수 없다.
package chap7; class Employee { String title = "사원"; } class Manager extends Employee{ String title = "관리직"; void test() { String title = "test 메소드 내부"; System.out.println(title); // 지역변수 System.out.println(this.title); // 멤버변수 System.out.println(super.title); // 상속받은 변수 // 만약, 지역변수도 멤버변수도 없다면 title, this.title, super.title 모두 같은 title(employee)을 가리킨다. } } public class ManagerTest { public static void main(String[] args) { Manager m = new Manager(); m.test(); } } ________________________________________________________________ test 메소드 내부 관리직 사원그림으로 보는 super 메모리 구조
class A extends Object{ 자동정의
int i;
A() {
super();자동정의
i = 10;
System.out.println
("A 생성자 호출");
}
}class B extends A {
int j;
B() {
super();자동정의;
j = 20;
System.out.println
("B 생성자 호출");
}
}public class SuperTest {
public static void main(String[] args) {
B b1 = new B();
System.out.println(b1.i);
System.out.println(b1.j);
}
}super();
사용자가 적지 않아도 자동정의된다.
Object() 의 기본 생성자를 호출하는 것이다.super();
사용자가 적지 않아도 자동정의된다.
A() 의 기본 생성자를 호출하는 것이다.
b1은 주소값을 따라가며 j, i, Object에 모두 접근 가능하다.
자식클래스 객체가 생성될 때 : 자식클래스 변수와 메소드 메모리가 할당된다.
부모클래스 객체가 생성될 때 : 부모클래스 변수와 메소드 메모리가 할당된다.
자식클래스 객체 생성시점에 부모클래스 객체가 자동 생성된다.
= 자식 변수 + 메소드 + 부모변수 + 메소드
실제로는 Object --> A --> B 순서로 메모리에 생성된다.
하루 끝!
'스타터스 백엔드 3기' 카테고리의 다른 글
221214 자바 7. 인터페이스, 내부클래스, 익명클래스, (0) 2022.12.14 221210. 자바5 (클래스 형변환) (0) 2022.12.13 유데미 스타터스 취업 부트캠프 3기 - 백엔드 3주차 (0) 2022.12.09 221209. 자바4 (객체지향 프로그래밍, 클래스, 메소드, 변수, static, 오버라이딩, 호출스택) (0) 2022.12.09 221208. 자바 3. 객체 (0) 2022.12.08