변수와 메서드는 무엇이며 어떻게 사용할까?
선언 위치에 따른 변수의 종류
--
자바에서는 선언 위치에 따라 변수의 종류가 달라진다.
변수의 종류
- 클래스 변수 (Static 변수)
- 인스턴스 변수
- 지역 변수
참고 : [변수] 변수와 상수 (+ 타입, 진법, 형변환)
인스턴스 변수는
클래스 내부에 선언된 변수를 가리키며
해당 클래스를 통해 객체를 생성하여 (힙)메모리에 저장될 때 인스턴스 변수가 생성된다.
정확하게는
그냥 클래스 내부에 선언된 변수를 "인스턴스 변수"라고 부르는 것이 아니라
해당 클래스로 객체를 생성하여 객체가 메모리에 저장될 때
메모리에 저장된 변수를 "인스턴스 변수"라고 부른다.
간단하게는
객체에 저장된 변수를 "인스턴스 변수"라고 부르면 된다.
(객체는 메모리에 저장되어 있으며 그 안에 존재하는 변수도 메모리에 저장되어 있으니)
해당 변수는 각 객체가 고유의 값을 가지므로
A객체에서 해당 인스턴스 변수의 값을 변경해도 B객체에는 영향을 미치지 않는다.
클래스 변수(Static 변수)는
인스턴스 변수와 똑같이 클래스 내부에 선언된 변수를 가리키지만
다른 점은 "static" 키워드가 붙여진 변수를 가리키며
해당 클래스가 (메서드 영역)메모리에 저장될 때 인스턴스 변수가 생성된다.
정확하게는
그냥 클래스 내부에 "static"키워드를 사용하여 선언된 변수를 "클래스 변수"라고 부르는 것이 아니라
해당 클래스에 접근하여 JVM을 통해 (메서드 영역)메모리에 저장될 때
메모리에 "static" 키워드가 붙여져 저장된 변수를 "클래스 변수"라고 부른다.
해당 변수는 해당 클래스를 통해 생성된 객체들이 모두 공유하여 사용하는 변수로
A객체에서 해당 클래스 변수의 값을 변경하면 B객체에도 변경된 값이 적용된다.
인스턴스 변수와 달리 객체를 생성하지 않고도 언제든지 바로 접근하여 사용할 수 있다.
클래스명.클래스변수명
그리고 클래스 변수에 public 접근 제어자를 사용하면
같은 프로그램 내에서 어디서든 해당 클래스 변수에 접근하여 사용할 수 있는 "전역 변수"가 된다.
지역 변수는
메서드나 생성자, 또는 블록 내에서 선언된 변수를 가리키며
해당 메서드나 블록이 실행될 때 (스택)메모리에 저장되어 생성된다.
그리고 해당 메서드나 블록 안에서만 사용할 수 있으며 메서드나 블록의 작업이 종료되면 자동으로 메모리에서 제거된다.
지역 변수는 자동으로 값이 초기화되지 않으므로, 값을 사용하기 전에는 반드시 직접 초기화를 하고 사용해야 한다.
예시 코드
class Car {
String color; // 인스턴스 변수
String model; // 인스턴스 변수
static String madeIn; // 클래스 변수 (static 변수, 전역 변수)
void speedTest() {
int speed = 80; // 지역 변수
System.out.println(speed);
}
}
Car car1 = new Car();
Car car2 = new Car();
car1.color = "Black";
car2.color = "blue";
System.out.println(car1.color); // Black
System.out.println(car2.color); // blue
car1.madeIn = "Japen";
car2.madeIn = "Korea";
System.out.println(car1.madeIn); // Korea (Japen이라고 저장했지만 car2가 Korea로 수정)
System.out.println(car2.madeIn); // Korea
Car.madeIn = "xxxx";
// 객체 없이 바로 사용 가능 (car1, car2 모두 madeIn은 "xxxx"값으로 변경)
--
메서드
--
메서드는
클래스 내부에 선언된 함수(객체 내부에 선언된 함수)를 의미한다.
함수(메서드)는
특정 작업을 수행하는 공장으로
일정한 동작을 수행하여 결과물을 반환하는 파트다.
메서드 작성 기본 형식
반환타입 메서드이름 ([타입 변수명, ...]) {
수행할 내용(작업)
[return 반환할 값]
}
반환 타입에 void를 작성하면 반환하지 않는다는 의미
그래서 반환하는 키워드인 "return"를 작성하지 않는다.
메서드의 괄호() 안에 작성한 변수를 "매개 변수"라고 부르며
외부로부터 해당 메서드를 호출할 때 같이 전달해주는 값으로
해당 메서드를 수행할 때 사용되는 값이다.
즉, 메서드 내부에서만 임시로 잠깐 사용할 값이다.
그리고 메서드를 호출할 때 매개 변수에 값을 할당하는 것을 "인자"라고 부른다.
void aaa(int a) { ... }
aaa(3);
// int a : 매개변수
// 3 : 인자
"return"은
해당 메서드를 종료하고 해당 메서드를 호출했던 위치로 반환할 값을 정의하는 파트다.
반환 타입에 맞는 값을 반환해야 하며 "return" 키워드는 꼭 작성해야 한다.
(메서드의 종료를 해주는 키워드이기 때문이다.)
다만 반환 타입이 void인 경우에는 "return" 키워드를 생략해도 된다.
컴파일러가 자동적으로 추가해주기 때문이다.
int add (int a, int b) { // int타입의 값을 반환, 매개변수는 int타입의 값 2개를 받음
int result = a + b; // 메서드 작업 수행
return result; // int타입의 변수 result를 반환
}
void test() { // 반환하지 않고 메서드 작업만 수행, 매개변수는 없음
System.out.println("테스트"); // 메서드 작업 수행
// return; 생략
}
int add () { // int타입의 값을 반환, 매개변수는 없음
int a = 10; // 지역 변수
int b = 20; // 지역 변수
return a + b; // a + b의 값을 반환
}
int sum = add(3, 5);
// sum = 8
test();
// "테스트" 출력
클래스 메서드(static 메서드)와 인스턴스 메서드
클래스 변수와 인스턴스 변수가 있는 것처럼
메서드에도 클래스 메서드와 인스턴스 메서드가 존재한다.
위 코드들 처럼 "static" 키워드가 없는 메서드가 "인스턴스 메서드"고
"static" 키워드가 있는 메서드가 "클래스 메서드"다.
클래스 메서드 또한 객체를 생성하지 않고 호출하여 사용이 가능하다.
System.out.println() 메서드도 static 메서드로
System 클래스로 객체를 생성 후 println()메서드를 사용하지 않고
바로 사용할 수 있는 이유가 바로 static 메서드이기 때문이다.
클래스 메서드 사용 규칙
- "static" 키워드를 붙인다.
- 해당 클래스로 객체를 생성하지 않아도 사용(호출) 가능
- 클래스 메서드에서 인스턴스 변수는 사용 불가능
- 메서드에서 인스턴스 변수를 사용하지 않으면, "static" 키워드를 붙여 클래스 메서드로 사용하는 것을 고려
클래스 메서드에서 인스턴스 변수를 사용하지 못하는 이유?
인스턴스 변수는 객체를 생성하여 메모리에 할당되어야 사용이 가능하지만
클래스 메서드는 객체 생성 없이 바로 사용이 가능하기 때문에
해당 메서드 안에 인스턴스 변수가 존재한다면 사용할 수 없게 된다.
메서드에 인스턴스 변수를 사용하지 않으면 클래스 메서드로 사용해도 문제가 없으며
클래스 메서드로 사용하면 메서드 호출시간이 짧아지므로 성능이 향상된다.
class Test {
int aaa = 10; // 인스턴스 변수
static int bbb = 20; // 클래스 변수
static void mmm() {
System.out.println(aaa); // 인스턴스 변수 사용 불가!!! 에러 발생
System.out.println(bbb);
Test t = new Test();
System.out.println(bbb); // 객체 생성으로 인해 해당 인스턴스 변수 사용 가능
}
}
--
초기화 블록 (Initialization Block)
--
초기화 블록은
변수를 초기화하거나, 객체가 생성될 때 바로 실행해야 할 로직을 정의하는 코드 블록을 의미한다.
초기화 블록 종류
- 인스턴스 초기화 블록 : 객체가 생성될 때마다 실행되는 코드 블록
- Static 초기화 블록 : 클래스가 처음 로드(메모리 할당)될 때 한 번만 실행할 로직을 정의하는 코드 블록
인스턴스 초기화 블록 작성 방법
클래스 내에 블록{}을 추가하고 해당 블록 내부에 로직 작성
class Test {
{
Test클래스의 객체 생성 시 실행할 로직
}
}
class MyClass {
int value;
// 인스턴스 초기화 블록
{
value = 10;
System.out.println("인스턴스 초기화 블록 실행");
}
}
public class Main {
public static void main(String[] args) {
MyClass obj1 = new MyClass(); // obj1의 value 값은 10으로 초기화 & "인스턴스 초기화 블록 실행" 출력
MyClass obj2 = new MyClass(); // obj2의 value 값은 10으로 초기화 & "인스턴스 초기화 블록 실행" 출력
}
}
Static 초기화 블록 작성 방법
클래스 내에 블록{}을 추가하고 해당 블록 앞에는 "static"키워드를 작성하고 내부에 로직 작성
해당 블록에는 클래스 변수만 사용할 수 있다.
class Test {
static {
Test클래스를 처음으로 메모리에 할당할 때 실행할 로직
}
}
class MyClass {
static int staticValue;
// 정적(Static) 초기화 블록
static {
staticValue = 100;
System.out.println("정적 초기화 블록 실행");
}
}
public class Main {
public static void main(String[] args) {
System.out.println(MyClass.staticValue); // 클래스 변수 staticValue는 100으로 초기화 & "정적 초기화 블록 실행" 출력
MyClass obj1 = new MyClass(); // 생성자만 실행
MyClass obj2 = new MyClass(); // 생성자만 실행
}
}
--
'Language > Java' 카테고리의 다른 글
제어자, 접근 제어자 (+ static, final, abstract, 추상 클래스, 추상 메서드) (0) | 2024.10.20 |
---|---|
package와 import (+ static import) (1) | 2024.10.19 |
상속 (+ super, super(), 포함 관계) (0) | 2024.10.17 |
오버로딩, 오버라이딩 (0) | 2024.10.16 |
생성자 (+ new, this, this() 키워드) (0) | 2024.10.13 |