본문 바로가기
국비 교육/백엔드(Java, Spring)

[자바] this, Static 지정자, 객체 배열

by 육츠 2024. 1. 24.
Contents 접기

this 와 this()

this this()
- 현재 객체
- 자기 자신을 가리키는 참조 변수
- 현재 객체 생성자
- 같은 클래스의 다른 생성자를 호출한다.

 

가장 잘 보여줄 수 있는 예제 코드

public class Coworker {
    private String name;
    private String department;
    private String job;
    public Coworker() {
        this("모모", "전산팀", "사원");
    }

    public Coworker(String name, String department, String job) {
         this.name = name;
         this.department = department;
         this.job = job;
    }

    public void output() {
         System.out.println("이름: " + name + ", 부서: " + department + ", 직위: " + job);
    }

    public static void main(String[] args) {
        Coworker c1 = new Coworker();
        c1.output();
        Coworker c2 = new Coworker("전우치", "경영정보팀","대리");
        c2.output();
    }
}

 

Static

하나의 파일 안에 클래스 두 개 가능. 하지만 public은 가질 수 없다.
저장을 하면 .java 는 하나지만 class 는 두 개 저장이 된다. ==> Test 용도가 아니라면 비추!

class Sample{
	public int s1; // static이 아니기 때문에 무조건 생성 해야함
	public static int s2; // 전체에서 변수가  s2 인건 하나만 생성 한다.
	
	
} // Test용도가 아니라면 비추!



public class StaticTest01 {
	// main 을 가지고 파일명이 같은 클래스 이름만이 public 을 가진다
	
	
	public static void main(String[] args) {
		// Sample.s2 =1; // 공용으로 접근 가능
		Sample.s2 +=1; // 1
		System.out.println(Sample.s2); 
		// 이름만으로 접근은 안됨
		
		
		Sample temp = new Sample();
		Sample temp2 = new Sample();  // new를 할때마다 새롭게 만들어짐
		
		temp.s1 += 1; 
		System.out.println(temp.s1); //0
코드 의미
public int s1; static이 아니기 때문에 무조건 객체 생성 해야한다.
public static int s2; 

public static void main(String[] args) {
Sample.s2 =1;
전체에서 변수가  s2 인건 하나만 생성 한다.


공용으로 접근 가능하다.
Sample temp = new Sample();
Sample temp2 = new Sample();  
new를 할때마다 새롭게 만들어진다.
		Sample.s2 += 1; // 2  : 이미 누적된 1의 값을 가지고 있기 때문에 2가 된다
		System.out.println(Sample.s2); 
		// 이름만으로 접근은 안됨
		
		
		temp = new Sample(); // 기존은 버리고 메모리에서 완전히 다시 만든다
		temp.s1 += 1; 
		System.out.println(temp.s1); //0
    }
    
}
코드 의미
Sample.s2 += 1; 2
이미 누적된 1의 값을 가지고 있기 때문에 2가 되는 것이다.
temp = new Sample(); 기존은 버리고 메모리에서 완전히 다시 만든다.
temp.s1 += 1; 해도 계속 1이 된다.

 

// class Smaple // 이미 만들었기 때문에 안됨
class Test{
	
	static final int DATA = 12; // 반드시 값을 초기화 해야함 // 상수
	
	private static double value; // 초기화 하는 곳은??
	// 생성자 ==> 인스턴스 변수를 생성하고 초기화 하는 것이 목적이다.   ==> 위와 같은 클래스 생성은 맞지 않다?
	
	// static 초기화 블럭?  => static 변수를 초기화 하는 
	static {
		value = 55;
	}
	
	// 인스턴스 변수 없기 때문에 생성자가 필요 없다.
	private Test() { }     // 굳이 생성하지 않도록 private으로 만들어 놓는다.
	
	/*
	public static void output() {
		System.out.println(DATA + " , " + value);
	}
	*/
	
	// 오류가 안나는 이유는? 
	// non-static 은 static 에 접근 할 수 있다.
	public void output() {
		System.out.println(DATA + " , " + value);
	}
	
}
public class StaticTest02 {
	private int a = 10;

	public static void main(String[] args) {
		System.out.println(Test.DATA); // 사용
		
		// System.out.println(a); // non-static에 접근 불가 (static 은 non-static 에 접근할 수 없다.)
		
		//Test.output(); // static이 존재하기 때문에 가능
		// static이 없다면 객체 생성하고 사용
		
		// Test t = new Test();
		// private 으로 기본 생성자를 만들었기 때문에 안되는 것.
		
	}

}

생성자 = 인스턴스 변수를 생성하고 초기화 하는 것이 목적  ==> 아래 코드와 같은 멤버변수 생성은 맞지 않다.
private static double value; 를 초기화 하는 곳은? ===> static 초기화 블럭 

코드 의미
static {
    value = 55;
}
static 초기화 블럭 -> static 변수를 초기화 하는 
코드 의미
private Test() { }  

 Test t = new Test();
// private 으로 기본 생성자를 만들었기 때문에 안되는 것이다.
인스턴스 변수 없기 때문에 생성자가 필요 없다.

-> 굳이 생성하지 않도록 private으로 만들어 놓는다.
코드 의미
public static void output() {
    System.out.println(DATA + " , " + value);
}

public class StaticTest02 {
    public static void main(String[] args) {
        Test.output(); 
static이 존재하기 때문에 가능하다.
(static이 없다면 객체 생성하고 사용해야 함)
class Test{
public void output() {
    System.out.println(DATA + " , " + value);
}
Class Test 안에서 오류가 안나는 이유는 non-static 은 static 에 접근 할 수 있기 때문이다. 
public class StaticTest02 {
    private int a = 10;
    public static void main(String[] args) {
        System.out.println(a);
main 에서 오류가 나는 이유는 non-static에 접근 불가 
(static 은 non-static 에 접근할 수 없다.)

 

객체 배열

class Person{
	private String name;
	private int age;
	
	public Person() { }
	
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public int getAge() {
		return age;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	public void output() {
		System.out.println(name + " : " + age);
	}
	
}
public class ObjectArrayTest01 {

	public static void main(String[] args) {
		
		Person p = new Person("홍길동", 25); // 단일 객체 생성
		
		// p.output();
		// 홍길동 : 25
		
		Person[] pary = new Person[5];
		// 객체 생성이 아닌 '배열 생성'
		// 방이 5개인 배열이 생성 ( Person 타입의 데이터가 저장)

		int size = 0; // 객체가 몇 번 방까지 들어있는지 기억하는 변수
		// Person 타입에서는 사이즈가 0 ~ 4 까지
		
		pary[0] = new Person("전우치", 30); ++size;
		
		// ㅁ -> ㅁㅁㅁㅁㅁ
		//        0: 전(위치값) 나머지: null
		

		// pary[1] = new Person("임꺽정", 32); ++size;
		pary[size] = new Person("임꺽정", 32); ++size; // ==> 좀 더 편하다!?
		
		pary[size] = new Person("홍길동", 25); ++size; 
		
		// 맞는 출력은?
		for(int i = 0; i < size; ++i)
			pary[i].output();
		
		/*
		 * null을 만나면 오류가 나기 때문에 맞는 출력이 아님
		for(Person tmp : pary) {
			tmp.output(); 
		} */
코드 의미
Person[] pary = new Person[5]; 배열 생성
방이 5개인 배열이 생성 ( Person 타입의 데이터가 저장)
pary[0] = new Person("전우치", 30); 직접 대입
ㅁ -> ㅁㅁㅁㅁㅁ
0: 전(위치값) 나머지: null 로 되어 있다.
for(Person tmp : pary) {
    tmp.output(); 
}
전체를 조회하며 출력하는 코드.
=> null 이 있으면 NullPointException 오류가 난다.
// 맞는 출력은
for(int i = 0; i < size; ++i)
    pary[i].output();
size 변수 필요.
size 까지만 출력을 하게 되므로 NullPointException 오류가 나지 않는다.
int size = 0; 객체가 몇 번 방까지 들어있는지 기억하는 변수
// Person 타입에서 사이즈 = 0 ~ 4 
pary[size] = new Person("임꺽정", 32); ++size;  size 를 사용하여 대입한다. 

 

특정 데이터를 삭제 할 때는?

뒤에 있는 데이터를 하나씩 앞으로 이동시켜야 한다.
마지막 자리에는 null 도 가능하지만 size-1 하는 방법도 있다.

[예시] 전우치 탈퇴

1. 전우치가 몇 번방 사람인가?   10번
2. 11번 -> 10번, 12번-> 11번,..... 마지막 = --size;
3. for문으로 처리

전우치의 위치값을 알고 있다는 전제하에 배열 옮기는 작업

   		int searchIndex = 0;

		for(int i = searchIndex; i < size ; ++i) {
			pary[i] = pary[i+1];  
		}	
		// 옮기는 작업 
		--size;
		
		for(int i = 0; i < size; ++i)
			pary[i].output();
		
	}

}

 

저팔계의 위치를 모르고 한다면?

		int searchIndex = -1; 

		for(int i = 0 ; i < size; i++) {
			if(pary[i].getName().equals("저팔계")) {
				searchIndex = i;
				break;
			}
		}
        
		System.out.println("저팔계의 위치값: " + searchIndex);
		
		// 옮기는 작업 
		if (searchIndex != -1) {
			for(int i = searchIndex; i < size -1 ; ++i) {
				pary[i] = pary[i+1];  // 오류가 난다.
			}	
		--size;
		} else {
			System.out.println("해당 회원 존재하지 않습니다.");
		}
		

		for(int i = 0; i < size; ++i)
			pary[i].output();

	}

}
원래 코드 바뀐 코드
int searchIndex = 0;  int searchIndex = -1; 
해당 사람을 찾지 못했는데 0번에 존재한 사람이 지워질 수 있기 때문이다.
for(int i = searchIndex; i < size; ++i) {
    pary[i] = pary[i+1]; 
}
--size;
for(int i = searchIndex; i < size -1 ; ++i) {
    pary[i] = pary[i+1];  
}
--size;
배열 밖의 데이터를 가져오려 해서 오류가 나기 때문에 for문의 범위를 size 에서 size - 1 까지로 변경해준다.