자바를 자바 08(클래스 세부, call-by-value)

TonyHan·2020년 9월 26일
0

20) 자바

목록 보기
7/27

Creating an Array of Objects

class Employee{
	private String name;
    public Employee(String name){
	this.name = name;
	}
	public String getName(){
		return this.name;
	}
}
public class Lecture{
	public static void main(String[] args){
		Employee m[] = new Employee[3];
        m[0] = new Employee("Mario");
		m[1] = new Employee("Luigi");
		m[2] = new Employee("Toad");
		System.out.println(m[0].getName());
	}
}

Instance Variable Instantiation

클래스 변수에 선언과 동시에 초기화 가능

class Employee {
	private String name = "Joe";
	public void setName(String name) {
		this.name = name;
	}
	public String getName() {
		return this.name;
	}
}

Default Initialization

만약 초기화가 아예 진행되지 않았다면? 그러면 클래스 자체적으로 default constructor가 발동하여
number : 0 / boolean : false / object : null
로 값이 초기화 된다.

하지만 local variable은 반드시 생성과 동시에 초기화 해주어야 한다.

class Employee {
	private int salary;
	public int getSalary() {
		return this.salary;
	}
}

public class Lecture {
	public static void main(String[] args) {
		Employee m = new Employee();
		System.out.println(m.getSalary());
		int local_var;
		System.out.println(local_var); // Error: local variable not initialized!
	}
}

Final Instance variable

final 이라는 것은 constructor에서는 초기화 할 수 있지만 다른 메소드에서는 변경할 수 없는 변수를 이야기 한다.

class Employee{
	priate final String name;
    public Employee(){
		this.name = name;
	}
    public void setName(String name){
		//this.name = name //에러난다.
	}
}

Static Variable

static variable 은 클래스 자체에 소속되는 거고 객체별로 속해지는 것이 아님. 그렇기에 공유되고 있는 변수라고 생각할 수 있음.

class Employee{
	//초기화 방법1
    private static int lastId=0; //static variable
    //초기화 방법2
    static{
		lastId = 0;
	}
    private int id; //instance variable
    public Employee() { id = ++lastId; }
	public int getId() { return this.id; }
	public int getLastId() { return this.lastId; } # 이건 좋은 방법이 아님
}

public class Lecture {
	public static void main(String[] args) {
		Employee m = new Employee();
		Employee n = new Employee();
		System.out.println(m.getId());
		System.out.println(n.getId());
		System.out.println(m.getLastId());
		System.out.println(n.getLastId());
	}
}

출력결과 : 1 2 2 2

여기에서 주의할 것이
public int getLastId() { return this.lastId; }
이 함수인데, static variable을 method에서 접근하고 있다. 이러면 java 에서는 에러를 띄어준다.

왜냐하면 java의 garbage collector(gc) 때문이다. gc가 해당 인스턴스 메소드가 끝나는 시점에 메모리를 제거한다면 static variable도 메모리상에서 삭제될 수 있기 때문에 이는 매우 위험하다고 볼 수 있다.

Static Final Variable

static 이면서 final 인 변수

public class Math{
	public static final double PI = 3.14159265358979323846;
}

- System.out 은 final variable이다.

public class System{
	public static final PrintStream out;
}

Static Method

클래스에 속해 있는 메소드. 해당 메소드를 호출하기 위햇 인스턴스를 생성할 필요가 없음.

대표 예시)
Math.pow(2,5);

Static Variable ans Static Method

위에서 static variable 은 instance method에서 호출하면 안된다고 하였다. 왜냐하면 언제 에러가 발생할지 알 수가 없기 때문이다.

반대로 static method에서는 static variable을 호출하여도 된다.
또한 static method에서 static variable을 호출한다면 this 키우드를 사용하지 않아도 된다. 왜냐하면 this는 객체가 자기자신을 호출하는 것인데 static은 객체가 없기 때문이다.

class Employee{
    private static int lastId=0; //static variable
    private int id; //instance variable
    public Employee() { id = ++lastId; }
	public int getId() { return this.id; }
	public static int getLastId() { return tlastId; } //이와 같이 실행하면 된다.
}


이는 위에서 설명한 바와 동일한 garbage collector(gc) 때문이다.


Java : Call-by-Value

자바에서는 call-by-value를 사용한다.

동적할당이 아닌 단지 값만 삽입했다면 함수를 사용할 경우 값이 바꾸지 않는다.

public class Lecture{
	public static void swap(int a,int b){
		int temp = a;
        a=b;
        b=temp;
	}
    public static void main(String[] args){
		int a1=10;
        int a2=20;
        swap(a1,a2);
        System.out.println(a1+" "+a2);
	}
}

이경우에는 a1과 a2의 값은 바뀌지 않는다.

하지만 동적할당을 하는 뱅열은 경우가 달라진다.

public class Lecture{
	public static void swap(int []x){
		int temp = x[0];
        x[1] = x[0];
        x[0] = temp;
	}
    public static void main(String[] args){
		int [] a = new int[2];
        x[0]=10;
        x[1]=20;
        swap(x);
        System.out.println(x[0]+" "+x[1]);
	}
}

이것의 결과물은 20,10 으로 삽입된 값이 달라지게 된다.


이는 동적할당된 메모리를 참고하엿 생기어난 결과물이다.

간단하게 말해서 동적할당, new를 사용했다면 인자로 값을 넘겨준다면 값이 바뀌게 된다.


하지만 자바에는 이런 연산조차 call-by-value라고 부른다. 다 말하는게 다르기는 하지만 가장 대표되는 의견은 결국 주소를 가르키는 변수가 가르키는 주소가 바뀐게 아니지 않느냐 이기 때문에 call-by-value를 주장하는 경우가 더 많다고 한다... 흠... 또다른 의견으로는 call-by-reference와의 구분은 중요치 않다고도 한다...

class Employee{
	String name;
	public Employee(String name) {
		this.name= name;
	}
}

public class Ex08_04 {
	public static void changeName(Employee e,String newName) {
		e.name=newName;
	}
	public static void setName(String oldName,String newName) {
		oldName=newName;
	}
	public static void main(String[] args) {
		Employee m = new Employee("Peter");
		System.out.println(m.name);
		changeName(m, "John");
		System.out.println(m.name); 
		setName(m.name, "James"); // 바뀌지 않는다.
		System.out.println(m.name);
	}
}


또다른 예제로 객체 역시 객체 자체를 넘기어 주어야지 인자를 넘기어 주는 것으로는 바뀌지 않는다.

함수

추가적으로 java는 함수 호출방식이 매우 특이한데



public class Ex08_03 {
	public void swap(int a,int b) {
		int temp = a;
		a= b;
		b=temp;
	}
	
	public static void swap(int[] x) { 	
		int temp=x[0];
		x[0]=x[1];
		x[1]=temp;
	}
	public static void main(String[] args) {
		int x=10;
		int y=20;
		swap(x,y);
		System.out.println(x+" "+y);
		
		int[] a=new int[2];
		a[0]=10;
		a[1]=20;
		swap(a);
		System.out.println(a[0]+" "+a[1]);
	}
}

현재 첫번쨰 swap에는 static이 안붙은 것을 확인할 수 있고 실재로도 이 코드는 실행이 안된다. 이 이유는 main함수가 public static이기 때문에 발생하는 문제인데 static 함수는 반드시 static함수만을 호출할 수 있기 때문에 함수를 정의하고 사용하려면 함수 앞에 반드시 public static을 붙이어야만한다. 하다못해 private static이라도...

profile
신촌거지출신개발자(시리즈 부분에 목차가 나옵니다.)

0개의 댓글