Method
매서드와 캡슐화
Factorial
package ch06;
public class Factorial2 {
public static void main(String[] args) {
int[] nums = {3,4,5,6,7};
for (int num:nums) {
System.out.println(num+"! = "+fact1(num));
System.out.print(num+"! = ");
System.out.println(fact2(num));
}
}
private static int fact1(int num) {
if (num == 0) return 1;
else return num*fact1(--num);
}
private static int fact2(int num) {
int result = 1;
for (int i=num; i>0;i--) {
if (i==1) System.out.print(i+" = ");
else System.out.print(i+" * ");
result *= i;
}
return result;
}
}
Recursive Function (반복함수)
private static int fact2(int num) {
if (num==1) return 1;
else return num * fact2(--num);
}
이렇게 스스로를 호출하는 function을 'recursive function'이라고 한다.
스스로를 호출하며 반복되기 때문에 infinite loop에 빠지기 쉬우니 항상 주의해서 사용해야한다.
num = 4 일 경우
4 * ( 3 * ( 2 * ( 1 ) ) ) 이렇게 된다
num * ( num * (num * ( 1 ) ) )
Call By Value
기본형 매개변수 - 변수의 값을 읽기만 할 수 있다.
> Read Only
package ch06;
class B1 {
void m1(int x, int y) { // 전달한 것은 x=10, y=20
x += 7; y+=5;
System.out.println("m1 x = "+x);
System.out.println("m1 y = "+y);
}
public class CallByValue1 {
public static void main(String[] args) {
B1 a1 = new B1();
int x = 10, y = 20;
a1.m1(x, y); // 값 10, 20을 전달한 것이지 변수 x, y를 전달한 것이 아니다
System.out.println("main x = "+x);
System.out.println("main y = "+y);
}
}
}
result :
m1 x = 17
m1 y = 25
main x = 10
main y = 20
m1에서 x와 y 값을 바꿔서 출력
package ch06;
class B1 {
void m1(int x, int y) { // 전달한 것은 x=10, y=20
// x와 y값을 서로 교환해서 출력
// call by value 메서드에서 변경된 결과는 원래 데이터에 영향이 없다
int temp=x; x=y; y=temp;
System.out.println("m1 x = "+x);
System.out.println("m1 y = "+y);
}
public class CallByValue1 {
public static void main(String[] args) {
B1 a1 = new B1();
int x = 10, y = 20; // 데이터가 기본형인 경우 a1.m1(10,20)
a1.m1(x, y); // 값 10, 20을 전달한 것이지 변수 x, y를 전달한 것이 아니다
System.out.println("main x = "+x);
System.out.println("main y = "+y);
}
}
}
result :
m1 x = 20
m1 y = 10
main x = 10
main y = 20
Call By Reference
참조형 매개변수 - 변수의 값을 읽고 변경 할 수 있다.
> Read and Write
package ch06;
class C1 {
void m1(int[] num) {
num[0]=77; num[1]=100;
for (int i=0; i<num.length; i++) {
System.out.println("num["+i+"] = "+num[i]);
}
}
}
public class CallByReferecne {
public static void main(String[] args) {
C1 c1 = new C1();
int[] num = {12,34,66}; // 배열은 참조형 // 참조형 데이터는 주소를 전달
c1.m1(num); // 메서드에서 바뀌면 원본 데이터도 바뀐다
for (int i=0; i<num.length; i++) {
System.out.println("main num["+i+"] = "+num[i]);
}
}
}
result :
num[0] = 77
num[1] = 100
num[2] = 66
main num[0] = 77
main num[1] = 100
main num[2] = 66
call by value 와 다르게 참조형은 주소를 전달하기 때문에 수정시 원본 데이터도 바뀐다.
another e.g.
package ch06;
class C2 {
int x, y;
public void m1(C2 c) {
// x와 y를 서로 교환하고 c.x, c.y를 출력
int temp;
temp = x; c.x=y; c.y=temp;
System.out.println("m1 x = "+c.x);
System.out.println("m1 y = "+c.y);
}
}
public class CallByReference2 {
public static void main(String[] args) {
// C2 c를 생성하여 c.x=10, c.y=20d를 대입하고 m1()메서드에 c를 전달
// c.x, c.y를 출력
C2 c = new C2();
c.x=10; c.y=20;
c.m1(c);
System.out.println("main x = "+c.x);
System.out.println("main y = "+c.y);
}
}
result :
m1 x = 20
m1 y = 10
main x = 20
main y = 10
Conclusion
Call By Value | Call By Reference |
data 값에 의한 호출 | data 메모리 주소에 의한 호출 |
data에 직접적인 영향을 줄 수 없다 | data에 직접적으로 영향을 줄 수 있다 |
Overloading (오버로딩)
: 하나의 클래스에 같은 이름의 메소드를 여러 개 정의하는 것
Method overloading / overloading
오버로딩의 조건
- 메소드의 이름이 같아야 한다.
- 매개변수의 개수 또는 타입이 달라야 한다. (같을 경우엔 error)
- 매겨변수는 같고 리턴 타입이 다른 경우는 오버로딩이 성립되지 않는다.
Example
다양하게 오버로딩된 메소드를 제공함으로써 모든 변수를 출력할 수 있도록 설계
void println ()
void println (boolean x)
void println (char x)
void printin (char [] x)
void printin (double x)
void printin (float x)
void printin (int x)
void printin (long x)
void println (Object x)
void println (String x)
매개 변수의 이름이 다른 것은 오버로딩이 아니다.
// [ex2.1]
int add (int a, int b) { return a+b; }
int add (int x, int y) { return x+y; }
리턴 타입은 오버로딩의 성립조건이 아니다.
// [ex2.2]
int add (int a, int b) { return a+b; }
int add (int a, int a) { return (long) (a + b); }
매개변수의 타입이 다르므로 오버로딩이 성립한다.
// [ex3]
long add (int a, int b) { return a+b; }
long add (long a, int b) { return a+b; } I
overloading1
package ch06;
class E1 {
int add(int x, int y) {
return x+y;
}
// int add(int a, int b) { return a+b; } // 기존 메소드와 같은 이름 and 같은 데이터형은 error
double add(double x, double y) {
return x+y;
}
String add(String name) {
return "Hello, "+name;
}
}
public class OverLoading {
public static void main(String[] args) {
E1 e1 = new E1();
System.out.println(e1.add("Leigh"));
System.out.println(e1.add(12, 67));
System.out.println(e1.add(3.14, 5.23));
}
}
result :
Hello, Leigh
79
8.370000000000001
overloading2
package ch06;
class Box {
int volume(int x, int y, int z) {
return x*y*z;
}
double volume(double x,double y,double z) {
return x*y*z;
}
}
public class Overloading2 {
public static void main(String[] args) {
// 객체생성
// 12, 15, 20
// 12.7, 5.6, 7.4
// 15.2, 5, 20
Box b1 = new Box();
System.out.println("Volume int : "+b1.volume(12, 15, 20));
System.out.println("Volume double : "+b1.volume(12.7, 5.6, 7.4));
// 실수와 정수가 섞여있는 정수는 실수로 변경 가능, 실수는 가ㅏㅇ제형 분환하지 않으면 변경 불가
System.out.println("Volume combined : "+b1.volume(15.2, 5, 20));
}
}
result :
Volume int : 3600
Volume double : 526.2879999999999
Volume combined : 1520.0
Method Overloading
Overloading(중복정의) : 하나의 클래스 내에서 같은 이름을 가지는 메서드(멤버함수) 를 여러 개 정의되는 것. 이것은 컴파일 시 컴파일러에 의해 각 메소드들이 구별되며 기 준은 인자가 된다.
메소드는 인자로 구분된다.
Example
package ch06;
public class Student1 {
String name;
int kor, eng, math;
public Student1() {}
public Student1(String n, int k, int e, int m) {
name = n; kor = k; eng = e; math = m;
}
int getTotal() {
return kor+eng+math;
}
float getAverage() {
return getTotal()/(float)3;
}
}
package ch06;
public class Student1Ex {
public static void main(String[] args) {
Student1 st1 = new Student1();
st1.name = "Bailey"; st1.kor=100; st1.eng=60; st1.math=76;
System.out.println("Name : "+st1.name);
System.out.println("Total : "+st1.getTotal());
System.out.println("Average : "+st1.getAverage());
System.out.println();
Student1 st2 = new Student1("Daniel", 77, 88, 99);
System.out.println("Name : "+st2.name);
System.out.println("Total : "+st2.getTotal());
System.out.println("Average : "+st2.getAverage());
}
}
result :
Name : Bailey
Total : 236
Average : 78.666664
Name : Daniel
Total : 264
Average : 88.0
위의 코드에 대해서 설명하자면,
Student class 에서 같은 이름의 메소드를 두번 만들었다. (메소드 오버로딩)
1. No parameter(매개변수 있음) 2. with 3 parameters(매개변수 없음)
그렇기 때문에 객체 생성할때 그냥 생성하면 1번이 호출되는 것이고 arguments(인자)를 넣어 생성하면 2번을 호출하는 것이다.
public Student1() {}
public Student1(String n, int k, int e, int m) {
name = n; kor = k; eng = e; math = m;
}
참조변수 this
this
인스턴스 자신을 가리키는 참조변수. 인스턴스의 주소가 저장되어있음 모든 인스턴스 메서드에 지역변수로 숨겨진 채로 존재
"this"는 현재의 객체를 의미
- 생성자나 메소드의 매개변수와 객체 변수가 같은 이름을 가질 때 사용
- 같은 클래스내의 다른 생성자를 호출할 때 사용
" this() "
- 같은 클래스내의 다른 생성자를 호출
Example - this 1
package ch06;
class Car{
String kind;
int displacement;
String color;
public Car(String k, int d, String c) {
kind = k; displacement = d; color = c;
}
void print() {
System.out.println("==================");
System.out.println("kind : "+kind);
System.out.println("displacement : "+displacement);
System.out.println("color : "+color);
}
}
public class CarEx {
public static void main(String[] args) {
Car car1 = new Car("Hyundai", 1500, "red");
Car car2 = new Car("Benz", 2000, "yellow");
Car car3 = new Car("BMW", 2500, "blue");
car1.print(); car2.print(); car3.print();
}
}
result :
==================
kind : Hyundai
displacement : 1500
color : red
==================
kind : Benz
displacement : 2000
color : yellow
==================
kind : BMW
displacement : 2500
color : blue
만약 Car 클래스 메소드에서 매개변수의 이름을 원래 변수의 이름과 같이 변경하고 싶다면?
class Car{
String kind;
int displacement;
String color;
public Car(String k, int d, String c) {
kind = k; displacement = d; color = c;
}
void print() {
System.out.println("==================");
System.out.println("kind : "+kind);
System.out.println("displacement : "+displacement);
System.out.println("color : "+color);
}
}
여기서
public Car(String k, int d, String c) {
kind = k; displacement = d; color = c;
}
이 부분을 kind = kind, displacement = displacement, color = color 이렇게 바꾸고 싶다면
class Car{
String kind;
int displacement;
String color;
public Car(String k, int d, String c) {
this.kind = kind, this.displacement = displacement, this.color = color
}
void print() {
System.out.println("==================");
System.out.println("kind : "+kind);
System.out.println("displacement : "+displacement);
System.out.println("color : "+color);
}
}
앞에 this를 붙여주어 구분될 수 있도록 한다.
Example - this 2
package ch06;
public class Student2 {
String name;
int kor, eng, math;
Student2(String name, int kor, int eng, int math) {
this.name = name; this.kor = kor; this.eng = eng; this.math = math;
}
void prn() {
int tot = kor+eng+math;
int avg = tot/3;
System.out.println("Name : "+name);
System.out.println("Korean : "+kor);
System.out.println("English : "+eng);
System.out.println("Math : "+math);
System.out.println("Total : "+tot);
System.out.println("Average : "+avg);
System.out.println("=====================");
}
public static void main(String[] args) {
Student2 st1 = new Student2("Hani", 88, 99, 66);
Student2 st2 = new Student2("Rose", 77, 88, 55);
Student2 st3 = new Student2("Bora", 92, 56, 88);
st1.prn(); st2.prn(); st2.prn();
}
}
result :
Name : Hani
Korean : 88
English : 99
Math : 66
Total : 253
Average : 84
=====================
Name : Rose
Korean : 77
English : 88
Math : 55
Total : 220
Average : 73
=====================
Name : Rose
Korean : 77
English : 88
Math : 55
Total : 220
Average : 73
=====================
Constructor 생성자
생성자란?
- 인스턴스가 생성될 때마다 호출되는 ‘인스턴스 초기화 메서드’
- 인스턴스 변수의 초기화 또는 인스턴스 생성시 수행할 작업에 사용
- 몇가지 조건을 제외하고는 메서드와 같다.
- 모든 클래스에는 반드시 하나 이상의 생성자가 있어야 한다.
* 인스턴스 초기화 – 인스턴스 변수에 적절한 값을 저장하는 것.
생성자의 조건
- 생성자의 이름은 클래스의 이름과 같아야 한다.
- 생성자는 리턴값이 없다. (하지만 void를 쓰지 않는다.)
클래스이름(타입 변수명, 타입 변수명, ... ) {
// 인스턴스 생성시 수행될 코드
// 주로 인스턴스 변수의 초기화 코드를 적는다.
}
기본 생성자란?
- 매개변수가 없는 생성자
- 클래스에 생성자가 하나도 없으면 컴파일러가 기본 생성자를 추가한다. (생성자가 하나라도 있으면 컴파일러는 기본 생성자를 추가하지 않는다.)
“모든 클래스에는 반드시
하나 이상의 생성자가 있어야 한다.”
Example - Constructor
public class Constructor {
int i; int j;
public Constructor(){ //디폴트생성자
System.out.println("Constructor()"); this.i=100;
this.j=100;
}
publicConstructor(inti){ //매개변수가있는생성자
System.out.println("Constructor(int i)"); this.i=i;
this.j=100;
}
public Constructor(int i,int j){
System.out.println("Constructor(int i,int j)");
this.i=i;
this.j=j;
}
}
다시 돌아와서
" this() "
- 같은 클래스내의 다른 생성자를 호출 (Call other Constructor)
EX
package ch06;
public class Student3 {
String name;
int kor, eng, math;
Student3(String name) {
this(name,60); // 1
System.out.println("매개변수 1개 이름 : "+name); // 7
}
Student3(String name, int kor) {
this(name,kor,60); // 2
System.out.println("매개변수 2개 이름 : "+name+", Korean : "+kor); // 6
}
Student3(String name, int kor, int eng) {
this(name,kor,eng,60); // 3
System.out.println("매개변수 3개 이름 : "+name+", Korean : "+kor+", English : "+eng); // 5
}
Student3(String name, int kor, int eng, int math) {
System.out.println("매개변수 4개 이름 : "+name+", Korean : "+kor+", English : "+eng+", Math : "+math);
// 4
}
public static void main(String[] args) {
Student3 st1 = new Student3("하니");
}
}
result :
매개변수 4개 이름 : 하니, Korean : 60, English : 60, Math : 60
매개변수 3개 이름 : 하니, Korean : 60, English : 60
매개변수 2개 이름 : 하니, Korean : 60
매개변수 1개 이름 : 하니
overloading
- Same method(same name) but different parameter ( type and number of parameters)
overriding
- 부모클래스로 상속 받은 method를 변형시킬 수 있다.
- 오버로딩과 비슷하지만 부모로부터 받은 메소드를 동일한 매개변수 조건으로 생성 가능하며 생성후에는 자식 클래스의 메소드가 우선이다.
'Java Class Notes' 카테고리의 다른 글
Access Modifier and Encapsulation (접근제어자와 캡슐화) (0) | 2023.02.23 |
---|---|
Ex - OOP (0) | 2023.02.23 |
Ex - Array (0) | 2023.02.22 |
객체 / OPP (Object-Oriented Programming) (1) | 2023.02.21 |
Array (배열) (2) | 2023.02.21 |