클래스에서의 변수선언 : 전역변수
메소드에서의 변수선언 : 지역변수
클래스에서의 변수
변수의 종류
클래스에서의 변수는 아래와 같이 구분한다.
- 1. 클래스 변수 : static 키워드를 가지고 필드에 선언하는 변수, 메모리의 static영역 사용
- 2. 멤버 변수(인스턴스 변수) : static 키워드 없이 필드에 선언하는 변수, 메모리의 heap영역 사용
- 3. 지역 변수 : 메소드, 생성자, 초기화 블록 내부에서 선언하는 변수
- 더이상 참조하지 않는경우 가비지 콜렉터(GC)가 변수를 지워준다.
class KindsOfVariable
public class KindsOgVariable {
/* 클래스 영역에 작성하는 변수를 필드라고 한다. */
/* 필드
* == 멤버변수 (클래스가 가지는 멤버라는 의미)
* == 전역변수(클래스 전역에서 아용할 수 있는 변수라는 의미)
*
* */
/* non-static field를 인스턴스 변수라고 한다.
* (인스턴스 생성 시점에 사용가능한 변수라는 의미) */
private int globalNum;
/* static field 를 정적필드(클래스변수)라고 한다.
* (정적 영역에 생성되는 변수라는 의미)
* */
private static int staticNum;
public void testMethod(int num) { // 메소드 영역의 시작
/* 메소드 영역에서 작성하는 변수를 지역변수라고 한다.
* 메소드 괄호 안에 선언하는 변수를 매개변수라고 한다.
* 매개변수도 일종의 지역변수이다.
* 지역변수와 매개변수 모두 메소드 호출 시 stack을 할당받아 stack에 생성된다.
* 호출이 종료되면 할당되었던 공간은 사라진다.
* */
int localNum;
/* 매개변수는 호출시 값이 넘어와서 변경되기 때문에 초기화가 필요없다.
* 그러나 지역변수는 선언외에 다시 사용하기 위해서는 반드시 초기화가 되어야 한다. */
System.out.println(num);
// System.out.println(localNum); // 컴파일 에러가 생긴다.
// he local variable localNum may not have been initialized
// 초기화 되지않아서 오류
// heap영역에 생성된 변수들은 알아서 초기값으로 들어가지만
// stack영역의 생성된 지역변수들은 반드시 선언과 동시에 초기화를 해주어야 한다.
System.out.println(globalNum);
System.out.println(staticNum);
// 전역 변수(모든영역)
// 전역 변수는 클래스 전역에서 사용가능하다.
} //메소드 영역의 끝
public void testMethod2() {
//System.out.println(localNum); //testMethod 내의 지역변수
System.out.println(globalNum);
System.out.println(staticNum);
// 지역변수는 해당지역 내에서만 사용가능하다. 지역을 벗어난다면 컴파일 오류
// 번역 변수는 다른 메소드에서도 사용 가능하다.
}
} // 클래스 영역의 끝
class KindsOfVariable
초기화 순서
- 인스턴스(non-static) 스태틱 키워드가 안붙어있음
- 클래스변수(static) 스태틱 키워드가 붙음
private int num = 10;
private static int num2 = 20;
클래스 변수의 경우 초기값 외의 정적 초기화, 인스턴스 초기화, 생성자를 생성하게 된다면 그 위에 값을 덮어쓰는 형태가 된다.
Application
public class Application {
public static void main(String[] args) {
/* 초기화 블럭과 초기화 순서 */
/* 초기화 블럭
* 복잡한 초기화를 수행할 수 있는 블럭을 제공하며,
* 인스턴스 초기화 블럭과 정적초기화 블럭으로 구분된다.
*
* 1. 인스턴스 초기화 블럭
* : 인스턴스가 생성되는 시점에 생성자 호출 이전에 먼저 실행이 된다.
* 인스턴스를 호출하는 시점마다 호출이 된다.
* 인스턴스 변수를 초기화하며 정적 필드에는 실행 시점마다 값을 덮어쓴다.
*
* {
* 초기화 내용 작성
* }
*
* 2. 정적 초기화 블럭
* : 클래스가 로드 될 때마다 한번 동작한다.
* 정적 필드를 초기화하며, 인스턴스 변수는 초기화 하지 못한다.
*
* static {
* 초기화 내용 작성
* }
*
*
*
* */
Product product = new Product(); // 없으므로 마우스오버하여 클래스 생성
System.out.println(product.getInfomation());
// 정적 초기화 블록 동작함...
// 인스턴스 초기화 블록 동작함...
// 기본 생성자 호출함...
// Product [name=사이언, price=900000, brand=헬지]
Product product2 = new Product("대륙폰", 300000, "샤우미");
System.out.println(product2.getInfomation());
// 인스턴스 초기화 블록 동작함...
// 매개변수 있는 생성자 호출됨...
// Product [name=대륙폰, price=300000, brand=샤우미]
}
}
class Product
public class Product {
/* 필드를 초기화 하지않으면 jvm이 정한 기본 값으로 객체가 생성된다. */
// private String name;
// private int price;
// private static String brand;
/* 명시적인 초기화가 동작함, 기본값을 초기화가 덮어씀 */
private String name = "갤럭시";
private int price = 1000000;
private static String brand = "삼송";
// 기본 생성자 호출함...
// Product [name=갤럭시, price=1000000, brand=삼송]
/* 인스턴스 초기화 블록 */
{
name = "사이언";
price = 900000; // 인스턴스 변수
/* 인스턴스 초기화 블록에서는 static 필드를 초기화 할 수 있는 것처럼 보인다.
* 하지만 static 초기화 블록은 클래스가 로드 될 떄 이미 초기화를 진행했다. = 헬지
* 따라서 인스턴스 초기화 블럭이 동작하는 시점에는 이미 초기화가 진행 된 정적 필드에 = 샘송
* 인스턴스 초기화 블럭에서 대입한 값으로 덮어쓰게 되는 것이다. */
brand ="사과"; //클래스 변수
System.out.println("인스턴스 초기화 블록 동작함...");
}
/* static 초기화 블록 */
static {
/* static 초기화 블럭에서는 non-static 필드를 초기화 하지 못한다.
* 정적 초기화 블럭은 클래스 로드시에 동작한다.
* 따라서 정적 초기화 블럭의 동작 시점에는 인스턴스가 아무것도 존재할 수 없기 때문에,
* 존재하지 않는 인스턴스 변수에 초기화 하는 것은 시기상으로 불가능하다.
*
*/
// name = "아이뽕";
// price = 1000000;
// Cannot make a static reference to the non-static field name
brand = "헬지";
System.out.println("정적 초기화 블록 동작함...");
// 왜 static 영역에서 name과 price를 초기화 할 수 없을까?
// 인스턴스 변수는 객체가 만들어져서 heap영역에 메모리가 할당 됐을때 존재
// 인스턴스가 생성된 적이 없으므로 초기화 자체가 불가능하다.
}
/* 실행 순서 확인 */
// 정적 초기화 블록 동작함...
// 인스턴스 초기화 블록 동작함...
// 기본 생성자 호출함...
// Product [name=사이언, price=900000, brand=사과]
public Product() {
System.out.println("기본 생성자 호출함...");
}
public Product(String name, int price, String brand) {
this.name = name;
this.price = price;
Product.brand = brand;
System.out.println("매개변수 있는 생성자 호출됨...");
// 인스턴스 초기화 블록 동작함...
// 매개변수 있는 생성자 호출됨...
// Product [name=대륙폰, price=300000, brand=샤우미]
}
public String getInfomation() {
return "Product [name=" + this.name + ", price=" + this.price + ", brand=" + Product.brand + "]";
}
}
객체배열
객체배열이란?
- 레퍼런스 변수(주소값이 담김)에 대한 배열
- 동일한 타입의 여러 인스턴스들을 배열로 관리할 수 있다.
1. 선언
클래스명[ ] 배열명;
클래스명 배열명[ ];
2. 할당
배열명 = new 클래스명[배열크기];
(new 연산자를 써야지만 힙 영역에 할당)
3. 선언과 동시에 할당
클래스명 배열명[ ] = new 클래스명[배열크기]
- 힙 영역에 객체를 참조할 변수만 생성이 된 상태이다.
- 즉, 해당객체가 만들어진게 아니라 그 객체를 모아서 참조할 수 있는 참조변수가 만들어진 상태
객체배열 선언과 할당
인덱스를 이용한 초기화
배열명[ i ] = new 클래스명( );
선언과 동시에 할당 및 초기화
클래스명 배열명[ ] = {new 클래스명(), new 클래스명()};
객체배열 저장구조
Example arr[ ] = new Example[2];
arr[0] = new Example( ); //0x678 주소값 참조
arr[1] = new Example( ); //0x098 주소값 참조
class Application
public class Application {
public static void main(String[] args) {
/* 객체배열은 레퍼런스 변수에 대한 배열이다.
* 생성한 인스턴스도 배열을 이용해서 관리하면
* 동일한 타입의 여러개 인스턴스를 각각 취급하지 않고 연속 처리할 수 있어서 유용하다.
* 또한 반환값은 1개의 값만 반환할 수 있기 때문에
* 동일한 타입의 여러 인스턴스를 반환해야 하는 경우 객체배열을 이용할 수 있다. */
/* 자동차 5대 인스턴스를 생성 후 모든 인스턴스가 최고 속도로 달리게 한다. */
Car car1 = new Car("페라리", 300);
Car car2 = new Car("람보르기니", 350);
Car car3 = new Car("롤스로이스", 250);
Car car4 = new Car("부가티베이론", 400);
Car car5 = new Car("포터", 500);
car1.driveMaxSpeed();
car2.driveMaxSpeed();
car3.driveMaxSpeed();
car4.driveMaxSpeed();
car5.driveMaxSpeed();
/* 동일한 타입의 인스턴스를 여러 개 사용해야 할 때 객체배열을 이용하면
* 보다 효율적으로 사용이 가능하다.
* Car 타입의 인스턴스 주소를 보관할 5칸 짜리 배열 할당 */
Car[] carArray = new Car[5];
System.out.println(carArray);
System.out.println(carArray[0]);
// carArray[0]객체의 주소 : [Lcom.greedy.section01.init.Car;@3830f1c0
// 인덱스 0의 값 : null
/* 각 인덱스에는 기본값 null로 초기화 되어 있기 때문에
* 인덱스별로 인스턴스를 생성해야 한다. */
carArray[0] = new Car("페라리", 300);
carArray[1] = new Car("람보르기니", 350);
carArray[2] = new Car("롤스로이스", 250);
carArray[3] = new Car("부가티베이론", 400);
carArray[4] = new Car("포터", 450);
/* 배열이기 때문에 반복문을 활용할 수 있다. */
for( int i = 0; i <carArray.length; i++ ) {
carArray[i].driveMaxSpeed();
}
/*
페라리(이)가 최고시속 300km/h로 달려갑니다.
람보르기니(이)가 최고시속 350km/h로 달려갑니다.
롤스로이스(이)가 최고시속 250km/h로 달려갑니다.
부가티베이론(이)가 최고시속 400km/h로 달려갑니다.
포터(이)가 최고시속 450km/h로 달려갑니다. */
}
/* 객체 배열도 할당과 동시에 초기화 할 수 있다. */
Car[] carArray2 = {
new Car("페라리", 300)
, new Car("람보르기니", 350)
, new Car("롤스로이스", 250)
, new Car("부가티베이론", 400)
, new Car("포터", 500)
};
{
/* 향상된 for문으로도 사용이 가능하다.
* for ( 타입과 변수명 : 배열 ) */
for(Car c:carArray2) {
c.driveMaxSpeed();
}
}
}
class Car
public class Car {
private String modelName;
private int maxSpeed;
/* 매개변수 생성자 정의 */
public Car (String modelName, int maxSpeed) {
this.modelName = modelName;
this.maxSpeed = maxSpeed;
}
/* 기능 */
public void driveMaxSpeed() {
System.out.println(modelName +"(이)가 최고시속 " + maxSpeed + "km/h로 달려갑니다.");
}
}
추가 예제
Application
import java.util.Scanner;
public class Application {
public static void main(String[] args) {
/* 동일한 타입의 여러개의 인스턴스를 인자로 전달하거나
* 리턴 받는 경우에도 객체 배열을 이용할 수 있다. */
/* DTO를 이용한 간단한 회원관리용 프로그램 */
/*
* 구현기능
* 1. 여러명의 회원 정보를 받아 한번에 여러 회원 정보를 등록
* 2. 전체 회원 조회 시 여러명의 회원정보를 반환
*
* */
Scanner sc = new Scanner(System.in);
MemberManager memberManager = new MemberManager();
// 없으므로 생성
menu :
while(true) {
System.out.println("==========회원관리 프로그램==========");
System.out.println("1. 회원등록");
System.out.println("2. 회원 전체 조회");
System.out.println("9. 프로그램 종료");
System.out.print("메뉴 선택 : ");
int no = sc.nextInt();
switch(no) {
case 1 : memberManager.signUpMembers(); break;
case 2 : memberManager.printAllMembers(); break;
case 9 : System.out.println("프로그램을 종료합니다."); break menu;
default : System.out.println("잘못 된 번호를 입력하셨습니다."); break;
}
}
}
}
//==========회원관리 프로그램==========
//1. 회원등록
//2. 회원 전체 조회
//9. 프로그램 종료
//메뉴 선택 : 1
//회원을 등록합니다.
//김영희님은 회원 등록에 성공했습니다.
//홍길동님은 회원 등록에 성공했습니다.
//박진희님은 회원 등록에 성공했습니다.
//이순신님은 회원 등록에 성공했습니다.
//한지희님은 회원 등록에 성공했습니다.
//
//김영희님은 회원 등록에 성공했습니다.
//홍길동님은 회원 등록에 성공했습니다.
//박진희님은 회원 등록에 성공했습니다.
//이순신님은 회원 등록에 성공했습니다.
//한지희님은 회원 등록에 성공했습니다.
//총 5명의 회원 등록에 성공했습니다.
//==========회원관리 프로그램==========
//1. 회원등록
//2. 회원 전체 조회
//9. 프로그램 종료
//메뉴 선택 : 2
//==========가입된 회원 목록==========
//MeberDTO [num=1, id =user01, pwd =pass01, name =김영희, age =20, gender =여]
//MeberDTO [num=2, id =user02, pwd =pass02, name =홍길동, age =22, gender =남]
//MeberDTO [num=3, id =user03, pwd =pass03, name =박진희, age =24, gender =여]
//MeberDTO [num=4, id =user04, pwd =pass04, name =이순신, age =26, gender =남]
//MeberDTO [num=5, id =user05, pwd =pass05, name =한지희, age =28, gender =여]
//MeberDTO [num=1, id =user01, pwd =pass01, name =김영희, age =20, gender =여]
//MeberDTO [num=2, id =user02, pwd =pass02, name =홍길동, age =22, gender =남]
//MeberDTO [num=3, id =user03, pwd =pass03, name =박진희, age =24, gender =여]
//MeberDTO [num=4, id =user04, pwd =pass04, name =이순신, age =26, gender =남]
//MeberDTO [num=5, id =user05, pwd =pass05, name =한지희, age =28, gender =여]
//====================
//총 5명의 회원이 가입되어 있습니다.
//==========회원관리 프로그램==========
//1. 회원등록
//2. 회원 전체 조회
//9. 프로그램 종료
//메뉴 선택 : 4
//잘못 된 번호를 입력하셨습니다.
//==========회원관리 프로그램==========
//1. 회원등록
//2. 회원 전체 조회
//9. 프로그램 종료
//메뉴 선택 : 9
//프로그램을 종료합니다.
class MemberDTO
public class MemberDTO {
/* 관리할 회원정보를 추상화해서 필드 작성 */
private int num;
private String id;
private String pwd;
private String name;
private int age;
private char gender;
/* 아무것도 체크하지않으면 기본생성자 */
public MemberDTO() {
super();
}
/* 마우스 우클릭 - source - Generate Constructor using Fields */
/* 모든 필드를 초기화하는 생성자 */
public MemberDTO(int num, String id, String pwd, String name, int age, char gender) {
super();
this.num = num;
this.id = id;
this.pwd = pwd;
this.name = name;
this.age = age;
this.gender = gender;
}
/* 마우스 우클릭 - source - Generate Getter and Setter */
/* 게터세터 생성 */
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
/* 모든 필드값을 문자열로 반환 */
public String getInformation() {
return "MeberDTO [num=" + num + ", id =" + id + ", pwd =" + pwd + ", name =" + name +
", age =" + age + ", gender =" + gender + "]";
}
}
class MemberInsertManager
public class MemberInsertManager {
/** <pre>
* 여러명의 회원 정보를 한 번에 등록할 수 있는 기능 제공
* </pre>
* @param members 회원 정보를 객체배열 형태로 전달
* */
public void insert(MemberDTO[] members) {
System.out.println("회원을 등록합니다.");
/* 일반 for문 */
for (int i = 0; i < members.length; i++) {
System.out.println(members[i].getName() + "님은 회원 등록에 성공했습니다.");
}
System.out.println();
/* 향상된 for문 */
/* 타입과 변수:멤버의 이름 */
for (MemberDTO member:members) {
System.out.println(member.getName() + "님은 회원 등록에 성공했습니다.");
}
System.out.println("총 " + members.length + "명의 회원 등록에 성공했습니다.");
}
}
class MemberManager
public class MemberManager {
/** <pre>
* 여러 명의 회원 정보를 등록
* </pre>
* */
public void signUpMembers() {
/* 5명의 회원 정보를 담을 객체배열 생성 */
MemberDTO[] members = new MemberDTO[5];
/* 5명의 회원정보를 각 인덱스에 할당 */
members[0] = new MemberDTO(1, "user01", "pass01", "김영희", 20, '여');
members[1] = new MemberDTO(2, "user02", "pass02", "홍길동", 22, '남');
members[2] = new MemberDTO(3, "user03", "pass03", "박진희", 24, '여');
members[3] = new MemberDTO(4, "user04", "pass04", "이순신", 26, '남');
members[4] = new MemberDTO(5, "user05", "pass05", "한지희", 28, '여');
/* 회원 정보를 입/출력할 용도의 MemberInsertManager 작성 */
MemberInsertManager memberInsertManager = new MemberInsertManager();
// 없으므로 생성
memberInsertManager.insert(members);
//memberDTO 5개의 참조변수에 대한 주소값을 인자로 전달
}
/** <pre>
* 모든 회원 목록을 조회하여 정보를 출력
* </pre>
* */
public void printAllMembers() {
/* MemberSelectManager 클래스 작성 */
/* 작성한 메소드를 호출하고 반환받은 값을 객체배열 레퍼런스 변수에 저장한다. */
MemberDTO[] selectedMembers = new MemberSelectManager().selectAllMembers();
/* 가입되어 있는 회원 목록을 출력한다. */
System.out.println("==========가입된 회원 목록==========");
for (int i = 0; i < selectedMembers.length; i++) {
System.out.println(selectedMembers[i].getInformation());
}
for (MemberDTO member : selectedMembers) {
System.out.println(member.getInformation());
}
System.out.println("====================");
System.out.println("총 " + selectedMembers.length + "명의 회원이 가입되어 있습니다.");
}
/* 클래스를 여러개 작성하는 이유: 클래스는 하나의 기능, 책임만을 가지고 있어야 함 */
/* 인자로 전달하는 테스트, 리턴받은 테스트를 하기 위함이었다. */
}
class MemberSelectManager
public class MemberSelectManager {
/** <pre>
* 회원 정보 전체를 반환하는 메소드
* </pre>
* @return 전체 회원 정보 객체 배열로 반환
*
* */
public MemberDTO[] selectAllMembers() {
/* MemberDTO배열을 리턴하는 메소드 */
return new MemberDTO[] {
new MemberDTO(1, "user01", "pass01", "김영희", 20, '여')
, new MemberDTO(2, "user02", "pass02", "홍길동", 22, '남')
, new MemberDTO(3, "user03", "pass03", "박진희", 24, '여')
, new MemberDTO(4, "user04", "pass04", "이순신", 26, '남')
, new MemberDTO(5, "user05", "pass05", "한지희", 28, '여')
};
}
}
'Programming > JAVA' 카테고리의 다른 글
다형성 (0) | 2022.01.05 |
---|---|
상속 (0) | 2022.01.04 |
클래스와 객체(3) (0) | 2021.12.30 |
클래스와 객체(2) (0) | 2021.12.29 |
배열, 클래스와 객체 (0) | 2021.12.28 |