210420_5~7_210421_1chapter11.(Call by value/reference, 문자열)
클래스 멤버 메서드와 call by value
호출한다 값으로 ,즉 메서드를 호출할때 인자가 기본형 데이타인 경우
특징, 수신인자의 값을 바꾸어도 호출인자의 값에 영향이 없다.
이유 , 함수영역과 호출영역은 영역이 다르기 때문에 변수들간에 영향이 없다.
호출 즉 스택복사로만 값을 전달 할 수 있다.
-------------------------------- 정의 영역
public int add (int a, int b) {
int c ;
c = a+b;
return c ; a = a;
} b = b; 전달행위를 스택복사 라고 한다
---------------------------------호출 영역
int a = 100 ;
int b = 200;
int c ;
c = add (a,b) ; // call by value : 인자가 기본형 변수일때
출력 ==> c ;
Call by reference
호출한다 레퍼런스값으로, 즉 함수를 호출할때 인자가 객체인 경우이다.
수신인자를 변경하면 호출인자도 같이 변경된다.
왜? 수신인자와 호출인자는 동일한 객체를 가리키기 때문이다
------------------------------------소스코드
class Hi{
int a ;
int b;
int c;
}
------------------------------------함수영역
public Hi add (hi) {
// hi.a=200; (hi.a가 200으로 바뀐다) // return때문에 호출영역의 hi.a가 변경된다.
hi.c = hi.a + hi.b ;
return hi;
}
------------------------------------호출영역
Hi hi = new Hi( );
hi.a=100;
hi.b=200;
add(hi); //호출인자 hi와 수신인자 hi가 동일한 hashCode 값을 가진다.
// 즉 같은 메모리 영역을 가리키게 된다.
sysout(hi.a)
------------------------------------heap
[a=100|b=200|c=300] <======= address --가공--> hashCode
// [a=200|b=200|c=400]
레퍼런스 값 ==> hashcode ==> 4byte정수(약 +/- 2억4천만 사이에서 발생)
-----------------------------------------------
package chapter11;
class Pay1 {
String name = "";
int pay = 0;
int comm = 0;
int tax = 0;
public Pay1(String name, int pay, int comm) {
this.name = name;
this.pay = pay;
this.comm = comm;
comm = 100000;
System.out.println("Pay1생성자 comm : " + comm);
}
public void tax() {
tax = (int) (pay * 0.05);
}
public int earn() {
int total = (pay + comm) - tax;
return total;
}
}
public class Employee {
public static void main(String[] args) {
String name = "아로미";
int pay = 1500000;
int comm = 200000;
System.out.println("comm변수의 초기값 : " + comm);
Pay1 p = new Pay1(name, pay, comm); // call by value
//String은 객체형이지만 인자로 사용되면 call by value로 작동한다
System.out.println("main 메소드 comm : " + comm);
}
}
package chapter11;
class Pay2{
String name="";
int pay = 0;
int comm =0;
int tax = 0;
public Pay2(String name, int pay, int comm) {
this.name=name;
this.pay=pay;
this.comm=comm;
}
public int tax() {
tax=(int)(pay*0.05);
return tax;
}
public int earn() {
int total = (pay+comm)-tax;
return total;
}
}
class PrintPay2{
public static void ptintPay(Pay2 pay) { // 객체를 가인자로 사용
System.out.println("------------------");
System.out.println("성명 : " + pay.name);
System.out.println("본봉 : " + pay.pay);
System.out.println("보너스 : " + pay.comm);
System.out.println("세금 : " + pay.tax);
System.out.println("실수령액 : " + pay.earn());
pay.tax=5000;
System.out.println("-------------------");
System.out.println("pay.hashCode() : " + pay.hashCode());
}
}
public class Employee_args2 {
public static void main(String[] args) {
Pay2 p= new Pay2("왕눈이", 1000000,1000); // call by reference
p.tax();
PrintPay2.ptintPay(p); // call by reference
PrintPay2.ptintPay(p);
System.out.println("p.hashCode() :" + p.hashCode());
}
}
//------------------
//성명 : 왕눈이
//본봉 : 1000000
//보너스 : 1000
//세금 : 50000
//실수령액 : 951000
//-------------------
//pay.hashCode() : 366712642
//------------------
//성명 : 왕눈이
//본봉 : 1000000
//보너스 : 1000
//세금 : 5000
//실수령액 : 996000
//-------------------
//pay.hashCode() : 366712642
//p.hashCode() :366712642
함수호출의 방식
call by value : 기본형 값을 인자로 호출하는 경우
call by reference : 객체 참조값, 즉 레퍼런스값을 인자로 호출하는 경우
즉 레퍼런스를 인자로 호출하는 경우(예외String)
예외.(일단암기)
String은 객체형이지만 인자로 사용되면 call by value로 작동한다
call by address: 주소값을 인자로 호출하는 경우 - 자바에서는 안나옴(C++에서만 사용)
210421_1
-------------------------------예1) ---(X) 메모리
String str1 = "홍길동"; 실행 --------->홍길동
String str2 = "홍길동"; --------->홍길동
--------------------------------
-------------------------------예2) ---(O) 메모리
String str1 = "홍길동"; 실행 -------->홍길동
String str2 = "홍길동"; ---------> ---↑
str1 == str2 : True
--------------------------------
문자열은 상수이므로 메모리 상에 동일한 상수는 한번만 존재한다.
-------------------------------예3) 메모리
String str1 = "홍길동"; 실행 ------------------------------>홍길동
String str2 = "홍길동"; --------->----------------------↑
String str3 = new String("홍길동");----->[heap]해쉬코드->---↑
str1 == str2 : True
str1 == str3 : False
str1 equals(str2) : True <=== equals()는 순수문자열을 비교한다.
str1 equals(str3) : True
str1 해쉬코드 : 12345
str2 해쉬코드 : 12345
str3 해쉬코드 : 12345
결론 1.문자열은 == (등치연산자)로 비교하지말것., equals()메서드로 비교한다.
2.문자열은 영역에 상관없이 같은 문자열이면 해쉬코드는 언제나 동일하다.
-------------------------------예4) 메모리
String str1 = "홍길동"; 실행 --------->홍길동 + 킹 + 왕 + 짱-----(1) (X) 상수는 메모리 연장안됨
String str1 +="킹";
String str1 +="왕";
String str1 +="짱";
str1 => "홍길동킹왕짱"
홍길동--------(2) (O) 바꿀수 없으니 새로운 상수를 계속 만들어낸다.
홍길동킹
홍길동킹왕
홍길동킹왕짱
--------------------------------
결론 3. 문자열이 바뀌면 해쉬코드도 무조건 바뀐다,
4.그래서 문자열이 자주 바뀌면 String을 사용하지 않는다.
대신에, StringBuffer 나 StringBuilder를 사용한다.
------code
class 코드영역
-------data
static 상수영역 정적영역
--------------------------------method area
-------heap
객체영역 gc대상영역:가끔수거
-------stack
메서드실행영역 자동수거, 바로수거됨
package chapter11;
class GenClass {
private String name;
private int num;
// String을 인자로 사용하는경우
public GenClass(String a, int b) {
name = a;
num = b;
}
public void rename(String a) {
String str = a;
System.out.println("\nrename()--------------------"); // 출력순서2
System.out.println("rename() : " + str);
System.out.println("rename() a.hashCode : " + str.hashCode());
str = "★" + str;
System.out.println("\nrename()문자열변경-----------"); // 출력순서3
System.out.println("rename() : " + str);
System.out.println("rename() a.hashCode : " + str.hashCode());
}
}
public class NonThread {
public static void main(String[] args) {
GenClass t1 = new GenClass("first", 1);
String sc = "대~한~민국";
System.out.println("\nmain()--------------------"); //출력순서1
System.out.println("main() sc:" + sc);
System.out.println("sc.hashCode : " + sc.hashCode());
t1.rename(sc); // call by value이기때문에 sc= "대~한~민국"으로 돌아온다
System.out.println("\nmaint() rename(sc)후--------"); //출력순서4
System.out.println("main() sc:" + sc);
System.out.println("sc.hashcode : " + sc.hashCode());
}
}
//
//main()--------------------
//main() sc:대~한~민국
//sc.hashCode : -612571759
//
//rename()--------------------
//rename() : 대~한~민국
//rename() a.hashCode : -612571759
//
//rename()문자열변경-----------
//rename() : ★대~한~민국
//rename() a.hashCode : 281523158
//
//maint() rename(sc)후--------
//main() sc:대~한~민국
//sc.hashcode : -612571759