Static / non-static 메소드
1. nonstatic 메소드 (멤버 / 인스턴스 메소드)
- 객체를 생성 후 호출해야 한다.
- 멤버변수 , 클래스변수 모두 접근할 수 있다.
2. static 메소드 (클래스 메소드 )
- 객체 생성 없이, 클래스명으로 직접 호출하는 메소드
- 클래스 변수에만 접근할 수 있다.
int a=100;
static int s=99;
public static void main(String[] args) {
MethodStudy study = new MethodStudy();
study.test1();
MethodStudy.test2();
}
/**
* 멤버메소드
*/
public void test1() {
System.out.println(a);
System.out.println(s);
//this 객체를 이용해 호출 (this보통 생략)
this.test3();
//static 메소드 호출(italic) - 같은 클래스 안이므로 클래스명 생략 가능
MethodStudy.test2();
}
public void test3() {
System.out.println("test3");
}
/**
* 클래스메소드
*/
public static void test2() {
// System.out.println(a); // Cannot make a static reference to the non-static field a
System.out.println(s);
// test3();
//객체생성후 호출은 가능!
new MethodStudy().test3();
}
오버로딩 (Overloading)
한 클래스 안에서 동일한 이름의 메소드를 여러개 선언
매개변수 선언부가 어떻게든 달라야 한다. (type, 순서, 개수)
오버로딩의 사용예시 )
매개변수의 타입은 다르지만, 동일한 작업을 하는 메소드를 그룹핑할 용도로 Overloading을 사용하자.
* 주의점 * 매개변수명, 접근제한자, 리턴타입은 상관치 않으므로 다른 메소드로 인정할 수 없다.
실제로 System.out.println을 ctrl 을 누르고 out을 눌러 확인해보면 모두 오버로딩 된 것을 확인할 수 있다.
public void test() {}
public void test(int a) {}
// public void test(int i) {} //매개변수명만 다른 것은 불가능
// private void test(int a) {} //접근제한자만 다른 것은 불가능
// public int test(int a) {} //리턴타입만 다른 것은 불가능
public void test(int a, int b) {}
public void test(int a, String b) {}
public void test(String b,int a) {}
public void test(String[] b,int a) {}
Call by value & Call by Reference
call by value
- 기본형을 매개인자로 사용하는 경우
- 값복사가 일어남
call by reference
- 참조형을 매개인자로 사용하는 경우
- 주소값 복사가 일어남 -> 같은 객체를 공유
CallByVallueReferenceStudy study = new CallByVallueReferenceStudy();
//call by value(기본형)
int a=10;
a=study.test1(a);
System.out.println("a = "+a); //10
//call by reference(참조형) 얕은복사
int[] arr= {1,2,3};
study.test2(arr);
System.out.println(Arrays.toString(arr)); //1,200,3
이때, 예외상황으로 String 형이 있다.
String형은 참조형으로 call by reference가 일어나야 하지만, 전달하는 타입에 따라서 call by value도, reference도 가능하다.
String은 immutable (변경불가한) 형태이다. String Literal Pool은 중복되지 않도록 관리하고, 재사용을 위해 변경하지 않는다.
그러므로 String연산에서 "안녕" 에 "잘가"를 더할 경우, 다음과 같아진다.
s에서만 안녕잘가의 주소를 가르키고, str에서는 안녕을 가르킨다.
일반적인 스트링 연산은 call by value 인 것이다.
이때 return String 타입을 사용하면 call by reference처럼도 사용이 가능하다.
아래 코드를 보고 참조하자.
//예외상황 참조형인데도 불구하고 call by value처럼 작동
String str = "안녕";
// study.test3(str);
str=study.test3(str); //call by reference처럼 쓸 수도 있음. return 사용하면.
System.out.println("str = "+str);//안녕
}
public void test4(int a, int[] arr) {
//전달하는 타입에 따라 callby v /r 달라짐 이 함수는 둘다 가능.
}
public String test3(String s) {
s+="잘가";
System.out.println("s = "+s);//안녕잘가
return s;
}
test3의 경우 call by reference 처럼 작동하고 (return type String)
test4의 경우 call by value 처럼 작동한다 (return type 없음)
재귀메소드 (재귀적 호출)
- 메소드 안에서 현재 메소드를 다시 호출하는 것.
- 종료조건을 명시하지 않으면 무한호출로 인해 StackOverflowError를 유발
- ex ) 팩토리얼, 하노이의탑
팩토리얼 함수 만들기
//5! = 5*4*3*2*1
int prod=1;
for(int i=5;i>0;i--) {
System.out.println(i);
prod *= i;
}
System.out.println(prod);
재귀함수로 만들기
public static void main(String[] args) {
RecursionStudy study = new RecursionStudy();
//main에서 출력하기
int prod = study.factorial(5);
System.out.println(prod);
}
//재귀 메소드
public int factorial(int n) {
System.out.println(n);
if(n==1) return 1; // 종료조건 명시
return factorial(n-1)*n;
}
생성자(메소드)
new 연산자를 통해 호출되는 메소드. 메모리 객체 할당 후 필드값 초기화 목적으로 사용한다.
생성자와 class의 이름은 똑같다.
생성자의 특징
- 리턴타입이 없다.
- 클래스 명과 생성자명은 동일 (대소문자도 구분함)
- 기본생성자, 파라미터 생성자로 구분
- 아무 생성자도 작성하지 않은 경우, JVM이 자동으로 기본생성자를 생성하여 호출한다.
- 파라미터 생성자를 하나라도 작성한 경우, JVM은 기본생성자를 만들지 않음.
즉, 명시적으로 기본 생성자를 작성할 것.
기본생성자가 필요한 이유
- 상속시 자식클래스에서 부모 클래스의 기본생성자를 자동으로 호출한다. (없으면 오류 발생)
- Spring framework에서 빈생성시 기본생성자를 호출한다.
생성자에서 다른 생성자를 호출하는 방법
다른 생성자를 호출하지 않고 그냥 사용할 경우, 생성자가 많으면 많아질수록 userId, userPw가 중복될 것이다.
이를 개선하기 위해 나온 것이 생성자에서 다른 생성자를 호출하는 방법 이다.
this : 다른 생성자 호출시 사용
- 생성자 맨 첫줄에 딱 한번만 호출이 가능함.
//constructor
public User() {
System.out.println("User 기본 생성자 호출!");
}
public User(String userId, String userPw) {
System.out.println("User(id, pw)");
this.userId=userId;
this.userPw=userPw;
}
public User(String userId, String userPw,
String userName, boolean snsAlarm, Date enrollDate) { //생성자의 오버로딩
this(userId,userPw); //맨윗줄 딱 한번만, 다른 생성자 호출하므로 User(id,pw) 호출하고 그다음에 아래내용.
System.out.println("User(id, pw, name, sns, date)");
this.userName=userName;
this.snsAlarm=snsAlarm;
this.enrollDate=enrollDate;
}
this를 이용하여 맨 아래 파라미터 생성자처럼 다른 생성자를 생성자 안에 호출할 수 있다.
VO Value Object class (데이터를 담기 위한 클래스)
기본 세팅법
- private field (캡슐화)
- public getter/setter (캡슐화)
- 기본생성자 / 모든 파라미터 생성자
- 모든 필드정보를 확인할 수 있는 메소드
꿀팁 getter/setter 한번에 만들기
오른쪽버튼 → sourse → Generate getters and setters