■ 인자값 전달방식
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"));
}
}
'IT&코딩 > Java' 카테고리의 다른 글
Java - 11일차 (추상클래스와 인터페이스) (0) | 2022.10.27 |
---|---|
Java - 10일차 (상속과 다형성) (0) | 2022.10.26 |
Java - 8일차 (객체지향 프로그래밍(클래스)) (0) | 2022.10.23 |
Java - 7일차 (Game 설계) (0) | 2022.10.23 |
Java - 6일차 (배열) (0) | 2022.10.20 |