객체의 동작을 실행 블록으로 정의하는 것
리턴타입 : 메소드 실행 후 호출한 곳으로 전달하는 결과값의 타입
메소드명 : 메소드명은 첫 문자를 소문자로 시작하고, 캐멀 스타일로 작성함
매개변수 : 메소드를 호출할 때 전달한 매개값을 받기 위해 사용
실행블록 : 메소드 호출 시 실행되는 부분
함수의 값(return)을 받지 않을 때에는 void 사용
리턴 타입 함수를 사용할 경우 리턴값을 해당 타입에 맞게 지정하기
만약 메소드 안에 if문을 사용할 경우 반드시 else문도 같이 만들어서 if문과 else문 모두 리턴값을 받아야함
형태
// 메소드 선언 클래스 (클래스 내부)
// 리턴값이 없는 메소드
// 인자값이 없는 기본메소드
void 함수명(){
실행문
}
// 인자값이 두 개인 일반메소드
void 함수명2(타입 값1, 타입 값2) {
실행문
}
// 리턴 값을 받아야 하는 메소드 (기본형 타입 메소드)
// 인자값이 없는 기본메소드
public 타입 함수명3(){
실행문
return 변수명;
}
// 인자값이 두 개인 일반메소드
public 타입 함수명4(타입 값1, 타입 값2){
실행문
return 변수명;
}
// 메소드 호출 클래스 (외부 클래스)
// 객체 생성
필드클래스명 참조변수 = new 필드클래스명();
// 메소드 호출
참조변수.함수명();
참조변수.함수명2(값1, 값2);
// 인자가 2개이기 때문에 매개값을 2개 넣어주기
참조변수.함수명3();
참조변수.함수명4(값1, 값2);
// 인자가 2개이기 때문에 매개값을 2개 넣어주기
package ch06.sec08.exam01;
public class Calculator {
boolean powered;
//전원을 켰을 때!
void powerOn() {
powered = true;
System.out.println("전원 on");
}
// 전원을 껐을 때!
void powerOff() {
powered = false;
System.out.println("전원 off");
}
// void 함수 특징 : 리턴 값을 받지 않음
// 더하기
public int plus(int a, int b) {
// 정수 형태의 두개의 인자를 입력해줘야함
if(this.powered) {
// powerOn()이 실행되면
return a+b;
// a+b 값을 리턴함
}
else {
// powerOff()가 실행되면
return 0;
}
}
// 빼기
public int minus(int a, int b) {
// 정수 형태의 두개의 인자를 입력해줘야함
if(this.powered) {
// powerOn()이 실행되면
return a-b;
// a-b 값을 리턴함
}
else {
// powerOff()가 실행되면
return 0;
}
}
// 곱셈
public int multiple(int a, int b) {
// 정수 형태의 두개의 인자를 입력해줘야함
if(this.powered) {
// powerOn()이 실행되면
return a*b;
// a*b 값을 리턴함
}
else {
// powerOff()가 실행되면
return 0;
}
}
// 나눗셈
public double divide (int a, int b) {
// 정수 형태의 두 개의 인자를 입력해줘야함
if(this.powered) {
// powerOn()이 실행되면
return (double)a/(double)b;
// a/b 값을 리턴함
// 본 함수는 실수 형태의 함수이므로 값을 실수형태로 변환해주기
}
else {
// powerOff()이 실행되면
return 0;
}
}
}
package ch06.sec08.exam01;
public class CalculatorExam {
public static void main(String[] args) {
// TODO Auto-generated method stub
Calculator cal = new Calculator();
// Calculator 객체 생성 (생성자 함수는 없음)
cal.powerOn();
// void powerOn()에 있는 구문 실행
// 참조변수.메소드의 형태
System.out.println(cal.plus(5, 4));
// plus 메소드 실행 및 5+4=9 값 리턴
// 인자가 2개인 일반메소드이기 때문에 값을 2개 넣어줘야함
System.out.println(cal.minus(5, 4));
// minus 메소드 실행 및 5-4=1 값 리턴
System.out.println(cal.multiple(5, 4));
// multiple 메소드 실행 및 5*4=20 값 리턴
System.out.println(cal.divide(5, 4));
// divide 메소드 실행 및 5/4=1.25 값 리턴
cal.powerOff();
// void powerOff() 메소드 실행
System.out.println(cal.plus(5, 4));
// powerOff가 실행되었으므로 결과값은 0
System.out.println(cal.minus(5, 4));
// powerOff가 실행되었으므로 결과값은 0
System.out.println(cal.multiple(5, 4));
// powerOff가 실행되었으므로 결과값은 0
System.out.println(cal.divide(5, 4));
// powerOff가 실행되었으므로 결과값은 0
System.out.println(cal.divide(5, 4));
// powerOff가 실행되었으므로 결과값은 0.0(실수 형태)
}
}
메소드가 가변길이 매개변수를 가지고 있다면 매개변수의 개수와 상관없이 매개값을 저장
메소드 호출 시 매개값을 쉼표로 구분해서 개수와 상관없이 제공할 수 있음
매개값들은 자동으로 배열 항목으로 변환되어 메소드에서 사용됨
일종의 배열 형태로 저장됨
형태
// for문
타입 함수명(타입 ... 변수명){
for(int i=0;i<변수명.length;i++){
실행문;
}
return 리턴값(또는 변수명);
};
package ch06.sec08.exam02;
public class Computer {
int sum(int ... values) {
// values는 가변길이 매개변수로 배열의 성질을 가짐
// 함수에 매개변수를 여러개 넣을 수 있음!
int sum = 0;
for(int i=0;i<values.length;i++) {
//values가 배열의 성질을 가지게 되어
//배열 for문처럼 실행해야함
sum += values[i];
}
return sum;
}
}
package ch06.sec08.exam02;
public class ComputerExam {
public static void main(String[] args) {
Computer com = new Computer();
// Computer 객체 선언
System.out.println(com.sum(1,2,3));
// sum 함수에 매개값을 3개 줌
System.out.println(com.sum(1,2,3,4,5));
// sum 함수에 매개값을 5개 줌
System.out.println(com.sum(new int[] {1,2,3,4,5}));
// sum 함수의 매개변수인 values가 배열의 형태이기 때문에
// 배열을 새로 선언하여 저장할 수도 있음
int[] values = {1,2,3,4,5};
// sum 함수의 매개변수인 values가 배열의 형태이기 때문에
// 배열 변수를 직접 넣어 sum 함수에 사용할 수도 있음
System.out.println(com.sum(values));
}
}
package ch06.sec08.exam03;
public class Car {
int gas;
// 멤버변수
void setGas(int g) {
this.gas = g;
}
// 리턴 값을 받지 않기 때문에 void문 사용
// this 연산자를 사용하여 멤버변수 gas에 값을 대입
boolean isleftGas() {
// 가스가 부족할 때!
// boolean 타입의 함수이므로 리턴값은 true/false
if(gas == 0) {
// gas가 0이면
System.out.println("gas가 없습니다");
return false;
// false 값을 리턴
}
System.out.println("gas가 있습니다");
// gas가 0이 아닐경우 가스가 있음
return true;
// true 값을 리턴
}
void run() {
// 자동차가 달린다
// 동작만을 위한 함수이기 때문에 void 함수 적용
while(true) {
if(this.gas>0) {
// gas가 0보다 크면
System.out.println("달립니다(gas=" + this.gas + ")");
gas--;
}
else {
// gas가 0보다 작거나 같으면
System.out.println("멈춥니다(gas=" + this.gas + ")");
return; // 메소드를 종료함
//return : 메소드를 종료하고 호출한 곳으로 되돌아가기
}
}
}
}
package ch06.sec08.exam03;
public class CarExample {
public static void main(String[] args) {
Car c = new Car();
// Car 객체를 생성함 (생성자 메소드는 없음)
c.setGas(5);
// Car 객체의 .setGas 함수 호출
// 인자값이 정수형 하나이므로 숫자 하나만 입력
if(c.isleftGas()) {
// Car 객체의 .isleftGas 함수 호출
System.out.println("출발합니다");
c.run();
// Car 객체의 .run 함수 호출
// gas가 0이 될때까지 실행
}
c.isleftGas();
// gas = 0이 되어서 false값 호출
System.out.println("gas를 주입하세요");
}
}
package ch06.sec08.exam04;
public class Calculator {
double areaRectangle(double width) {
//정사각형 구하는 함수
return width * width;
}
double areaRectangle(double width, double height) {
//직사각형 구하는 함수
return width * height;
}
// 메소드 오버로딩 : 같은 함수명은 사용 가능하나
// 매개변수의 타입과 갯수가 달라야함
}
package ch06.sec08.exam04;
public class CalculatorExam {
public static void main(String[] args) {
Calculator cal = new Calculator();
// Calculator 객체 생성
System.out.println(cal.areaRectangle(10));
// 매개변수가 1개인 areaRectangle() 함수 호출!
// 100.0
System.out.println(cal.areaRectangle(10, 5));
// 매개변수가 2개인 areaRectangle() 함수 호출!
// 50.0
}
}
package ch06.sec09;
public class Car {
// 멤버변수
String model;
int speed;
// 매개변수가 1개인 일반생성자 (String 타입)
Car(String m){
this.model = m;
// 입력받은 매개변수의 값을 멤버변수 model에 대입
}
// 매개변수가 1개인 일반메소드 (int 타입)
void setSpeed(int s) {
this.speed = s;
// 입력받은 매개변수의 값을 멤버변수 speed에 대입
}
void run() {
// 동작
this.setSpeed(100);
// 내부에 생성된 setSpeed 함수를 실행시킴
// 매개값이 정수 타입이 되어야함
System.out.println(this.model + "가 달립니다.(시속:" + this.speed + "km/h)");
}
}
package ch06.sec09;
public class CarExample {
public static void main(String[] args) {
Car c1 = new Car("벤츠");
// 매개변수가 1개인 일반생성자 객체 선언
Car c2 = new Car("포르쉐");
// 매개변수가 1개인 일반생성자 객체 선언
// run 함수 호출
c1.run();
// 벤츠가 달립니다.(시속:100km/h)
c2.run();
// 포르쉐가 달립니다.(시속:100km/h)
}
}
정적 멤버란 메소드 영역의 클래스에 고정적으로 위치하는 멤버로 공유 변수를 뜻함!
일반 멤버 메소드 호출시 컴파일러 내부에서는 객체를 전달하는데 이와는 다름!
일반 멤버(인스턴스 멤버)와 정적 멤버를 구분하는 것이 중요!
객체를 직접 생성하지 않고 내부 클래스에 있는 변수를 외부에서 사용할 수 있음!
-> 객체를 생성해야 사용할 수 있는 인스턴스 멤버와는 차이가 있음!
객체별로 소속이 되는 인스턴스 멤버와는 달리 클래스에 소속되어 있음
static
-> 정적 멤버를 사용하기 위한 용어로 함수나 변수 앞에 선언해주면 됨!
-> static을 선언해주는 동시에 클래스에 소속이 된 변수나 함수가 됨!
-> static 변수 또는 함수는 하나만 만들어짐! (중복 불가)
-> 정수 형태의 정적 변수는 초기값이 0
-> 일반 멤버함수에는 객체를 생성해야지만 메소드와 변수를 사용할 수 있었지만 static 함수에서는 클래스에 바로 소속이 되있기 때문에 클래스명으로 접근을 꼭 해주기 (변수명으로 해도 되지만 경고뜸)
-> 정적 멤버 변수/메소드 안에서는 인스턴스 멤버 변수, 메소드로 접근 안되고, this 사용도 불가능! (정적 멤버만 사용 가능함)
내부 클래스에서 정적 멤버의 사용 : static 변수명 / static 함수명()
외부 클래스에서 정적 멤버의 사용 : 클래스명.메소드명(); / 클래스명.변수명;
예제
package ch06.sec10.exam01;
public class Calculator {
static double pi = 3.14159;
// double 타입의 정적 변수 선언
static int plus(int x, int y) {
return x+y;
}
// 정적 메소드 선언 : 더하기 공식
static int minus(int x, int y) {
return x-y;
}
// 정적 메소드 선언 : 빼기 공식
}
package ch06.sec10.exam01;
public class CalculatorExam {
public static void main(String[] args) {
System.out.println(10 * 10 * Calculator.pi);
// Calculator 객체에서 만든 정적 변수 pi를 선언
// 314.159
System.out.println(Calculator.plus(5, 3));
// Calculator 객체에서 만든 정적 메소드 plus()를 선언
// 8
System.out.println(Calculator.minus(5, 3));
// Calculator 객체에서 만든 정적 메소드 minus()를 선언
// 2
// 정적 멤버 : 인스턴스 멤버처럼 객체를 선언하지 않고 함수나 변수를 선언 가능한 것
// 정적 멤버는 소속이 해당 클래스가 되기 때문에
// 정적 변수나 함수를 불러올 때는 함수나 변수명 앞에 클래스를 붙여준다.
}
}
정적 필드를 선언할 때 복잡한 초기화 작업이 필요할 때 사용함!
정적 블록은 클래스가 메모리로 로딩될 때 자동으로 실행
정적 블록이 클래스 내부에 여러 개가 선언되어 있을 경우에는 선언된 순서대로 진행
정적 필드는 객체 생성 없이도 사용할 수 있기 때문에 생성자에서 초기화 작업을 하지 않음!
형태
static {
변수명 = 값;
}
내부 클래스 (메소드 선언 클래스)
package ch06.sec10.exam02;
public class BaseballTeam {
static String manager = "이숭용";
// 문자열 타입 변수 manager를 정적 변수로 사용
static String out = "나가";
// 문자열 타입 변수 out을 정적 변수로 사용
static String landers;
// 문자열 타입 정적 변수 선언
static {
landers = manager + "-" + out;
// 정적 블록을 이용하여
// landers라는 정적변수에 값을 조합하여 초기화함
}
}
외부 클래스 (메소드 실행 클래스)
package ch06.sec10.exam02;
public class ManagerOutExam {
public static void main(String[] args) {
System.out.println(BaseballTeam.manager); // 이숭용
// 정적 변수 manager를 클래스와 함께 선언
System.out.println(BaseballTeam.out); // 나가
// 정적 변수 out을 클래스와 함께 선언
System.out.println(BaseballTeam.landers); // 이숭용-나가
// 정적 블록을 통해 만들어진 문자열 landers 출력
// ! 이숭용 나가 !
}
}
정적 메소드와 정적 블록은 내부에 인스턴스 필드와 메소드를 사용할 수 없음
정적 메소드와 정적 블록에서 인스턴스 멤버를 사용하고 싶으면 정적 멤버 내부에 객체를 먼저 생성하고 참조 변수로 접근
형태
static void 함수명(){
클래스명 참조변수 = new 클래스명();
참조변수.변수 = 값;
참조변수.함수명();
}
public static void main(String[] args){
정적함수명();
public class Car {
// 인스턴스 변수
int speed;
// 인스턴스 메소드
void run() {
System.out.println(speed + "km/h로 달립니다");
}
// 정적 메소드
static void simulate() {
Car c = new Car();
// Car 객체를 생성하여 인스턴스 멤버 함수와 메소드를 가져옴
c.speed = 200;
// 참조변수에 인스턴스 변수 speed를 선언하여 값을 대입
c.run();
// 참조변수에 인스턴스 메소드 run()을 선언
}
public static void main(String[] args) {
simulate();
// 정적 메소드 simulate()
// 같은 클래스 내에 만들어진 메소드이기 때문에 클래스명을 붙이지 않아도 됨
Car c = new Car();
c.speed = 60;
c.run();
}
}
package ch06.sec11.exam01;
public class Landers {
final String manager;
// final : manager라는 필드를 상수값으로 선언
final String out = "나가";
// out이라는 필드에 "나가" 라는 값을 주면서 선언과 동시에 초기화!
// final을 사용함으로서 "나가"라는 값이 부동의 값이 됨
String team = "SSG랜더스";
// final을 사용하지 않았으므로 변경이 가능한 값
public Landers(String m) {
// 인자값이 1개인 일반생성자
this.manager = m;
}
// m이라는 매개변수를 입력받아 해당 클래스의 manager 변수에 저장
// final 필드인 manager에 값을 저장함으로서 해당 값이 부동의 값이됨
}
package ch06.sec11.exam01;
public class LandersExample {
public static void main(String[] args) {
Landers ssg = new Landers("이숭용");
// String 타입의 매개값을 가지는 생성자를 호출
// 해당 매개값은 final 필드에 저장되는 값이므로 불변
System.out.println(ssg.team);
// SSG랜더스
System.out.println(ssg.manager);
// 이숭용
System.out.println(ssg.out);
// 나가
// manager와 out은 final 필드에 저장된 값으므로
// 다른 값으로 변경할 수 없음
// ssg.manager = "김원형";
// ssg.out = "종신감독";
ssg.team = "SK와이번스";
// 하지만 변수 team은 final 필드를 사용하지 않았기 때문에
// 값을 변경 할 수 있음
System.out.println(ssg.team);
// SK와이번스
}
}
불변의 값을 저장하는 필드로, 상수의 값을 저장함
하나의 값을 가지면서 변하지 않는 값을 저장할 때 사용함
형태 : static final 타입 상수 = 값(초기값);
내부 클래스
package ch06.sec11.exam02;
public class Earth {
static final double EARTH_RADIUS = 6400;
// static final : 하나의 값을 가지며 절대로 변하지 않을 때 사용
// 지구를 예로 들자면 우주상의 지구는 하나밖에 없고, 지구의 반지름은 변하지 않음
static final double EARTH_SURFACE_AREA;
// 지구의 표면적
// 지구의 표면적 또한 변하지 않는 값이기 때문에 static final 사용
static {
EARTH_SURFACE_AREA = 4 * Math.PI * EARTH_RADIUS * EARTH_RADIUS;
}
// 정적 블록을 사용하여 복잡한 초기화식을 따로 저장
// 표면적 구하는 식
}
package ch06.sec11.exam02;
public class EarthExample {
public static void main(String[] args) {
System.out.println("지구의 반지름= " + Earth.EARTH_RADIUS + "km");
// 정적 필드를 사용하였기 때문에 앞에 해당 클래스명만 붙여주면 됨
System.out.println("지구의 표면적= " + Earth.EARTH_SURFACE_AREA + "km^2");
// 정적 필드를 사용하였기 때문에 앞에 해당 클래스명만 붙여주면 됨
// 값 변경 불가능
// Earth.EARTH_RADIUS = 6500;
// Earth.EARTH_SURFACE_AREA = 5000;
}
}