본문 바로가기

IT&코딩/Java

Java - 9일차 (객체지향 프로그래밍(클래스)2)

728x90
반응형

■ 인자값 전달방식

 

1. 값 호출 (Call by value)

 

이는 앞선 예제 MethodExTwo.java와 같이 메소드를 호출할 때 기본 자료형의 값을 인자로 전달하는 방식을 의미한다.

 

package jun.java.exam07;

public class ValueParameter {
	public int increase(int n) {
		++n;
		return n;
	}
	
	public static void main(String[] args) {
		int var1 =100;
		ValueParameter vp = new ValueParameter();
		int var2 = vp.increase(var1);
		System.out.println("var1 = " + var1 + ", var2 = " + var2);
	}
}

 

<결과>

var1 = 100, var2 = 101

 

2. 참조 호출 (Call by reference)

 

메소드 호출시 전달하려는 인자를 참조(객체) 자료형을 사용할 경우를 의미한다. 여기에는 기본 자료형이 아닌 일반 객체 또는 배열들이 속한다.

 

package jun.java.exam08;

public class ReferenceParameter {
	public void increase(int[] n) {
		for(int i=0; i<n.length; i++)
			n[i]++;
	}
	
	public static void main(String[] args) {
		int[] ref1 = {100, 800, 1000};
		ReferenceParameter rp = new ReferenceParameter();
		rp.increase(ref1);
		for(int i=0; i<ref1.length; i++)
			System.out.println("ref1[" + i + "] = " + ref1[i]);
	}
}

 

<결과>

ref1[0] = 101
ref1[1] = 801
ref1[2] = 1001

 

3. Varargs(Variable Arguments)

 

JDK5.0에서 새롭게 추가된 기능이며 이는 메소드 정의시 통일된 인자의 자료형에 '···' 라고 명시하고 이를 통해 메소드를 수행하는 데 필요한 인자의 수를 유연하게 구현할 수 있다. (내부적으로 배열화 작업을 자동적으로 해주기 때문)

 

package jun.java.exam09;

public class VariableEx {
	public void argTest(String...n) {
		for(int i=0; i<n.length; i++)
			System.out.println("n[" + i + "] : " + n[i]);
		System.out.println("-------------------------------");
	}
	public static void main(String[] args) {
		VariableEx ve = new VariableEx();
		ve.argTest("Varargs", "Test");
		ve.argTest("100", "600", "900", "1000");
	}
}

 

<결과>

n[0] : Varargs
n[1] : Test
-------------------------------
n[0] : 100
n[1] : 600
n[2] : 900
n[3] : 1000
-------------------------------

 

■ 메소드 오버로딩

 

하나의 클래스에서 같은 이름을 가진 메소드가 여러개 정의되는 것을 말함

같은 이름의 메소드의 인자가 다름

인자가 다르다는 것은 개수가 다르거나, 자료형이 다르거나, 인수의 순서가 다른 것

같은 목적으로 비슷한 동작을 수행하는 메소드들을 모아 이름을 같게 만들어 일관성 유지

 

'기능이 같은데 왜 이름을 여러개 만드는가? 기능이 같으면 이름도 통일해서 쓰자'는 의도.

문법에 영향을 주는 건 --> 매개변수의 개수나 자료형이 달라야 한다.

 

[메소드 비오버로딩 예제]

 

package jun.java.exam10;

public class OverloadingEx1 {
	
	public void intLength(int a) {
		String s = String.valueOf(a);
		System.out.println("입력한 값의 길이 : " + s.length());
	}
	
	public void floatLength(float f) {
		String s = String.valueOf(f);
		System.out.println("입력한 값의 길이 : " + s.length());
	}
	
	public void stringLength(String str) {
		System.out.println("입력한 값의 길이 : " + str.length());
	}
	
	public static void main(String[] args) {
		OverloadingEx1 oe1 = new OverloadingEx1();
		oe1.intLength(1000);
		oe1.floatLength(3.14f);
		oe1.stringLength("10000");
	}
}

 

<결과>

입력한 값의 길이 : 4
입력한 값의 길이 : 4
입력한 값의 길이 : 5

 

[메소드 오버로딩 예제]

매개변수의 개수가 다르거나(or) 자료형이 다르면 된다.

 

package jun.java.exam11;

public class OverloadingEx2 {
	public void getLength(int n) {
		String s = String.valueOf(n);
		getLength(s);
	}
	
	public void getLength(float n) {
		String s = String.valueOf(n);
		getLength(s);
	}
	
	private int getLength(String str) {
		System.out.println("입력한 값의 길이 : " + str.length());
		return 0;
	}
	
	public static void main(String[] args) {
		OverloadingEx2 oe2 = new OverloadingEx2();
		oe2.getLength(1000);
		oe2.getLength(3.14f);
		oe2.getLength("10000");
	}
}

 

■ 생성자

 

메모리 내에 객체가 생성될 때 호출되어 객체의 구조를 인식하게 하고 생성되는 멤버변수들을 초기화하는 데 목적을 둠

생성자명은 클래스명과 같아야 하고, return type을 정의하지 말아야 함

프로그래머가 어떠한 생성자도 정의하지 않았을 경우 컴파일러가 default 생성자를 자동으로 정의해줌 : 

default 생성자 : 인자가 없는 생성자 // 하나라도 만들면 default 생성자를 만들지 않는다.

생성자를 여러개 만들면 자동으로 오버로딩이 -

 

□ 생성자 접근제한의 의미

1. 생성자의 접근제한을 둘 경우 해당 객체를 생성할 수 있는 접근권한을 가짐

2. 클래스의 접근제한이 public으로 정의되어도 생성자를 private으로 정의하면 클래스 내부에서만 접근이 가능하다.

3. 만약 protected로 정의되는 클래스는 상속관계의 객체들만 생성할 수 있음

 

□ 생성자의 구성

 

□ 생성자 오버로딩 

 

생성자의 Overloading은 객체를 생성할 수 있는 방법의 수를 제공하는 것과 같으며 앞서 배운 메소드 오버로딩법과 다를 것이 없어 각 생성자의 구분 또한 인자로 구별된다.

 

문법 자체는 똑같지만

메소드 오버로딩이 기능이 같은데 왜 다른 이름으로 하느냐에 대한 물음에 대한 답이라면

생성자 오버로딩은 사용자에게 다양한 생성방식을 제공하기 위한 방식이다.

 

package jun.java.exam12;

class MyClass {
	private String name;
	private int age;
	public MyClass() {
		name = "무명";
	}
	public MyClass(String n) {
		name = n;
	}	
	public MyClass(String n, int a) {
		age = a;
		name = n;
	}
	public MyClass(int a, String n) {
		age = a;
		name = n;
	}
	public String getName() {
		return name;
	}
	public int getAge() {
		return age;
	}
}

 

package jun.java.exam12;

public class MyClassEx {

	public static void main(String[] args) {
		
		MyClass mc1 = new MyClass();
		MyClass mc2 = new MyClass("아라치");
		MyClass mc3 = new MyClass("마루치", 46);
		MyClass mc4 = new MyClass(23, "오자바");
		System.out.println(mc1.getName() + "," +mc1.getAge());
		System.out.println(mc2.getName() + "," +mc2.getAge());
		System.out.println(mc3.getName() + "," +mc3.getAge());
		System.out.println(mc4.getName() + "," +mc4.getAge());
	}
}

 

<결과>

무명,0
아라치,0
마루치,46
오자바,23

 

■ this와 this() // 두번째 문제의 해결

 

this란 특정 객체 내에서 자신이 생성되었을 때의 주소 값 변수

객체의 주소는 생성 전까지는 모르기 때문에 객체 생성 후 자신의 주소로 대치됨

this()는 현재 객체의 생성자를 의미함

생성자 안에서 오버로딩 된 다른 생성자를 호출할 경우에 this()라는 키워드로 호출함.

 

package jun.java.exam01;
	
class ThisEx {
	String name, jumin, tel;
	public ThisEx() {
		this.name = "Guest";
		this.jumin = "000000 - 0000000";
		tel = "000 - 0000 - 0000";
	}
	public ThisEx(String name) {
		this();
		this.name = name;
	}
	public ThisEx(String name, String jumin) {
		this(name);
		this.jumin = jumin;
	}
	public ThisEx(String name, String jumin, String tel) {
		this(name, jumin);
		this.tel = tel;
	}
	public String getName() {
		return name;
	}
	public String getJumin() {
		return jumin;
	}
	public String getTel() {
		return tel;
	}
}

 

package jun.java.exam01;

public class ThisEx1 {
	public static void main(String[] ar) {
		ThisEx ref = new ThisEx();
		System.out.println("Name : " + ref.getName());
		System.out.println("TEL : " + ref.getTel());
		System.out.println("Jumin : " + ref.getJumin());
	}
}

 

<결과>

Name : Guest
TEL : 000 - 0000 - 0000
Jumin : 000000 - 0000000

 

this는 생략지향이라 생략할 수 있으면 생략하기를 원한다. 즉 굳이 쓸 필요가 없는 경우에는 안 쓴다.

tel이 this.tel이 아닌 이유?

 

this()는 사용하려면 무조건 생성자의 첫 번째 줄에 써야 한다.

methodExThree에 var도
this.var = var 로 고치면 문제 해결

 

■ static 예약어

 

- 메소드나 멤버변수에 정의할 수 있으며 지역변수나 클래스에는 정의 불가

- static 키워드를 사용하면 static 변수(클래스 변수), static 메소드라 지칭함.

- 멤버 변수나 멤버 메소드는 해당 객체가 생성될 때 Heap 영역에 존재한다.

- static으로 선언된 필드, 메소드는 static 영역에 유일하게 만들어지면서 모든 객체들이 사용할 수 있는 공유개념을 가지기 때문

- 객체를 생성하지 않더라도 사용할 수 있음

- 클래스명.변수명 or 클래스명.메소드명 으로 접근 가능

 

Static 정리

 

1. 공유 - 메모리

2. 객체없이 사용가능하다 (클래스명으로 접근 가능)

3. 한 번만 초기화 됨 (초기화 구문이 별도로 존재한다)

4. static 메소드 안에서는 static 변수만 사용가능 / static 변수는 static 메소드 안에서만 사용가능.

- 자바에서 Static은 Heap이나 Stack과 메모리층이 다르다. 그래서 같이 사용할 수가 없다.

 

Static은 컴파일 할 때 가장 먼저 메모리에 잡힌다.

 

package jun.java.exam03;

public class StaticEx {
	int x; static int y;
}

 

package jun.java.exam03;

public class StaticExTest {
	public static void main(String[] ar) {
		// System.out.println(StaticEx.x); // error (객체를 발생시켜야 함)
		System.out.println(StaticEx.y); // 0 출력
		StaticEx.y = 100;
		System.out.println(StaticEx.y); // 100 출력
		
		StaticEx se = new StaticEx(); // x = 0, y = 0
		System.out.println(se.x); // 0 출력
		System.out.println(se.y); // 100 출력
	}
}

 

<결과>

0
100
0
100

 

■ final 예약어

 

final은 더 이상의 확장이 불가능함을 알리는 종단(상수)과 같은 것을 의미한다.

변수에 final을 적용시 상수를 의미한다.

메소드에 final을 적용시 오버라이딩으로서의 확장이 불가능하다

클래스에 final을 적용시 더 이상의 상속 확장이 불가능하다.

 

예를 들어서
public final double PIE = 3.141592 (상수는 전체 대문자)
상수는 값을 바꾸려는 시도 자체가 에러다.
상수는 정해져 있으니 굳이 숨길 수 필요가 없고 (public), 보통 static이 함께 붙는다. 

 

package jun.java.exam05;

public class Account { // Account.java
	private String name;
	private long balance;
	public Account() {
		
	}
	public Account(String name) {
		this.name = name;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public long getBalance() {
		return balance;
	}
	public void deposit(long amount) {
		balance += amount;
	}	
	public void withdraw(long amount) {
		if(balance < amount)
			System.out.println("잔고가 부족합니다");
		else
			balance -= amount;
	}
}

 

package jun.java.exam05;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Banking { // Banking.java
	public static void main(String[] args) throws IOException {
		
		Account na = new Account("홍길동");
		BufferedReader br = new BufferedReader(
				new InputStreamReader(System.in));
		
		String strWork;
		do {
			System.out.println("\n \n 작업내용을 선택하세요");
			System.out.println("==========================");
			System.out.println("입       금 =======>       1");
			System.out.println("출       금 =======>       2"); 
			System.out.println("잔 고 확 인 =======>       3"); 
			System.out.println("종       료 =======>       0");
			System.out.println("==========================");
			System.out.print("작업내용을 선택하세요 : ");
			strWork = br.readLine();
			int switchInt = 0;
			
			if(strWork != null)
				switchInt = Integer.parseInt(strWork);
			else {
				System.out.println("작업내용을 입력하지 않았습니다");
				System.exit(0);
			}
			switch(switchInt) {
			case 0: break;
			case 1:
				System.out.println("\n =================");
				System.out.print("금액을 입력하세요 : ");
				String strdepositIn = br.readLine();
				long depositLong = Long.parseLong(strdepositIn);
				na.deposit(depositLong);
				break;
			case  2:
				System.out.println("\n =================");
				System.out.print("금액을 입력하세요 : ");
				String strwithdrawIn = br.readLine();
				long withdrawLong = Long.parseLong(strwithdrawIn);
				na.withdraw(withdrawLong);
				break;
			case 3:
				System.out.println(na.getName() + "님의 잔고는 " + na.getBalance() + "원입니다");
				break;
			default:
				System.out.println("0 ~ 3 사이 숫자 입력\n");
			}
		}while(!strWork.equals("0"));	
	}
}
728x90
반응형