[JAVA] 6.2 클래스-2

redcarrot01·2021년 5월 5일
0

JAVA

목록 보기
7/9
post-thumbnail

6.4 메소드

메소드 선언

선언부(리턴 타입, 메소드 이름, 매개 변수 선언)와 실행 블록으로 구성

메소드 이름

  • 소문자로 작성(관례)
  • 혼합된 단어의 경우, 뒤에 오는 단어의 첫글자는 대문자로
메소드 선언 : Calculator.java
public class Calculator {
	//메소드
	void powerOn() {
		System.out.println("전원을 켭니다.");
	}
	// 메소드 선언 -> 리턴 타입, 메소드 이름, 매개변수 , 실행블록
	int plus(int x, int y) {
		int result = x + y;
		return result;
	}
	
	double divide(int x, int y) {
		double result = (double)x / (double)y;
		return result;
	}
}
메소드 호출 : CalculatorExample.java
public class CalculatorExample {
	public static void main(String[] args) {
		Calculator myCalc = new Calculator(); // 객체 생성
		myCalc.powerOn(); // 클래스변수.메소드이름 -> 메소드 호출하면 메소드 블록이 실행됨
		
		int result1 = myCalc.plus(5, 6);
		System.out.println("result1: " + result1);
		
		byte x = 10;
		byte y = 4;
		double result2 = myCalc.divide(x, y); // byte는 int 타입으로 자동변환되어 계산
		System.out.println("result2: " + result2);
        
        divide(10, 20) // 변수 선언안하고 호출 가능
	}
}

매개변수의 개수 모를 경우

매개변수를 배열 타입으로 미리 선언하는 경우와

배열 생성하지 않고 값의 목록만 넘겨주는 방법 2가지가 있다.

Computer.java
public class Computer {
    
    // 배열 타입 미리 선언
	int sum1(int[] values) { 
		int sum = 0;
		for(int i=0; i<values.length; i++) {
			sum += values[i];
		}
		return sum;
	}
	// 값의 목록만 넘겨줌 (... 도 배열 타입)
	int sum2(int ... values) {
		int sum = 0;
		for(int i=0; i<values.length; i++) {
			sum += values[i];
		}
		return sum;
	}
}
ComputerExample.java
public class ComputerExample {
	public static void main(String[] args) {
		Computer myCom = new Computer();
		
        // sum1 호출시 배열을 넘겨줌으로 배열의 항목값 전달됨
		int[] values1 = {1, 2, 3};
		int result1 = myCom.sum1(values1);
		System.out.println("result1: " + result1);
		
		int result2 = myCom.sum1(new int[] {1, 2, 3, 4, 5});
		System.out.println("result2: " + result2);		
		
        // sum2 호출시 자동으로 배열 생성되고 매개값으로 사용됨
		int result3 = myCom.sum2(1, 2, 3);
		System.out.println("result3: " + result3);
		
		int result4 = myCom.sum2(1, 2, 3, 4, 5);
		System.out.println("result4: " + result4);
	}
}

메소드 오버로딩

class 클래스 {

리턴타입 메소드이름  (타입 변수, ...) { }

//(상관x)  (동일)   (매개변수의 타입, 개수, 순서 중 하나가 달라야)
 
리턴타입 메소드이름  (타입 변수, ...) { }

}

6.5 인스턴스 멤버와 정적 멤버

인스턴스 멤버는 객체마다 가지고 있는 멤버,

정적 멤버는 클래스에 위치시키고 객체들이 공유하는 멤버

인스턴스 멤버와 this

인스턴스 필드는 객체마다 따로 존재하고, 인스턴스 메소드는 메소드 영역에 저장되고 공유됨

인스턴스 메소드도 객체에 소속된 멤버인데, 왜 메소드 영역 ??

메소드는 코드 블록이므로 객체마다 동일한 코드 블록을 가지고 있을 필요가 없기 떄문이다

this

객체 내부에서도 사용

this는 주로 생성자와 메소드의 매개변수 이름이 필드와 동일한 경우,

인스턴스 멤버인 필드임을 명시하고자 할 때 사용

public class Car {
	//필드
	String model;
	int speed;
	
	//생성자 
	Car(String model) {
		this.model = model;
	}
	
	//메소드
	void setSpeed(int speed) {
		this.speed = speed;
	}
	
	void run() {
		for(int i=10; i<=50; i+=10) {
			this.setSpeed(i);
			System.out.println(this.model + "가 달립니다.(시속:" + this.speed + "km/h)");
		}
	}	
}

정적 멤버와 static

클래스에 고정된 멤버로서 객체 생성하지 않고 사용할 수 있는 필드와 메소드

객체마다 가지고 있어야 하는 데이터 -> 인스턴스 필드로 선언

공용 데이터 -> 정적 필드로 선언

  • Calculator.java
public class Calculator {
	static double pi = 3.14159;
	
	static int plus(int x, int y) {
		return x + y;
	}
	
	static int minus(int x, int y) {
		return x - y;
	}
}
  • CalculatorExample.java
public class CalculatorExample {
	public static void main(String[] args) {
		double result1 = 10 * 10 * Calculator.pi;
		int result2 = Calculator.plus(10, 5);
		int result3 = Calculator.minus(10, 5);
		
		System.out.println("result1 : " + result1);
		System.out.println("result2 : " + result2);
		System.out.println("result3 : " + result3);
	}
}

정적 메소드 선언 시 주의할 점

정적 메소드 내에서는 this 키워드 사용 불가

정적 메소드 내에서 인스턴스 멤버를 사용하고 싶다면 객체 생성하고, 참조 변수로 접근

public class Car {
	int speed;
	
	void run() {
		System.out.println(speed + "으로 달립니다.");
	}
	
	public static void main(String[] args) {
		Car myCar = new Car(); 
		myCar.speed = 60;
		myCar.run();
	}
}

싱글톤

단 하나의 객체 만드는 것

  1. private 연산자로 외부에서 생성자 호출 막기
  2. 자신의 타입인 정적 필드 하나 선언하고, 자신의 객체 생성해 초기화

외부에서 객체를 얻는 방법은 getInstance() 메소드 호출

  • 싱글톤 만들기
public class 클래스 {
	// 정적 필드
	private static 클래스 singleton = new 클래스();
	
	// 생성자
	private 클래스() {}
	
	// 정적 메소드
	static 클래스 getInstace() {
		return singleton;
	}
}
  • 싱글톤
public class Singleton {
	private static Singleton singleton = new Singleton();
	
	private Singleton() {}
	
	static Singleton getInstance() {
		return singleton;
	}
}
  • 싱글톤 객체
public class SingletonExample {
	public static void main(String[] args) {
		/*
		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 객체 입니다.");
		}
	}
}

final 필드와 상수

final 필드는 초기값이 최종값

초기값 주는 방법

  1. 필드 선언시
  2. 생성자에게 주기
  • Person.java
public class Person {
	final String nation = "Korea";
	final String ssn;
	String name;
	
	public Person(String ssn, String name) {
		this.ssn = ssn;
		this.name = name;
	}
}
  • PersonExample.java
public class PersonExample {
	public static void main(String[] args) {
		Person p1 = new Person("123456-1234567", "홍길동");
		
		System.out.println(p1.nation);
		System.out.println(p1.ssn);
		System.out.println(p1.name);
		
		//p1.nation = "usa";
		//p1.ssn = "654321-7654321";
		p1.name = "홍삼원";;
	}
} 

> Korea
> 123456-1234567
> 홍삼원

상수

static이면서 final이여야 함

final 필드는 상수 아님 -> 객체마다 저장되고, 생성자의 매개값 통해 여러 가지 값 가능

상수 = 불변의 값 = 공용성 있고 여러가지 값을 초기화 불가

상수 이름은 모두 대문자로 작성

static final 타입 상수 = 초기값;
static final double EARTH_RADIUS = 6400;

6.6 패키지와 접근 제한자

패키지 선언

패키지는 모두 소문자로 작성

package 상위패키지.하위패키지;

import 문

import 상위패키지.하위패키지.클래스이름;
import 상위패키지.하위패키지.*;

접근 제한자

접근 : 클래스 및 인터페이스, 멤버의 접근

  • 접근 제한자 종류

| public | 외부 클래스가 자유롭게 사용 가능 |
| --------- | -------------------------------------- |
| protected | 같은 패키지, 자식 클래스에서 사용 가능 |
| private | 외부 사용 불가 |
| default | 같은 패키지 소속에서만 사용 가능 |

class 접근 제한

public : 라이브러리 클래스 개발시 반드시 public

package sec06.exam03.package1;

class A {  // default로 접근 제한

}
package sec06.exam03.package1;

public class B {
	A a;  // A클래스 접근 가능, 같은 패키지 내에 있음
}

생성자 접근 제한

package sec06.exam04.package1;

public class A {
	//필드
	A a1 = new A(true);
	A a2 = new A(1);
	A a3 = new A("문자열");

	//생성자	
	public A(boolean b) {}
	A(int b) {}
	private A(String s) {} 
}
package sec06.exam04.package1;

public class B {
	//필드
	A a1 = new A(true);
	A a2 = new A(1);
	//A a3 = new A("문자열");
}
package sec06.exam04.package2; // 패키지 다름

import sec06.exam04.package1.A;

public class C {
	// 필드
	A a1 = new A(true);
	// A a2 = new A(1);
	// A a3 = new A("문자열");
}

필드와 메소드 접근 제한

package sec06.exam05.package1;

public class A {
	//필드
	public int field1;
	int field2;
	private int field3;
	
	//생성자
	public A() { // 클래스 내부 경우 영향 없음
		field1 = 1;   
		field2 = 1;   
		field3 = 1;   
		
		method1();   
		method2();   
		method3();   
	}
	
	//메소드
	public void method1() {}
	void method2() {}
	private void method3() {}
}
package sec06.exam05.package2; // 패키지 다름

import sec06.exam05.package1.A;

public class C {
	public C() {
		A a = new A();
		a.field1 = 1;   
		//a.field2 = 1;   
		//a.field3 = 1;   
		
		a.method1();   
		//a.method2();   
		//a.method3();   
	}
}

Getter Setter 메소드

객체 지향에서는 객체의 필드를 외부에서 접근하는 것을 막는다.

메소드를 통해서 필드를 변경하는 방법이 있다.

setter 메소드 : 메소드는 매개값 통해 객체의 필드로 저장 가능
getter 메소드 : 메소드로 필드값 가공한 후 외부로 전달(읽을때 사용)

클래스 선언시, 필드를 private 선언하고 setter getter 메소드 사용해서 안전하게 필드값 변경하는 것이 좋다

package sec06.exam06;

public class Car {
	//필드 private로 접근 제한
	private int speed;
	private boolean stop;
	
	//생성자
	
	//메소드
	public int getSpeed() {
		return speed;
	}
	public void setSpeed(int speed) {
		if(speed < 0) { 
			this.speed = 0;
			return;
		} else {
			this.speed = speed;
		}
	}

	public boolean isStop() {
		return stop;
	}
	public void setStop(boolean stop) {
		this.stop = stop;
		this.speed = 0;
	}
}
package sec06.exam06;

public class CarExample {
	public static void main(String[] args) {
		Car myCar = new Car();
		
		//잘못된 속도 변경
		myCar.setSpeed(-50); 
		
		System.out.println("현재 속도: " + myCar.getSpeed()); // 0
		
		//올바른 속도 변경
		myCar.setSpeed(60); // 60
		
		//멈춤
		if(!myCar.isStop()) { // 리턴값이 false라면 메소드 호출해서 stop = true , speed = 0
			myCar.setStop(true);
		}
		
		System.out.println("현재 속도: " + myCar.getSpeed()); // 0
	}
}

관심 있을 만한 포스트

0개의 댓글