[JAVA+국비교육] static, this, 변수 초기화 방법, Overloading, 생성자
by 무작정 개발2021.12.30(8일 차)
벌써 2021년 연말이다. 벌써 26살이 코앞이라니... 날씨도 점점 추워진다. 20명 정도로 시작해 현재는 15명이 대면 수업을 듣고 나머지는 비대면 수업을 듣는다. 몇몇 사람들과는 친해졌고, 대부분의 사람들과 이야기를 나눠보았다.
전공자도 있고, 비전공자인데 수업을 듣기 전에 미리 공부를 해온 사람 등 다양한 사람이 있었다.
올해는 후회가 많은 2021년이었는데 2022년엔 꼭 후회 없는 해를 보내야겠다.
오늘의 수업 내용
static
static 예약어는 멤버 메서드나 멤버 변수(인스턴스 변수)에 정의할 수 있으며 지역 변수나 클래스에게는 정의할 수없다.
멤버 메서드나 멤버 변수에 static이라는 예약어를 정의하면 static 메서드(클래스 메서드)와 static 변수(클래스 변수)라고
불리게 된다.
why?
멤버 변수나 멤버 메서드들은 해당 객체가 생성될 때 객체가 생성된 메모리 공간에 같이 존재하게 되지만 static으로
선언된 메서드(멤버 함수)나 변수들은 static 영역(메서드 영역)이라는 곳에 유일하게 만들어지면서 모든 객체(Object)들이 사용할 수 있도록 공유 개념을 가지기 때문이다.
static 변수 (클래스 변수)
여러 개의 객체가 생성될 때 단 하나만 생성되며 모든 객체들이 공유(같은 메모리)하는 개념으로 사용되는 변수
package com.day7;
public class Data {
static String name = "아이유"; // static 변수이므로 이미 메모리 할당되어 있다.
static int age = 27;
public static void getInstance() {
System.out.println(name + "의 나이는 " + age + "살 입니다.");
}
}
package com.day7;
import java.util.Calendar;
public class Test3 {
public static void main(String[] args) {
//Data ob = new Data();
//ob.print();
//Data클래스.getInstance메서드
Data.getInstance(); // 클래스이름.메소드명
//Calendar now = Calendar.getInstance();
}
}
Date와 Test 3을 실행시킨 결과이다. Test 3에서 Data.getInstance(); // 클래스 이름. 메서드명 여기를 보자.
Date 클래스에 있는 getInstance 메서드를 호출해서 위의 결과가 나오는 것이다.
전역 변수는 반드시 메모리를 다른 곳에 저장하고 메서드만 동일 주소로 사용함을 볼 수 있는 예제
//하나의 파일에 2개이상의 public클래스를 만들면 오류뜸. 그래서 public 클래스는 1개만 생성 가능.
//main절이 있는 클래스에만 public가 들어가고 나머지 클래스에는 class만 정의
class SubClass { //int값 2개를 저장할 수 있는 클래스.
int a, b; //instance변수(전역변수)
}
public class Test1 {
public static void main(String[] args) {
SubClass ob1 = new SubClass(); // new로 객체를 생성한 전역변수는 초기값이 들어있다.
SubClass ob2 = new SubClass();
// 인스턴스변수는 반드시 메모리를 다른곳에 저장
System.out.println("ob1.a: " + ob1.a); //0
System.out.println("ob1.b: " + ob1.b); //0
ob1.a = 10;
ob1.b = 20;
System.out.println("ob1.a: " + ob1.a); //10
System.out.println("ob1.b: " + ob1.b); //20
System.out.println("ob2.a: " + ob2.a); //0
System.out.println("ob2.b: " + ob2.b); //0
ob2.a = 100;
ob2.b = 200;
System.out.println("ob2.a: " + ob2.a); //100
System.out.println("ob2.b: " + ob2.b); //200
System.out.println("ob1.a: " + ob1.a); //10
System.out.println("ob1.b: " + ob1.b); //20
// 메모리공간은 모두 각자 따로 쓴다.
}
}
this
전역변수 r, 지역변수 r처럼 이름이 동일하면 구분하지 못하기에 전역 변수로 인식하기 위해 this 사용.
package com.day7;
// this : 클래스이름(ME)
//클래스 이름인데 클래스 안에 같은 클래스를 입력하면 헷갈려서 this로 표현
class Circle { // Circle 클래스
private int r; // 인스턴스변수(맴버변수) - 정보의 은닉화(캡슐화)
// 값을 변경할 수 있으니 외부에서 접근하지 못하게 접근 지정자 지정
//초기화 메서드. 매개변수 이용
public void setDate(int r) { //setData(int r, Circle this)내부적으로 이렇게 처리
//우회도로
this.r =r; // 전역변수r, 지역변수r, 처럼 이름이 동일하면 java가 구분하지 못함. 전역변수로 인식하기 위해 this 사용.
// this는 me와 같다(클래스이름의 대명사)
// Circle를 this로 바꾼 것이다.(클래스 안에 같은 클래스명을 쓰면 오류가 뜸)
}
// 메서드
public double area() { // area(Circle this)
return r*r*3.14;
//retrun this.r*this.r*3.14;
}
//메서드 - void가 있으면 반환값 x
public void result(double a) { // result(double a, Circle this)
System.out.println("반지름 : " + r); // = ("반지름 : " + this.r);
System.out.println("넓이 : " + r);
}
}
public class Test1 {
public static void main(String[] args) {
Circle ob = new Circle(); // ob는 Circle의 다른 이름
//ob.r은 캡슐화되어있어 외부에서 접근 못함.
ob.setDate(10); // = setData(10.ob); -> 내부적으로 ob클래스의 주소를 가져감.
double a = ob.area(); // ob.area(ob) -> 매개변수가 없으므로 ob클래스 주소만 가져감
ob.result(a); // result(a, ob)
ob.setDate(100);
a = ob.area();
ob.result(a);
}
}
실행결과
반지름 :10
넓이 : 314.0
반지름 :100
넓이 : 31400.0
인스턴스 변수 r를 private로 선언했다. private로 선언해서 외부에서 접근을 못하도록해서 메서드를 통한 우회도로를
만들어야 함. 또한 우회도로 메서드는 public으로 선언해서 접근 가능하게 해야 함
static
- static는 new를 사용하지 않아도 알아서 메모리로 올라간다.
- static는 객체가 100개 생성돼도 메모리 공간은 1개만 생성된다.
- static이 있는 변수를 클래스(class) 변수라 함. ( ex : public static int a = 10; )
- new를 통해 메모리 할당을 받지 않아도 사용 가능
package com.day7;
//1. static는 new를 사용하지 않아도 알아서 메모리로 올라간다.
//2. static는 객체가 100개가 생성되도 메모리 공간을 1개만 생성된다.
//Test2 클래스
public class Test2 {
public static int a = 10; // 클래스변수 : static이 있는 변수
//클래스변수 또는 클래스 메서드는 클래스가 로딩되는 순간 메모리 할당이 이루어지고,
// [클래스이름.객체]를 통해 접근할 수 있다.
// 즉, new를 통해 메모리 할당을 받지 않아도 사용 가능.
private int b = 20; // 인스턴스변수(멤버변수,전역변수)
// 인스턴스 변수 또는 인스턴스메서드는 new를 통해 메모리를 할당받아야만
// 사용가능하고 다른 메서드에서는 접근 가능하지만 클래스 메서드에서는 접근 불가능
// 인스턴스 메서드
public void write() {
System.out.println("class 변수 a : " + a);
System.out.println("instance 변수 b : " + b);
}
// 클래스 메서드 - static이 붙으면 인스턴스메서드에서 클래스 메서드가 된다.
public static void print() {
}
public static void main(String[] args) {
System.out.println("class 변수 a : " + a);//10
System.out.println("class 변수 a : " + Test2.a); // 10 클래스 변수
System.out.println("------------------------");
//write();
print(); // 10
Test2.print(); // 10 클래스 메서드
Test2 ob1 = new Test2(); // 객체생성. 다시 위로 가서 실행
System.out.println("class변수 a : " + ob1.a); // 10
System.out.println("instance변수 b : " + ob1.b); //20
System.out.println("------------------------");
//ob1.print();
ob1.write();
System.out.println("------------------------");
Test2 ob2 = new Test2(); // 객체생성. 다시 위로 가서 실행
ob2.a = 100;
ob2.b = 200;
ob2.write();
System.out.println("------------------------");
Test2 ob3 = new Test2(); // 객체생성. 다시 위로 가서 실행
ob3.a = 1000;
ob3.b = 2000;
ob3.write();
System.out.println("------------------------");
ob1.write();
ob2.write();
ob3.write();
}
}
/*
위에부터 아래로 내려오면서 읽어내는데 static는 생성과 동시에 메모리에 올라가서 실행 / static이 없는애들은
new를 만나야(객체생성) 실행되서 일단 패스하면서 쭉 내려가서 new를 만나서 객체 생성을 해준다. 그리고
다시 위로가서 static이 없는 애들을 실행해줌. static이 있는 애들은 이미 실행했으니 패스한다.
*/
Overloading(오버 로딩)
메서드 중복 정의. 하나의 클래스 안에서 비슷한 역할을 하는 메서드의 이름을 통일시키는 기능으로
메서드의 이름은 동일하지만 괄호 속의 인수의 개수나 인수의 자료형을 다르게 주면 각각 다른 메서드로 인식을 한다.
package com.day7;
class Rect { //전부 instance변수와 instance 메소드
private int w, h;// 전역변수, 인스턴스 변수
public void set(int w, int h) { // 전역변수와 매개변수의 이름이 같으면 혼란이 생겨 this를 사용
// 우회해서 초기화.
this.w = w;
this.h = h;
}
public int area() { //넓이 //인스턴스 메소드
return w*h;
}
public int length() { //둘레
return (w+h)*2;
}
public void print(int a, double l) {
System.out.println("가로 : " + w);
System.out.println("세로 : " + h);
System.out.println("면적 : " + a);
System.out.println("둘레 : " + l);
}
// 메소드 중복 정의(Overloading)
// 하나의 클래스 안에서 비슷한 역할을하는 메소드의 이름을
// 통일시키는 기능으로 메소드의 이름은 동일하지만
//괄호 속의 인수의 갯수나 인수의 자료형을 다르게 주면
// 각각 다른 메소드로 인식을 한다.
public void print() {
System.out.println("가로 : " + w);
System.out.println("세로 : " + h);
}
public void print(int a) {
System.out.println("가로 : " + w);
System.out.println("세로 : " + h);
System.out.println("면적 : " + a);
}
public void print(double l) {
System.out.println("가로 : " + w);
System.out.println("세로 : " + h);
System.out.println("둘레 : " + l);
}
}
public class Test4 {
public static void main(String[] args) {
Rect ob = new Rect();
ob.set(10, 20);
int a = ob.area();
double l = ob.length();
ob.print();
ob.print(l);
ob.print(a);
ob.print(a, l);
}
}
생성자
- 객체 생성(메모리를 할당받을 때 사용)
- 변수 초기화 목적
- 생성자는 class(클래스) 이름과 동일
- 리턴 값이 없기 때문에 property가 필요 없다.
- 오버 로딩 가능( 오버 로딩 : 메서드 중복 정의)
- 코딩의 첫 번째 줄에서 한 번만 호출 가능
package com.day7;
/* 생성자
만드는 이유
1. 객체 생성 2. 변수 초기화 목적
메모리 할당을 받을 때 사용을 하고 생성자는 class의 이름과 동일함
리턴값이 없기 때문에 property가 필요 없다.
생성자는 중복정의(Overloading)이 가능
생성자 안에서 생성자를 호출 가능
단 호출 시 제일 선두에서만 호출 가능 ( 생성자는 기본적으로 생략되어 있다.)
*/
public class Test5 {
// 인스턴스변수와 초기화 메서드는 세트라고 생각. 없으면 초기값 설정할 수 없음.
private int x; //인스턴스 변수
// 기본생성자 - Overoading할거아니면 생략 / 기본 생성자 특징 : 반환값 없음
public Test5() {
this(50); // = Test5(int x); -> 오버로딩된 생성자를 호출 ( 오버로딩된 생성자를 먼저 처리한다.)
System.out.println("기본 생성자...");
x = 10;//생성자를 통한 변수 초기화
System.out.println("x : " + x);
}
//오버로딩된 생성자 - 필요에 의해 만듬
public Test5(int x) {
System.out.println("오버로딩된 생성자...");
this.x = x;
System.out.println("x : " + x);
}
public static void main(String[] args) {
Test5 ob1 = new Test5(); //객체 생성. 다시 위로 가서 실행
Test5 ob2 = new Test5(50);
}
}
private 변수 초기화 방법은 2가지 : 초기화 메서드 이용, 생성자 이용
package com.day7;
class RectA {
private int w, h; // 인스턴스변수(전역변수)
// private 변수 초기화 방법은 2가지. -> 초기화메서드 이용, 생성자 이용
//기본 생성자
public RectA() { }
//Overoading된 생성자
public RectA(int w, int h) { //오버로딩된 생성자가 없을때는 기본 생성자 생략가능하지만 있으면 생략 못함
this.w = w;
this.h = h;
}
//초기화 메서드
public void set(int w, int h) {
this.w = w;
this.h = h;
}
//인스턴스 메서드
public int area() {
return w*h;
}
public int length() {
return (w*h)*2;
}
//메서드
public void print(int a) {
System.out.println("가로 : " + w);
System.out.println("세로 : " + h);
System.out.println("면적 : " + a);
}
//메서드 오버로딩
public void print(int a, int l) {
System.out.println("가로 : " + w);
System.out.println("세로 : " + h);
System.out.println("면적 : " + a);
System.out.println("둘레 : " + l);
}
}
public class Test6 {
public static void main(String[] args) {
RectA ob1 = new RectA(); // 기본생성자 + 초기화메서드 사용 -> 기본 생성자 호출 다시 위로가서 실행
ob1.set(10, 20);
int a = ob1.area(); //반환값 200
int l = ob1.length(); //반환값 400
ob1.print(a);
ob1.print(a, l);
System.out.println("-----------------------------------");
RectA ob2 = new RectA(100, 200); // 오버로딩된 생성자를 통해 객체 생성 시 초기화 바로 진행 ->Spring에서는 '의존성 주입'이라 함
a = ob2.area();
l = ob2.length();
ob2.print(a);
ob2.print(a, l);
}
}
객체가 생성되면 바로 실행되는 instance 블록
package com.day7;
// static이 가장 먼저 실행되고 생성자가 가장 늦게 실행된다. 인스턴스변수는 new를 만나야 실행된다.
public class Test7 {
int a = 5; // 인스턴스 변수 (멤버or전역 변수)
//객체가 생성되면 바로 실행되는 instance 블럭
{ // 초기화 블럭 - 메서드로 호출하지는 않는데 형식은 갖춰야 함. instance. 객체를 생성해야 볼 수 있음
System.out.println("초기화 블럭 : a ->" + a); // 5
a = 10;
System.out.println("초기화 블럭:a ->" + a);
}
static int b; // 클래스변수. 메모리 할당이 되어 있음
static { // static 블럭
b = 10;
System.out.println("static 블럭b : " + b);
}
final int C; //상수는 대문자
public Test7() {
System.out.println("생성자...");
C = 100;
System.out.println("C : " + C);
} // 이런 경우에 가장 마지막에 생성되는 것은 생성자
public static void main(String[] args) {
Test7 ob1 = new Test7(); // 객체생성 - static 블럭이 제일 먼저 생성된다.
Test7 ob2 = new Test7(); // 객체 2개 생성 시 static은 객체를 여러번 만들어도 한번만 만들어짐 why? 메모리를 같이쓰니까
}
}
점점 어려워지는 게 느껴진다. 개념을 이해했지만 코딩을 하자니 막막하다.. 꾸준히 복습을 해야겠다.
'Language > Java' 카테고리의 다른 글
[JAVA+국비교육] 상속, Object 클래스, 생성자, Override, super(), 클래스를 활용해서 계산기 만들기 (0) | 2022.01.03 |
---|---|
[JAVA+국비교육] 상속, Call By Value, Call By Reference (0) | 2022.01.01 |
[JAVA+국비교육] 클래스(Class), 객체 지향(OOP) 시작! (0) | 2021.12.30 |
[JAVA+국비교육] 배열 기초 (0) | 2021.12.30 |
[JAVA+국비교육] 반복문 (0) | 2021.12.30 |
블로그의 정보
무작정 개발
무작정 개발