[Java 11-2] final 제한자 - 필드, 메소드, 클래스에 설정 가능한 제한자

임승현·2022년 10월 16일

Java

목록 보기
36/126

🐧static 제한자 - 필드, 메소드, 클래스(내부클래스)에 설정 가능한 제한자

→ 객체에 상관 없이 클래스로 접근하기 위해 사용하는 제한자

🐧final 제한자 - 필드, 메소드, 클래스에 설정 가능한 제한자

1.final 필드 - final 제한자를 사용하여 선언한 필드
형식) 접근제한자 final 자료형 필드명=값;
ex) Math 클래스 >> public static final double PI : 원주율을 제공하기 위한 상수
→ 필드에 저장된 값 변경 불가능 - 필드값을 변경할 경우 에러 발생
→ 필드 선언시 반드시 초기값이 저장되도록 설정
2.final 메소드 - final 제한자를 사용하여 선언한 메소드
형식) 접근제한자 final 반환형 메소드명(자료형 매개변수명,...) { 명령; ... }
→ Object 클래스 >> public final void notify()
→ 자식클래스에서 절대로 오버라이드 선언하지 못하도록 설정하는 메소드
3.final 클래스 - final 제한자를 사용하여 선언한 클래스
형식) public final class 클래스명 { }
→ ex) public final class System extends Object 클래스
→ 다른 클래스에서 상속 받을 수 없는 클래스

package inheritance;

//사원정보(사원번호,사원이름)를 저장하기 위한 클래스
// => 모든 사원 관련 클래스가 상속받아야 되는 부모클래스
// => 객체 생성이 목적이 아닌 상속이 목적인 클래스로 작성 - 추상클래스로 선언하는 것을 권장
//추상클래스(Abstract Class) : abstract 제한자를 사용하여 선언된 클래스 
// => 객체 생성 불가능 - 상속 전용 클래스
// => 형식) public abstract class 클래스명 {}
//abstract 제한자 - 클래스, 메소드에 설정 가능한 제한자
public abstract class Employee {
	private int empNo;
	private String empName;
	
	//상수필드(Constant Field) : 프로그램에서 값(리터럴) 대신 사용하기 위해 
    의미있는 단어로 제공되는 필드값
	//형식) public static final 자료형 상수명=값;
	// => 상수명은 대문자로 작성하며 스네이크 표기법을 이용하여 작성하는 것을 권장
	public static final double INCENTIVE_RATE=1.5;
	
	public Employee() {
		// TODO Auto-generated constructor stub
	}

	public Employee(int empNo, String empName) {
		super();
		this.empNo = empNo;
		this.empName = empName;
	}

	public int getEmpNo() {
		return empNo;
	}

	public void setEmpNo(int empNo) {
		this.empNo = empNo;
	}

	public String getEmpName() {
		return empName;
	}

	public void setEmpName(String empName) {
		this.empName = empName;
	}
	
	/*
	//급여를 계산하여 반환하는 메소드
	//자식클래스에서 부모클래스의 메소드를 오버라이드 선언하지 않아도 에러 미발생
	// => 자식클래스에서 메소드를 오버라이드 선언하지 않은 경우 부모클래스의 
    메소드 호출 - 비정상적인 결과 발생
	public int computePay() {
		return 0;
	}
	*/
	
	//자식클래스에서 부모클래스의 메소드를 무조건 오버라이드 선언되도록 설정하기
    위해 추상메소드로 선언
	//추상메소드(Abstract Method) : abstract 제한자를 사용하여 선언된 메소드
	// => 메소드의 머릿부만 작성하고 몸체부는 작성하지 않는 미완성된 메소드
	//형식) 접근제한자 abstract 반환형 메소드명(자료형 매개변수명,...);
	// => 추상메소드가 선언된 클래스는 무조건 추상클래스로 선언
	public abstract int computePay();
	
	//인센티브를 계산하여 반환하는 메소드
	// => 모든 사원에게 급여의 150%를 인센티브로 제공되도록 계산
	//자식클래스에서 메소드를 오버라이드 선언하면 비정상적인 결과값 반환
	// => 자식클래스에서 메소드를 오버라이드 선언하지 못하도록 final 메소드로 선언
	public final int computeIncentive() {
		//추상메소드를 호출한 경우 묵시적 객체 형변환에 의해 자식클래스의
        메소드 호출
		//return (int)(computePay()*1.5);
		return (int)(computePay()*INCENTIVE_RATE);
	}
}

============================================================

package inheritance;

//사원 급여 관리 프로그램
public class EmployeeApp {
	public static void main(String[] args) {
		//추상클래스로 객체를 생성할 경우 에러 발생
		//Employee employee=new Employee();
		
		//추상클래스(부모클래스)로 참조변수를 생성하여 모든 자식클래스의 객체 저장 가능
		//Employee employee1=new EmployeeRegular();
		//Employee employee2=new EmployeeTime();
		//Employee employee3=new EmployeeContract();
		
		//모든 사원정보를 저장할 수 있는 참조요소가 존재하는 배열 생성
		Employee[] empArray=new Employee[5];
		
		empArray[0]=new EmployeeRegular(1000, "홍길동", 96000000);
		empArray[1]=new EmployeeTime(2000, "임꺽정", 50000, 150);
		empArray[2]=new EmployeeContract(3000, "전우치", 7000000);
		empArray[3]=new EmployeeTime(4000, "일지매", 20000, 100);
		empArray[4]=new EmployeeRegular(5000, "장길산", 60000000);
		
		for(Employee employee:empArray) {
			System.out.println("사원번호 = "+employee.getEmpNo());			
			System.out.println("사원이름 = "+employee.getEmpName());
			
			/*
			//사원의 급여를 반환받아 출력
			// => 참조변수는 부모클래스의 객체만 참조 가능하므로 자식클래스의 
            메소드 호출 불가능
			// => 명시적 객체 형변환을 사용하여 참조변수로 자식클래스의 객체를 
            참조하여 메소드 호출 가능
			// => instanceof 연산자를 사용하여 자식클래스를 구분하여 객체 형변환 - 
            ClassCastException 발생 방지
			if(employee instanceof EmployeeRegular) {
				System.out.println("급여 = "+
                ((EmployeeRegular)employee).computeRegular());
			} else if(employee instanceof EmployeeTime) {
				System.out.println("급여 = "+
                ((EmployeeTime)employee).computeTime());
			} else if(employee instanceof EmployeeContract) {
				System.out.println("급여 = "+
                ((EmployeeContract)employee).computeContract());
			}
			*/
			
			//자식클래스에서 부모클래스의 메소드를 오버라이드 선언하면 묵시적 객체 
            형변환에 의해 자동으로 참조변수가 자식클래스로 형변환되어 자식클래스의
            메소드 호출 가능
			System.out.println("급여 = "+employee.computePay());
			
			//사원의 인센티브를 반환받아 출력
			System.out.println("인센티브 = "+employee.computeIncentive());
			System.out.println("==================================================");			
		}
	}
}
package inheritance;

//정규직 사원정보(사원번호,사원이름,연봉)를 저장하기 위한 클래스
// => Employee 클래스를 상속받아 작성
public class EmployeeRegular extends Employee {
	private int annualSalary;
	
	public EmployeeRegular() {
		// TODO Auto-generated constructor stub
	}

	public EmployeeRegular(int empNo, String empName, int annualSalary) {
		super(empNo, empName);
		this.annualSalary = annualSalary;
	}

	public int getAnnualSalary() {
		return annualSalary;
	}

	public void setAnnualSalary(int annualSalary) {
		this.annualSalary = annualSalary;
	}
	
	//급여를 계산하여 반환하는 메소드
	public int computeRegular() {
		return annualSalary/12;
	}
	
	//추상메소드가 선언된 추상클래스를 상속받은 자식클래스에서는 반드시 부모클래스의 모든
	//추상메소드를 무조건 오버라이드 선언 - 오버라이드 선언하지 않은 경우 에러 발생
	// => 추상메소드를 오버라이드 선언하지 않은 자식클래스는 추상클래스로 설정 가능 - 비권장
	@Override
	public int computePay() {
		return annualSalary/12;
	}
	
	/*
	//부모클래스의 final 메소드를 자식클래스에서 오버라이드 선언한 경우 에러 발생
	@Override
	public int computeIncentive() {
		return 100000000;
	}
	*/
}
package inheritance;

//시간제 사원정보(사원번호,사원이름,시급,근무시간)를 저장하기 위한 클래스
// => Employee 클래스를 상속받아 작성
public class EmployeeTime extends Employee {
	private int moneyPerHour;
	private int workedHour;
	
	public EmployeeTime() {
		// TODO Auto-generated constructor stub
	}

	public EmployeeTime(int empNo, String empName, int moneyPerHour, int workedHour) {
		super(empNo, empName);
		this.moneyPerHour = moneyPerHour;
		this.workedHour = workedHour;
	}

	public int getMoneyPerHour() {
		return moneyPerHour;
	}

	public void setMoneyPerHour(int moneyPerHour) {
		this.moneyPerHour = moneyPerHour;
	}

	public int getWorkedHour() {
		return workedHour;
	}

	public void setWorkedHour(int workedHour) {
		this.workedHour = workedHour;
	}
	
	//급여를 계산하여 반환하는 메소드
	public int computeTime() {
		return moneyPerHour*workedHour;
	}
	
	@Override
	public int computePay() {
		return moneyPerHour*workedHour;
	}
}
package inheritance;

//계약직 사원정보(사원번호,사원이름,계약급여)를 저장하기 위한 클래스
// => Employee 클래스를 상속받아 작성
public class EmployeeContract extends Employee {
	private int contractPay;
	
	public EmployeeContract() {
		// TODO Auto-generated constructor stub
	}

	public EmployeeContract(int empNo, String empName, int contractPay) {
		super(empNo, empName);
		this.contractPay = contractPay;
	}

	public int getContractPay() {
		return contractPay;
	}

	public void setContractPay(int contractPay) {
		this.contractPay = contractPay;
	}
	
	//급여를 계산하여 반환하는 메소드
	public int computeContract() {
		return contractPay;
	}
	
	@Override
	public int computePay() {
		return contractPay;
	}
}

0개의 댓글