BackEnd/Java

0921 JAVA - PASS BY , this 키워드

jeoniee 2022. 9. 21. 13:49
728x90
반응형

목차

     

    메서드 호출 시 값 전달 방식에 따른 차이

      메서드 파라미터로 기본 데이터타입과 참조 데이터타입 전달 시 차이
      => 메서드 호출 시 값을 전달하는 경우 값의 복사가 일어남 
       


      1.Pass by Value (값에 의한 전달)
      - 메서드 호출 시 기본 데이터타입 데이터를 전달하는 경우 
      => 실제 값 (실제 데이터)를 복사해서 전달
     - 호출 된 메서드 내에서 전달받은 값(복사한 데이터)을 변경해도
        원본 데이터에는 아무런 영향이 없음
          
      2.Pass by Reference (참조에 의한 전달) 
     - 메서드 호출 시 참조 데이터타입 데이터를 전달 하는 경우
      => 실제 값이 있는 공간의 주소 값(참조 값)을 복사해서 전달
      - 호출 된 메서드 내에서 전달받은 값(복사한 주소값)을 접근하여 
        해당 주소에 있는 데이터를 변경하는 경우 
        원본 데이터도 동일한 주소값을 참조하므로 변경된 결과에 영향을 받음

     

    Money m = new Money();
    	PassByTest pbt = new PassByTest();
    	// 1. 메서드 파라미터로 기본 데이터타입 변수 값을 전달 하는 경우
    	System.out.println("changePrimitiveType() 메서드 호출 전 money =" + m.money);
    
    	// Money 인스턴스의 멤버변수 money 값을 메서드에 전달
    	// => 이 때, 기본 데이터 타입 (int) 이므로 실제 값을 복사해서 전달
    	pbt.changePrimitiveType(m.money); // money에 저장된 실제 값 (10000)이 복사됨
    
    	System.out.println("changePrimitiveType() 메서드 호출 후 money=" + m.money);
    	//호출 된 메서드에서 전달받은 데이터(복사한 실제 데이터)를 변경하더라도
    	//우너본 데이터에는 아무런 영향이 없다 (=10000그대로 존재)
    	System.out.println("----------------------------------------------------------");
    	
    	//2. 메서드 파라미터로 참조 데이터타입 변수 값을 전달 할 경우
    	System.out.println("changeReferenceType() 메서드 호출 전 money : " + m.money);
    	
    	//Money 인스턴스의 주소가 저장된 참조변수 값을 메서드에 전달 
    	//=> 이 때, 참조 데이터타입(Money) 이므로 주소 값을 복사해서 전달 
    	
    	pbt.changeReferenceType(m); // Money 인스턴스의 주소가 복사됨 
    	
    	System.out.println("changeReferenceType() 메서드 호출 후 money : " + m.money);
    	//호출 된 메서드에서 전달받은 (복사된)주소값에 접근하여 
    	//인스턴스 내의 데이터를 변경하는 경우
    	//원본 데이터도 동일한 주소값을 참조하게 되므로 
    	//변경된 값은 원본 데이터에도 영향을 주게 됨 
    	// = > 즉, 동일한 주소값을 참조하므로 어느 한쪽에서 객체 데이터를 
    	//     변경하는 경우 같은 주소를 참조하는 모두가 영향을 받음 
    	
    	
    	}
    
    }
    
    class PassByTest {
    	public void changePrimitiveType(int money) {
    		// 기본 데이터 타입 데이터(실제 값)을 전달받음(복사)
    	// 전달받은 기본 데이터타입 데이터를 변경
    	money -= 5000;
    	System.out.println("changePrimitiveType() 메서드의 money = " + money);
    }
    
    public void changeReferenceType(Money m) {
    	// 참조 데이터타입 데이터(주소값)을 전달받음(복사)
    	// 전달받은 주소 값에 해당하는 인스턴스에 접근하여
    	// 인스턴스 내의 멤버변수(실제 값)을 변경
    	// => 참조변수명.멤버변수에 접근 가능
    	m.money -= 5000;
    	System.out.println("changeReferenceType() 메서드의 money = " + m.money);
    
    	}
    }
    
    class Money {
    	int money = 10000;
    }

     

     

     

     

     


    this

    this 키워드
    자신의 인스턴스 주소값을 저장하는 참조 변수  = > 개발자가 생성하는 것이 x,  자바가 자동으로 만들어줌

    모든 인스턴스에는 this가 존재, 자신의 인스턴스 주소가 저장됨  = > 즉, 인스턴스마다 this에 저장된 값이 다름 

     

     



     

    이름, 나이를 전달 받아 초기화 하는 생성자 정의
    Alt + Shift + S -> O

     

    public class Ex {
    	public static void main(String[] args) {
        
    	Person p = new Person();
    	}
    }
    
    	class Person{
    	private String name;
    	private int age;
    
    	이름, 나이를 전달 받아 초기화 하는 생성자 정의
    	Alt + Shift + S -> O
    	public Person(String name, int age) {
    	this.name = name;  (로컬변수)
    	this.age = age; (로컬변수) 
    	}



     

     

     

     

     

    멤버변수 Getter / Setter 메서드 정의
     Alt  + Shift  + S  + R 

     

    public String getName() {
    		// 로컬 변수와 멤버변수의 이름이 중복되지 않으므로 
    		// 레퍼런스 this를 생략 가능 
    		return name;// return this.name; 과 동일하다. 
    	}
    
    	public void setName(String name) {
        	//메서드 내의 로컬변수와 클래스 내의 멤버변수의 이름이 동일할 경우
    		//메서드 내에서 변수 지정 시 로컬변수가 지정됨 
    		this.name = name;//로컬변수 name의 값을 다시 로컬변수 name에 저장하는 코드
    	}
    
    	public int getAge() {
    		return age;
    	}
    
    	public void setAge(int age) {
    		this.age = age;
    	}

    로컬변수와 멤버변수를 구별하기 위해서는

    멤버변수명 앞에  레퍼런스 this를 사용하여 해당 인스턴스에 접근하는 코드로 사용해야함

     
      => 외부에서 멤버변수 name에 접근 시 참조변수명.name형태로 접근하듯이

    내부에서 멤버변수 name에 접근 시 this.name 형태로 접근 

     

     

     

     

     

    문제


    Account 클래스 생성
    멤버변수 : accountNo, ownerName, balance 선언 (private 접근제한자 사용)
    파라미터 3개를 전달받아 초기화 하는 파라미터 생성자 정의
    Getter/Setter 메서드 정의 
    showAccountInfo() 메서드 -> 계좌번호, 예금주명, 현재잔고 출력
    public class Test {
    
    	public static void main(String[] args) {
    		Account ac = new Account("11-11","정지원",123);
    			
    		ac.showAccountInfo();
    		
    		ac.setAccountNo("222-222");
    		ac.setOwnerName("코코");
    		ac.setBalance(123123);
    		
    		ac.showAccountInfo();
    	}
    }

     

    alt shift s r

    alt shift s o 

    class Account{
    	private String accountNo;
    	private String ownerName;
    	private int balance;
    
    	public Account(String accountNo, String ownerName, int balance) {
    
    		this.accountNo = accountNo;
    		this.ownerName = ownerName;
    		this.balance = balance;
    	}
    
    	public String getAccountNo() {
    		return accountNo;
    	}
    
    	public void setAccountNo(String accountNo) {
    		this.accountNo = accountNo;
    	}
    
    	public String getOwnerName() {
    		return ownerName;
    	}
    
    	public void setOwnerName(String ownerName) {
    		this.ownerName = ownerName;
    	}
    
    	public int getBalance() {
    		return balance;
    	}
    
    	public void setBalance(int balance) {
    		this.balance = balance;
    	}
    
    	public void showAccountInfo() {
    		//클래스 내의 메서드에서 멤버변수에 접근하기 위해 멤버변수 이름 지정 
    			System.out.println("계좌번호 : " + accountNo);
    			System.out.println("계좌명 : " + ownerName);
    			System.out.println("잔고 : " + balance);
    		}
    }

     


    생성자 this ()

    자신의 생성자 내에서 자신의 또 다른 생성자를 호출 
     - 레퍼런스 this 사용과 동일하게 자신의 인스턴스에 접근하여 
     - 다른 오버로딩 생성자를 호출하는 용도로 사용 


     => 여러 생성자에서 각 각 인스턴스 변수를 중복으로 초기화하지 않고  하나의 생성자에서만 초기화 코드를 작성한 뒤 
     나머지 생성자에서는 해당 초기화 코드를 갖는 생성자를 호출하여 초기화 할 값만 전달 후 대신 인스턴스 변수를 초기화 
     

    => 메서드 오버로딩 시 코드의 중복을 제거하기 위해서 하나의 메서드에서만 작업을 수행하고 나머지 메서드는 해당 메서드를 호출하여 데이터를 전달하는 것과 동일함. (단, 메서드는 이름()으로 호출, 생성자는 this()로 호출하는 차이)

     

     

     

    <생성자 this() 호출 기본 문법>

    생성자 내의 첫번째 라인에서 

    this([데이터...]);

     

    class MyDate{
    	int year;
    	int month;
    	int day;
    	public MyDate(int year, int month, int day) {
    		super();
    		this.year = year;
    		this.month = month;
    		this.day = day;
    	}

     

     

     


    기본 생성자 만들기 (ALT + SHIFT + S -> O(bject)) 
    연도(year)만 전달받고, 나머지는 1월 1일로 초기화 하는 생성자
    연도(year), 월(month) 전달 받고 나머지는 1일로 초기화 하는 생성자
    연도(year), 월(month), 일(day)를 전달받고 초기화 하는 생성자 

     

    class MyDate{
    	int year;
    	int month;
    	int day;
    	
    	//기본 생성자
    	public MyDate() {
    		//연도 1900, 월 1, 일 1 로 초기화 
    		year = 1900;
    		month = 1;
    		day = 1; 
    	}
    	//연도(year)만 전달받고, 나머지는 1월 1일로 초기화 하는 생성자
    	// ALT SHIFT S - O   , year만 체크! 
    	public MyDate(int year) {
    		this.year = year;
    		month = 1;
    		day = 1;
    	}
    	//연도(year), 월(month) 전달 받고 나머지는 1일로 초기화 하는 생성자
    	// ALT SHIFT S - O   , year, month 체크! 
    	public MyDate(int year, int month) {
    		this.year = year;
    		this.month = month;
    		day = 1;
    	}
    	//연도(year), 월(month), 일(day)를 전달받고 초기화 하는 생성자 
    	// ALT SHIFT S - O  모두 체크! 
    	public MyDate(int year, int month, int day) {
    		super();
    		this.year = year;
    		this.month = month;
    		this.day = day;
    	}
    
    }

     

     

     

     

     


     MyDate()생성자 호출 => 1900년 1월 1일 로 초기화 
     MyDate(int) 생성자 호출 => 2022년 1월 1일로 초기화 
    MyDate d1 = new MyDate();
    System.out.println(d1.year + "/" + d1.month + "/" + d1.day); 
    
    
    ///////////////////////////////////////////////////////////
    
    
    MyDate d2 = new MyDate(2022);
    System.out.println(d2.year + "/" + d2.month + "/" + d2.day);

     

     

    MyDate(int,int) 생성자 호출 => 2022년 9월 1일로 초기화 
    MyDate d3 = new MyDate(2022, 9);
    System.out.println(d3.year + "/" + d3.month + "/" + d3.day); 
    System.out.println("--------------------------------------");

     

     

    MyDate(int,int,int) 생성자 호출 => 2022년 9월 21일로 초기화 
    MyDate d4 = new MyDate(2022, 9, 21);
    System.out.println(d4.year + "/" + d4.month + "/" + d4.day); 
    System.out.println("--------------------------------------");

     

     

     

    생성자 this를 사용해서 반복되는 구문을 제거하기

     

    인스턴스 변수 초기화 코드가 다른 생성자와 중복됨
    중복 제거를 위해 3개의 값을 전달받는 파라미터 생성자를 호출하여
    초기화에 사용될 데이터를 전달, 초기화 대신 수행

    class MyDate{
    	int year;
    	int month;
    	int day;
    	
    	//기본 생성자
    	public MyDate() {
    		//연도 1900, 월 1, 일 1 로 초기화 
    		
    		// 자신의 생성자 내에서 다른 오버로딩 된 생성자를 호출 하는 방법
    		this(1900, 1, 1); //다른 실행코드보다 무조건 먼저 실행되어야함
    		//=> public Mydate(int year, int month, int day) {} 생성자가 호출 됨 
    		System.out.println("MyDate(int)생성자 호출 됨!");
    		//생성자 내의 다른 실행코드보다 아래쪽에 생성자 this()가 올 수 없다. 
    	
    //		year = 1900;
    //		month = 1;
    //		day = 1; 
    
    		
    		
    	}
    	//연도(year)만 전달받고, 나머지는 1월 1일로 초기화 하는 생성자
    	// ALT SHIFT S - O   , year만 체크! 
    
    	public MyDate(int year) {
    	//MyDate(int,int,int)생성자를 호출하여
    	//전달받은 연도(year)와 1월 1일 값을 전달하여 대신 초기화 
    		
    		this(year, 1, 1);
    		System.out.println("MyDate(int)생성자 호출 됨!");
    //		this.year = year;
    //		month = 1;
    //		day = 1;
    	}
    	//연도(year), 월(month) 전달 받고 나머지는 1일로 초기화 하는 생성자
    	// ALT SHIFT S - O   , year, month 체크! 
    	public MyDate(int year, int month) {
    		this(year, month, 1);
    		//MyDate(int,int,int)생성자를 호출하여
    		//전달받은 연도(year), 월(month)과 1일 값을 전달하여 대신 초기화 
    		System.out.println("MyDate(int,int)생성자 호출 됨!");
    		this.year = year;
    		this.month = month;
    		day = 1;
    	}
    	//연도(year), 월(month), 일(day)를 전달받고 초기화 하는 생성자 
    	// ALT SHIFT S - O  모두 체크! 
    	public MyDate(int year, int month, int day) {
    		System.out.println("MyDate(int,int,int)생성자 호출 됨!");
    		this.year = year;
    		this.month = month;
    		this.day = day;
    	}
    
    }

     

     

    문제


    Accoun2t2 클래스 정의
    - 멤버변수 : accoutNo, ownerName, balance 선언
    - 생성자 오버로딩 (레퍼런스 this 와 생성자 this()를 활용)
     1) 기본 생성자 ("111-1111-111","홍길동",0) 
     2) 계좌번호만 전달받아 초기화하는 생성자
     3) 계좌번호, 예금주명을 전달 받아 초기화하는 생성자 
     4) 계좌번호, 예금주명, 현재잔고를 전달받아 초기화하는 생성자
    => 초기화 작업을 수행하는 생성자 *-일반 메서드 : showAccountInfo()

     

     

    public class Test2 {
    	public static void main(String[] args) {
    		Account2 ac2 = new Account2();
    		System.out.println(ac2.accountNo + ac2.ownerName + ac2.balance);
    		
    		Account2 ac3 = new Account2("222-2222-222");
    		System.out.println(ac3.accountNo + ac3.ownerName + ac3.balance);
    
    		Account2 ac4 = new Account2("1-1", "코코");
    		System.out.println(ac4.accountNo + ac4.ownerName + ac4.balance);
    		
    		Account2 ac5 = new Account2("1234-1234", "카누",10000);
    		System.out.println(ac5.accountNo + ac5.ownerName + ac5.balance);
    	}
    
    }
    	//Accoun2t2 클래스 정의 
    class Account2{
    	String accountNo;
    	String ownerName;
    	int balance;
    	
    	//1) 기본 생성자
    	public Account2() {
    	this("111-1111-111", "홍길동", 0);
    	
    	}
    	//2) 계좌번호만 전달받아 초기화하는 생성자 
    	public Account2(String accountNo) {
    		this.accountNo = accountNo;
    		ownerName = "홍길동";
    		balance = 0;
    	}
    	// 3) 계좌번호, 예금주명을 전달 받아 초기화하는 생성자
    
    	public Account2(String accountNo, String ownerName) {
    		this.accountNo = accountNo;
    		this.ownerName = ownerName;
    		balance = 0;
    	}
    	// 4) 계좌번호, 예금주명, 현재잔고를 전달받아 초기화하는 생성자 
    	public Account2(String accountNo, String ownerName, int balance) {
    		super();
    		this.accountNo = accountNo;
    		this.ownerName = ownerName;
    		this.balance = balance;
    	}
    	public void showAccountInfo() {
    	//초기화 작업 수행하는 생성자 
    		System.out.println("계좌번호 : " + accountNo);
    		System.out.println("계좌명 : " + ownerName);
    		System.out.println("잔고 : " + balance + "원");
    			
    		}
    }
    728x90
    반응형