클래스, 필드, 생성자, 오버로딩, this()

oYJo·2024년 12월 17일

Java

목록 보기
16/25

클래스(Class)

  • 클래스 선언

  • 클래스 예시

  • 클래스 접근제한자

[] : 생략가능
() : 무조건 생략
public : import 가능, +
(default) : 같은 패키지 안에서만, ~

cls
class ClsService

package edu.kh.oop.cls.model.service;

import edu.kh.oop.cls.model.vo.Student;
import edu.kh.oop.cls.model.vo.User;
// import edu.kh.oop.cls.model.vo.TestVO;
// The type edu.kh.oop.cls.model.vo.TestVO is not visible

public class ClsService {
	public void ex1() {
		
		// 클래스 접근 제한자 확인하기
		
		Student std = new Student();
		// public class인 Student는 import 가능
		
		// TestVO test = new TestVO();
		// (default) class인 TestVO는 import 불가 (다른 패키지여서)
		
		System.out.println("다른 패키지");
		System.out.println(std.v1);
		// v1은 다른 패키지에서도 접근 가능한 public
		
		// System.out.println(std.v2);
		// System.out.println(std.v3);
		// System.out.println(std.v4);
		
	}

	public void ex2() {
		// static 필드 확인 예제
		
		// 학생 객체 2개 생성
		
		Student std1 = new Student();
		Student std2 = new Student();
		
		// 학생 객체에 name 세팅
		std1.setName("김철수");
		std2.setName("이영희");
		
		// 정보 출력
		System.out.println(std1.schoolName); // public이기 때문에 직접 접근 가능
		System.out.println(std1.getName());
		System.out.println(std2.schoolName); // public이기 때문에 직접 접근 가능
		System.out.println(std2.getName());
	
		// schoolName 변경
		std1.schoolName = "KH정보교육원";
		System.out.println("변경 후 std1 : " + std1.schoolName); // KH정보교육원
		System.out.println("std2 : " + std2.schoolName); // KH고등학교이 아니라, KH정보교육원으로 나옴
		// std1만 변경한다고 생각했는데, 그게 아니라 std1을 이용해서 변경된거임 즉, std2도 이름 변경된 걸로 나옴
		
		
		// std3 생성
		Student std3 = new Student();
		
		System.out.println("std3 : " + std3.schoolName);
		
		// schoolName에 노란줄이 뜨는 이유(The static field Student.schoolName should be accessed in a static way) 
		// -> 제대로 작성하지 않아서
		
		// *** static이 붙은 필드(변수)는 클래스명.변수명으로 사용함 ***
		Student.schoolName = "KH";
		System.out.println("Student.schhoName : " + Student.schoolName);
		
		/* static
		 * 
		 * 1) 공유 메모리 영역 (또는 정적 메모리 영역)
		 * 
		 * why? 프로그램 시작 시 static이 붙은 코드들이 모두
		 * static 영역에 생성됙,
		 * 프로그램이 종료될 때까지 사라지지 않음(정적)
		 * 그리고 static 영역에 생성된 변수는 어디서든지 공유할 수 있다.(공유)
		 * 
		 * 2) 사용 방법 : 클래스명.변수명
		 * 
		 * 
		 * */
		
		
	
	}

	public void ex3() {
		// 생성자 확인 테스트
		
		// Student 객체를 기본 생성자를 이용해 생성하고 이를 참조하는 참조변수 s1에 대입
		Student s1 = new Student();
					// 기본 생성자
						// new Student : Student 클래스를 보고, Student 객체를 만들겠다
						// Student(); : Student 객체가 생성된 후 기본 생성자에 작성된 코드를 수행
					// ctrl + 마우스커서 : 기본 생성자 확인가능
		
		// User 기본 생성자를 이용해서 객체 생성
		User u1 = new User();
		
		// User 객체 필드 초기화 확인
		System.out.println(u1.getUserId());
		System.out.println(u1.getUserPw());
		System.out.println(u1.getUserName());
		System.out.println(u1.getUserAge());
		System.out.println(u1.getUserGender());
		
		// User 기본 생성자를 이용해서 객체 생성
		User u2 = new User();
		
		// User 객체 필드 초기화 확인
		System.out.println(u2.getUserId());
		System.out.println(u2.getUserPw());
		System.out.println(u2.getUserName());
		System.out.println(u2.getUserAge());
		System.out.println(u2.getUserGender());
		
		
		// 문제점 : u1이 참조하고 있는 User 객체와
		// 	      u2가 참조하고 있는 User 객체의 필드 값이 모두 동일함
		// 		  Why? 같은 기본 생성자를 이용해서 User 객체를 생성했기 때문에
		
		System.out.println("------------------------------------");
		
		// 해결 방법 1 : setter를 이용해서 새로운 값을 대입
		u2.setUserId("user02");
		u2.setUserPw("pass02");
		u2.setUserName("이일동");
		u2.setUserAge(25);
		u2.setUserGender('여');
		
		// User 객체 필드 초기화 확인
		System.out.println(u2.getUserId());
		System.out.println(u2.getUserPw());
		System.out.println(u2.getUserName());
		System.out.println(u2.getUserAge());
		System.out.println(u2.getUserGender());
	
		// 해결방법 2 : 매개변수 생성자를 이용해서
		//			  객체가 생성될 때 부터 다른 값으로 필드를 초기화
		
		User u3 = new User("test03", "pass03"); // 매개변수 생성자
						// 생성자 수행 시 전달할 값을 작성 (순서 꼭 지켜야함!!)
		
		System.out.println(u3.getUserId()); // null 나옴 -> 필드로는 안 간 것
		System.out.println(u3.getUserPw()); // null 나옴 -> 필드로는 안 간 것
	}
	
	public void ex4() {
		// 매개변수 생성자 예제
		
		User u1 = new User(); // 기본 생성자
		User u2 = new User("user02", "pass02"); // 매개변수 2개 생성자
		User u3 = new User("user03", "pass03", "수지", 28, '여'); // 매개변수 5개 생성자
		User u4 = new User("user04", "pass04", "공유", 35, '남'); // 매개변수 5개 생성자
		User u5 = new User("user05", "pass05", "데프콘", 22, '남'); // 매개변수 5개 생성자
		
		System.out.printf("u1 : %s / %s / %s / %d / %c\n", 
				u1.getUserId(), u1.getUserPw(), u1.getUserName(), u1.getUserAge(), u1.getUserGender());
		
		System.out.printf("u2 : %s / %s / %s / %d / %c\n", 
				u2.getUserId(), u2.getUserPw(), u2.getUserName(), u2.getUserAge(), u2.getUserGender());
		
		System.out.printf("u3 : %s / %s / %s / %d / %c\n", 
				u3.getUserId(), u3.getUserPw(), u3.getUserName(), u3.getUserAge(), u3.getUserGender());
		
		System.out.printf("u4 : %s / %s / %s / %d / %c\n", 
				u4.getUserId(), u4.getUserPw(), u4.getUserName(), u4.getUserAge(), u4.getUserGender());
		
		System.out.printf("u5 : %s / %s / %s / %d / %c\n", 
				u5.getUserId(), u5.getUserPw(), u5.getUserName(), u5.getUserAge(), u5.getUserGender());
		
	}	
}

class Student

package edu.kh.oop.cls.model.vo;

public class Student { // 클래스 선언부

	// [접근제한자] [예약어] class 클래스명

	// 접근 제한자 public : 같은 프로젝트 내에 어떤 클래스에서든 import 할 수 있음

	// 1. 필드(field) | 객체의 속성을 작성하는 클래스 내부 영역

	// == 멤버 변수 : 메소드 밖에 작성된 변수

	// 인스턴스 변수 : 필드에 작성되는 일반 변수

	// 클래스 변수(== static 변수) : 필드에 static 예약어가 작성된 변수
	// why? 같은 클래스로 만들어진 객체가 값을 공유할 수 있기 때문에


	/* 
	 * [접근제한자]		      [예약어]	        자료형 			변수명 [= 초기값];
	 * 
	 * + public		  	  final 	 	   기본자료형
	 * # protected	     static 			 배열
	 * ~ (default)	  final static		   클래스명
	 * - private	  static final 		   (참조형)
	 * 
	 * 필드의 접근 제한자의 뜻 : 직접 접근 가능한 범위를 나타냄
	 * 
	 */

	public int v1 = 10;
	protected int v2 = 20;
	int v3 = 30;
	private int v4 = 40;

	// 접근 제한자 예제
	public void ex() {
		System.out.println("같은 클래스 내부");
		System.out.println(v1); // 10
		System.out.println(v2); // 20
		System.out.println(v3); // 30
		System.out.println(v4); // 40

	}

	// ---------------------------------------------

	// static 예약어
	public static String schoolName = "KH고등학교"; 
	// static 변수
	private String name; // 캡슐화 원칙 때문에 private -> 간접 접근 방법 필요
	// static 없음 = 인스턴스 변수 = 일반적인 변수

	{ // 초기화 블록 : 객체 생성 시 필드 값 초기화
		name = "김길동";
	}


	// getter / setter
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}


	// 2. 생성자(constructor) | 
	/* - new 연산자를 통해서 객체를 생성할 때
	 * 생성된 객체의 필드 값 초기화 + 지정된 기능을 수행하는 역할
	 * 
	 * - 생성자 작성 규칙
	 * 1) 생성자의 이름은 반드시 클래스명과 같아야 한다.
	 * 2) 반환형이 존재하지 않는다.
	 * 
	 * - 생성자 종류
	 * 1) 기본 생성자
	 * 2) 매개변수 생성자
	 * 
	 */
	// 기본 생성자
	// [접근제한자] 클래스명() { 코드 }
	public Student() {
		// 객체가 생성될 때 수행할 코드
		System.out.println("기본 생성자에 의해서 Student 객체가 생성되었습니다");

	}

	//public void ex1() {
	// void가 반환형 (생성자는 존재하지 않음)


}



// 3. 메소드(method)

class TestVO

package edu.kh.oop.cls.model.vo;

class TestVO {

	// 접근 제한자 (default) : 같은 패키지 내에서만 import가 가능함을 나타냄
	
	// Student와 같은 패키지
	// -> public, protected, (default) 3개만 접근 가능
	
	public void ex() {
		System.out.println("같은 패키지");
		
		Student std = new Student(); // 학생 객체 생성
		
		System.out.println(std.v1);
		System.out.println(std.v2);
		System.out.println(std.v3);
		// System.out.println(std.v4); // The field Student.v4 is not visible
		// v4는 같은 패키지라도 private이기 때문
		// 다른 클래스에서 직접 접근 불가
		
	}
}

class User

package edu.kh.oop.cls.model.vo;

public class User {
	// 속성(== 필드)

	// 아이디, 비밀번호, 이름, 나이, 성별 (추상화 진행)
	private String userId;
	private String userPw;
	private String userName;
	private int userAge;
	private char userGender;

	// 기능(== 생성자 + 메소드)

	// 생성자 : new연산자를 통해서 객체가 생성될 때
	//		  생성된 객체의 필드 값 초기화 + 기능 수행 역할
	
	// 기본 생성자
	public User() {
		// 기능
		System.out.println("기본 생성자로 User 객체 생성");
		
		// 필드 초기화
		userId = "user01";
		userPw = "pass01";
		userName = "홍길동";
		userAge = 20;
		userGender = '남';
				
	}
	
	// 매개변수 생성자
	// ** 사용되는 기술, 변수 : 매개변수, 오버로딩(Overloading), this
	
	// ** 매개변수 : 생성자나 메소드 호출 시 ()안에 작성되어
	// 			   전달되어지는 값을 저장하는 변수
	// -> 전달 받은 값을 저장하고 있는 매개체(지니고 있는) 역할의 변수
	public User(String userId, String userPw) {
				  // 매개변수      // 매개변수
		System.out.println("매개변수 생성자를 이용해서 User 객체 생성");
		System.out.println(userId + " / "+ userPw);
		
		
		// 전달 받은 값을 필드에 초기화(this 참조변수)
		
		// *** this 참조 변수 ***
		// - 객체가 자기 자신을 참조할 수 있도록 하는 변수
		// - 모든 객체 내부에 숨겨져 있다.
		// 왜 사용하는가?
		// -> 필드명과 매개변수명이 같을 경우
		//	  이를 구분하기 위해서 주로 사용
		
		this.userId = userId;
		// 필드 = 매개변수
		// 전달받은 userId를 필드의 userId로 저장하겠다
		
		this.userPw = userPw;
		
	}

	// 필드를 전부 초기화 하는 목적의 매개변수 생성자
	public User(String userId, String userPw, String userName, 
			int userAge, char userGender) {

		// 매개변수로 전달 받은 값으로 필드 초기화
		// this.userId = userId; // 현재 객체가 가지고 있는 필드 userId에
							  // 매개변수 userId 값을 대입
		// this.userPw = userPw;
		
		// User(userId, userPw); // 오류발생 : The method User(String, String) is undefined for the type User
		this(userId, userPw); // this() 생성자
		// - 같은 클래스의 다른 생성자를 호출할 때 사용
		// - 생성자 내에서 반드시 첫 번째 줄에 작성 되어야 한다!!
		
		// 왜 사용? 1) 중복 코드 제거, 2) 코드 길이 감소, 3) 재사용성 증가
		// (가독성이 어려운 경우가 생길 수 있어서 많이 사용되진 않음)
		
		this.userName = userName;
		this.userAge = userAge;
		this.userGender = userGender;

	}
	
	// 자바는 기본적으로 필드명, 생성자명, 메소드명, 변수명의
	// 중복을 허용하지 않음
	
	/*
	private String userId; // 오류 발생 : Duplicate field User.userId
	public User() {} // 오류 발생 : Duplicate method User() in type User
	public String getUserId() {} // 오류 발생 : This method must return a result of type String
	public void ex() {
		int num = 10;
		int num = 20; // 오류 발생 : Duplicate local variable num
	}
	*/
	
	// 위에서 본 것처럼 자바는 중복되면 오류가 발생하는데, public User 중복 안 됨
	// -> 오버로딩 특징 덕분에 오류 나지 않음
	
	// *** 오버로딩(Over Loading) ***
	// - 클래스 내에 동일한 이름의 메소드(생성자도 포함)를
	// 	 여러 개 작성하는 기법
	
	// --> 하나의 이름으로 여러 기능을 수행할 수 있게 하는 것
	
	// [오버로딩 조건]
	// 1) 메소드(생성자 포함)의 이름이 동일
	// 2) 매개변수의 개수, 타입, 순서 중 1개라도 달라야 함!!
	
	// public User() {} : // 오류발생 : 매개변수가 하나도 없음(기본 생성자)
						  // 위에 있음 = 기본 생성자가 이미 작성되어 있어서 중복
	
	public User(String userId) {} // 매개변수의 개수가 같은 생성자 없음
								  // -> 오버로딩 성립
	
	public User(int userAge) {} // 매개변수의 개수는 같지만 타입이 다름
								  // -> 오버로딩 성립
	public User(int userAge, String userId) {}
	// 매개변수의 개수는 같지만 타입이 다름 -> 오버로딩 성립
	
	public User(String userId, int userAge) {}
	// 매개변수의 개수, 타입은 같지만 순서가 다름 -> 오버로딩 성립
	
	public User(String userId, String userPw, String userName) {}
	
	// public User(String userName, String userId, String userPw) {} 
	// 오류 발생 : 115과 변수명 순서는 다른데 왜 오류? 
	// 			매개변수의 개수, 타입, 순서가 모두 같아서 오버로딩 불가
	// 			-> 변수명은 신경쓰지 않는다!!!
	
	
	
	// 캡슐화로 인한 간접 접근 기능(getter / setter
	// private으로 만드니깐 나도 접근못해서 비밀통로 만들기
	public String getUserId() { // userId의 getter
		return userId;
	}
	public void setUserId(String userId) { // userId의 setter
		this.userId = userId;
	}
	public String getUserPw() {
		return userPw;
	}
	public void setUserPw(String userPw) {
		this.userPw = userPw;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public int getUserAge() {
		return userAge;
	}
	public void setUserAge(int userAge) {
		this.userAge = userAge;
	}
	public char getUserGender() {
		return userGender;
	}
	public void setUserGender(char userGender) {
		this.userGender = userGender;
	}
	
}

class ClsRun

package edu.kh.oop.cls.run;

import edu.kh.oop.cls.model.service.ClsService;

public class ClsRun {
	public static void main(String[] args) {
		ClsService service = new ClsService();
		
//		service.ex2(); // static 확인 예제 호출
//		service.ex3();
		service.ex4();

	}
}

필드(Field)

  • 필드 표현식
  • 필드 예시
  • 필드 접근제한자

  • 필드 예약어 - static
    같은 타입의 여러 객체가 공유할 목적의 필드에 사용하며, 프로그램 start시에 정적 메모리(static) 영역에 자동 할당되는 멤버에 적용

공유 메모리 영역 = 정적 메모리 영역
vs Heap : 동적메모리(new 연산자로 만들 때마다 만들어지기 때문)

  • 필드 예약어 - final
    하나의 값만 계속 저장해야 하는 변수에 사용하는 예약어

final 키워드가 붙은 필드명은 모두 대문자로 표기

필드 - 클래스 초기화 블럭

  • 인스턴스 블럭 ( { } ) - 인스턴스 변수를 초기화 시키는 블럭으로 객체 생성시 마다 초기화
  • static(클래스) 블럭 ( static{ } ) - static 필드를 초기화 시키는 블럭으로 프로그램 시작 시 한 번만 초기화
  • 클래스 초기화 블럭 표현식

필드 - 초기화 순서

  • 클래스 변수

static(클래스) 블럭 (static { } ) : static 필드를 초기화 시키는 블럭으로 프로그램 시작 시 한번만 초기화

  • 인스턴스 변수

인스턴스 블럭( { } ) : 인스턴스 변수를 초기화 시키는 블럭으로 객체 생성시 마다 초기화

생성자(Constructor)

  • 생성자?
    객체가 new 연산자를 통해 Heap 메모리 영역에 할당될 때
    객체 안에서 만들어지는 필드 초기화 + 생성 시 필요한 기능 수행
    생성자는 일종의 메소드로 전달된 초기값을 받아서 객체의 필드에 기록
  • 생성자 규칙
    생성자의 선언은 메소드 선언과 유사하나 반환 값이 없으며 생성자명을 클래스명과 똑같이 지정해주어야 함

  • 생성자 표현식

  • 기본 생성자
    작성하지 않은 경우, 클래스 사용 시 컴파일러가 자동으로 기본 생성자 생성

  • 매개변수 생성자

  1. 객체 생성 시 전달받은 값으로 객체를 초기화 하기 위해 사용
  2. 매개변수 생성자 작성 시 컴파일러가 기본 생성자를 자동으로 생성해주지 않음
  3. 상속에서 사용 시 반드시 기본 생성자를 작성
  4. 오버로딩을 이용하여 작성

❗️오버로딩

  • 오버로딩?
    한 클래스 내에 동일한 이름의 메소드를 여러 개 작성하는 기법

  • 오버로딩 조건

  1. 같은 메소드 이름
  2. 다른 매개변수의 개수 또는 다른 매개변수 타입, 순서

한 이름 당 기능이 여러 개 적재
(Over : 초과, 넘어서다 + Loading : 적재하다(불러오기라고 하지 않는다))
즉, 이름은 1개지만 기능은 여러 개 할 수 있음

this

  • this?
    모든 인스턴스의 메소드에 숨겨진 채 존재하는 레퍼런스로, 할당된 객체를 가리킴
    함수 실행 시 전달되는 객체의 주소를 자동으로 받음

this : 모든 객체에 숨겨져 있는 참조 변수, 자기 자신을 부르는 것

  • this 사용 예시

위와 같이 매개변수를 가지는 생성자에서 매개변수 명이 필드명과 같은 경우
매개변수의 변수명이 우선이므로 this 객체를 이용하여 대입되는 변수가 필드라는 것을 구분해줌

this()

  • this()?
    생성자, 같은 클래스의 다른 생성자를 호출할 때 사용, 반드시 첫 번째 줄에 선언해야 함

this() : 생성자, 같은 클래스의 다른 생성자를 호출할 때 사용, 반드시 1번째 줄에 선언해야 함

  • this() 사용 예시
profile
Hello! My Name is oYJo

0개의 댓글