JAVA(Sol)(정리대기중..언젠가)

210420_5~7_210421_1chapter11.(Call by value/reference, 문자열)

너굴셉 2021. 4. 20. 16:01

클래스 멤버 메서드와 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