변수에 대해서 본격적으로 알아보기 전에 다음 코드를 작성하고 실행해봅시다.
다음 절차를 따라해주세요.
단순히 숫자 10을 3번 출력하는 코드이다.
그런데 여기서 숫자 10을 3번 출력하는 대신에 숫자 20을 3번 출력하도록 코드를 변경하려고 한다. 어떻게 해야할까?
package variable;
public class Var1 {
public static void main(String[] args) {
System.out.println(20); //변경 10 -> 20
System.out.println(20); //변경 10 -> 20
System.out.println(20); //변경 10 -> 20
}
}
여기서 숫자 10이 쓰여진 모든 곳을 찾아서 숫자 20으로 변경해야 합니다. 여기서는 코드를 총 3번 변경했습니다.
간단한 예제이기 때문에 코드를 3번만 변경했지만, 만약 숫자 10을 출력하는 부분이 100개가 있다면 모든 100개의 코드를 변경해야 합니다.
더 나아가, 사용자가 숫자를 입력하고 사용자가 입력한 숫자를 출력하고 싶다면 어떻게 해야 할까요?
모든 프로그래밍 언어는 이런 문제를 해결하기 위해 변수(variable)라는 기능을 제공한다. 변수는 이름 그대로 변할 수
있다는 뜻이다.
이제 변수(variable)를 적용해 코드를 다시 작성해봅시다.
이전에 작성했던 코드와 동일하게 10이 총 3번 출력되는 것을 볼 수 있습니다. 이렇게 되면 a = 20; 으로 초기화했을 경우 출력값도 모두 20이 세번 출력이 되므로써 변수를 사용하면 간단하게 모든 코드를 변경할 수 있습니다.
그러면 이제부터 변수에 대해 하나씩 자세하게 설명해드리겠습니다.
int a;
이 코드는 정수를 보관할 수 있는 데이터 저장소를 만들어 이름을 'a'로 지정합니다. 이것이 변수입니다. 이렇게 변수를 만드는 행위를 변수 선언이라고 합니다. 이제 변수 'a'에는 정수를 보관할 수 있게 되었습니다. 숫자 정수 외에도 문자, 소수 등 다양한 종류의 값을 저장할 수 있는 변수들이 있습니다.
우선은 숫자 정수를 저장하는 'int'를 알아봅시다.
값 대입
a = 10;
자바에서 '='는 오른쪽에 있는 값을 왼쪽에 저장한다는 의미입니다. 이것은 수학에서 사용되는 '같다(=)'와는 다른 의미입니다! 변수 'a'에 숫자 10을 저장합니다. 이것을 변수 초기화라고 합니다.
System.out.println(a);
변수에 저장된 값을 읽어서 사용하는 방법은 간단합니다. 변수 이름을 적어주기만 하면 됩니다. 만약 변수 'a'에 10이 들어가 있다면 자바는 실행 시점에 변수의 값을 읽어서 사용합니다. 따라서 위의 코드는 다음과 같이 해석됩니다.
System.out.println(a); // 변수 'a'의 값을 읽음
System.out.println(10); // 'a'의 값인 10으로 변경, 숫자 10 출력
참고로 변수의 값은 반복해서 읽을 수 있습니다. 변수의 값을 읽는다고 값이 없어지는 것이 아닙니다.
a = 20;
변수는 이름 그대로 변할 수 있는 수입니다. 변수 'a'에 저장된 값을 언제든지 바꿀 수 있습니다. 이번에는 중간에 변수의 값을 변경해봅시다.
Var3
package variable;
public class Var3 {
public static void main(String[] args) {
int a; // 변수 선언
a = 10; // 변수 초기화: a(10)
System.out.println(a); // 10 출력
a = 50; // 변수 값 변경: a(10 -> 50)
System.out.println(a); // 50 출력
}
}
실행 결과
10
50
변수의 값이 변경된 이후에는 10 대신에 50이 출력된 것을 확인할 수 있습니다. 변수 선언과 초기화 변수 선언 변수를 선언하면 컴퓨터의 메모리 공간을 확보해서 그곳에 데이터를 저장할 수 있습니다. 그리고 변수의 이름을 통해서 해당 메모리 공간에 접근할 수 있습니다. 쉽게 이야기해서 데이터를 보관할 수 있는 공간을 만들고, 그곳에 이름을 부여합니다.
Var4
package variable;
public class Var4 {
public static void main(String[] args) {
int a;
int b;
int c, d;
}
}
변수 선언 변수는 하나씩 선언할 수도 있습니다.
int a;
int b;
또는 한 번에 여러 변수를 선언할 수도 있습니다.
int c, d;
변수 초기화 변수를 선언하고, 선언한 변수에 처음으로 값을 저장하는 것을 변수 초기화라고 합니다.
Var5
package variable;
public class Var5 {
public static void main(String[] args) {
// 1. 변수 선언, 초기화 각각 따로
int a;
a = 1;
System.out.println(a);
// 2. 변수 선언과 초기화를 한 번에
int b = 2;
System.out.println(b);
// 3. 여러 변수 선언과 초기화를 한 번에
int c = 3, d = 4;
System.out.println(c);
System.out.println(d);
}
}
Var6
package variable;
public class Var6 {
public static void main(String[] args) {
int a;
System.out.println(a); // 컴파일 에러 발생
}
}
초기화하지 않은 변수 읽기 위와 같은 코드에서 다음과 같은 컴파일 에러가 발생합니다.
java: variable a might not have been initialized
해석해보면 변수가 초기화되지 않았다는 오류입니다. 왜 이런 오류가 발생할까요? 컴퓨터에서 메모리는 여러 시스템이 함께 사용하는 공간이기 때문에 어떤 값들이 계속 저장되어 있습니다. 변수를 선언하면 메모리 공간을 차지하고 사용합니다. 그런데 그 공간에 기존에 어떤 값이 있었는지는 아무도 모릅니다. 따라서 초기화를 하지 않으면 이상한 값이 출력될 수 있습니다. 이런 문제를 예방하기 위해 자바는 변수를 초기화하도록 강제합니다.
참고: 변수 이름은 의미있고, 용도를 명확하게 설명해야 합니다. 에러를 확인하고 나면 해당 라인 전체에 주석을 적용하고 나중에 다른 예제를 실행할 때도 컴파일 에러가 발생하지 않도록 해야 합니다.
변수는 데이터의 종류에 따라 다양한 형식이 있습니다. 다음 코드를 실행하여 살펴봅시다.
Var7
package variable;
public class Var7 {
public static void main(String[] args) {
int a = 100; // 정수
double b = 10.5; // 실수
boolean c = true; // 불리언(true, false 가능)
char d = 'A'; // 문자 하나
String e = "Hello Java"; // 문자열, 특별한 타입
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
System.out.println(e);
}
}
실행 결과
100
10.5
true
A
Hello Java
변수는 데이터의 종류에 따라 다양한 형식이 있습니다. 이러한 형식을 영어로는 타입(type)이라 하고, 우리말로는 형식 또는 형이라고 합니다. 변수 타입의 예는 다음과 같습니다.
int a = "백원"; // 정수 타입에 문자열(X)
int b = "100"; // 정수 타입에 문자열(X), 숫자 100이 아니라 문자열 "100"입니다.
리터럴 코드는 개발자가 직접 쓴 100, 10.5, true, 'A', "Hello Java" 등을 프로그래밍 용어로 리터럴(literal)이라 합니다.
int a = 100; // 정수 리터럴
double b = 10.5; // 실수 리터럴
boolean c = true; // 불리언 리터럴
char d = 'A'; // 문자 하나 리터럴
String = "Hello Java" //문자열 리터럴
변수의 값은 변할 수 있지만 리터럴은 개발자가 직접 입력한 고정된 값이므로 변하지 않습니다.
이번에는 다양한 숫자 타입에 대해 알아봅시다.
다음 코드를 작성해보세요.
Var8
package variable;
public class Var8 {
public static void main(String[] args) {
// 정수
byte b = 127; // -128 ~ 127
short s = 32767; // -32,768 ~ 32,767
int i = 2147483647; // -2,147,483,648 ~ 2,147,483,647 (약 20억)
long l = 9223372036854775807L; // -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
// 실수
float f = 10.0f;
double d = 10.0;
}
}
코드를 실행하여 숫자 타입을 자세히 알아봅시다. 변수와 메모리 공간 크기 표현할 수 있는 숫자의 범위와 차지하는 메모리 공간은 다음과 같습니다.
정수형:
실수형:
기타:
리터럴 타입 지정 :
자주 사용하는 타입 :
변수 명명 규칙과 관례 :
변수 명명 규칙 자바에서 변수의 이름을 짓는데는 규칙과 관례가 있습니다. 규칙은 필수이며, 규칙을 지키지 않으면 컴파일 오류가 발생합니다. 관례는 필수는 아니지만 전세계 개발자가 해당 관례를 따르기 때문에 사실상 규칙이라고 생각할 수 있습니다.
규칙:
관례:
다음은 변수 명명 규칙과 관례를 지키는 예제입니다.
Var9
package variable;
public class Var9 {
public static void main(String[] args) {
// 변수 선언
int myAge;
double height;
boolean isJavaFun;
String myName;
// 변수 초기화
myAge = 25;
height = 175.5;
isJavaFun = true;
myName = "John Doe";
// 변수 사용
System.out.println("나의 나이: " + myAge);
System.out.println("나의 키: " + height);
System.out.println("자바는 재미있다: " + isJavaFun);
System.out.println("내 이름: " + myName);
}
}
이 코드에서는 변수 선언, 초기화, 사용을 연습하면서 변수 명명 규칙과 관례를 지켰습니다. 변수명을 가독성 있게 작성하고, 낙타 표기법과 상수 표기법을 지켜 코드를 작성했습니다.
변수의 사용 범위 변수의 사용 범위(scope)
변수의 사용 범위 변수의 사용 범위(scope)는 변수가 선언된 블록 내에서만 유효하다는 개념입니다.
블록은 중괄호 {}로 표현되며, 일반적으로 클래스, 메서드, 제어문(if, for, while 등), 블록 내에 또 다른 블록이 있을 수 있습니다.
예를 들어, 다음 코드를 살펴봅시다.
Var10
package variable;
public class Var10 {
public static void main(String[] args) {
// 외부 블록 시작
int outerVar = 10;
System.out.println("외부 블록의 outerVar: " + outerVar);
// 내부 블록 시작
{
int innerVar = 20;
System.out.println("내부 블록의 innerVar: " + innerVar);
// 외부 블록의 변수에 접근 가능
System.out.println("내부 블록에서 외부 블록의 outerVar: " + outerVar);
}
// 내부 블록 끝
// 내부 블록의 변수에 접근 불가능
//System.out.println("외부 블록에서 내부 블록의 innerVar: " + innerVar); // 주석 해제하면 컴파일 에러 발생
// 외부 블록의 변수에 접근 가능
System.out.println("외부 블록에서 outerVar: " + outerVar);
}
}
이 코드에서 outerVar와 innerVar는 서로 다른 블록에 선언되어 있습니다.
전역 변수와 지역 변수
전역 변수는 일반적으로 객체의 상태를 나타내는 데 사용되며, 지역 변수는 특정 메서드에서 임시로 필요한 데이터를 처리하는 데 사용됩니다.
다음은 전역 변수와 지역 변수를 사용한 예제 코드입니다.
Var11
package variable;
public class Var11 {
// 전역 변수
static int globalVar = 100;
public static void main(String[] args) {
// 지역 변수
int localVar = 10;
System.out.println("전역 변수: " + globalVar);
System.out.println("지역 변수: " + localVar);
// 다른 메서드에서도 전역 변수 사용 가능
anotherMethod();
}
// 다른 메서드에서도 전역 변수 사용 가능
static void anotherMethod() {
System.out.println("다른 메서드에서 전역 변수 사용: " + globalVar);
}
}
이 코드에서 globalVar는 클래스 블록 안에서 선언되었으므로 전역 변수입니다. main 메서드와 anotherMethod 메서드에서 모두 사용할 수 있습니다. 반면에 localVar는 main 메서드 블록 안에서만 선언되었으므로 지역 변수로, main 메서드에서만 사용할 수 있습니다.
메서드의 매개변수
메서드의 매개변수(parameter)는 메서드를 호출할 때 전달되는 값입니다. 메서드가 호출되면 매개변수에 전달된 값이 해당 위치의 변수에 저장되어 메서드 내부에서 사용됩니다. 매개변수는 메서드의 괄호 안에서 선언되며, 메서드를 호출할 때 전달되는 값의 타입과 순서에 따라 정의됩니다. 매개변수를 사용하면 동일한 로직을 여러 값에 대해 실행할 수 있습니다. 이는 메서드의 재사용성을 높여주며, 코드의 유지보수성을 향상시킵니다.
다음은 메서드의 매개변수를 사용한 예제 코드입니다.
Var12
package variable;
public class Var12 {
public static void main(String[] args) {
// 메서드 호출
printSum(3, 5);
printSum(10, 20);
printSum(-7, 2);
}
// 매개변수를 받아 합계를 출력하는 메서드
static void printSum(int a, int b) {
int sum = a + b;
System.out.println(a + " + " + b + " = " + sum);
}
}
이 코드에서 printSum 메서드는 두 개의 int형 매개변수 a와 b를 가지고 있습니다. 이 메서드를 호출할 때마다 전달된 값으로 해당 매개변수들이 초기화되며, 메서드 내부에서는 이 값을 사용하여 합계를 계산하고 출력합니다.
메서드의 시그니처
메서드의 시그니처(signature)는 메서드의 선언부에서 반환 타입, 메서드 이름, 매개변수의 순서와 타입을 의미합니다. 메서드의 시그니처가 다르면 같은 이름의 메서드라도 서로 다른 메서드로 인식됩니다.
메서드의 시그니처 예시
int add(int a, int b); // 시그니처: 반환 타입은 int, 메서드 이름은 add, 매개변수는 int a와 int b
void printMessage(String message); // 시그니처: 반환 타입은 void, 메서드 이름은 printMessage, 매개변수는 String message
double calculateArea(double radius); // 시그니처: 반환 타입은 double, 메서드 이름은 calculateArea, 매개변수는 double radius
메서드 오버로딩
메서드 오버로딩(Overloading)은 같은 이름의 메서드가 여러 개 정의되어, 서로 다른 매개변수를 받을 수 있는 것을 말합니다. 오버로딩된 메서드는 시그니처가 다르게 구성되어야 합니다. 메서드 오버로딩을 통해 동일한 메서드 이름을 사용하면서 다양한 데이터 타입이나 매개변수 조합을 지원할 수 있습니다.
이는 코드의 가독성을 높여주고, 사용자에게 편의를 제공합니다.
다음은 메서드 오버로딩의 예시 코드입니다.
Var13
package variable;
public class Var13 {
public static void main(String[] args) {
printNumber(10);
printNumber(3.14);
printNumber("Java");
}
// 정수를 출력하는 메서드
static void printNumber(int num) {
System.out.println("정수: " + num);
}
// 실수를 출력하는 메서드
static void printNumber(double num) {
System.out.println("실수: " + num);
}
// 문자열을 출력하는 메서드
static void printNumber(String str) {
System.out.println("문자열: " + str);
}
}
이 코드에서 printNumber 메서드가 세 번 정의되어 있습니다. 첫 번째는 int형을, 두 번째는 double형을, 세 번째는 String을 매개변수로 받습니다. 각 메서드는 다른 데이터 타입을 출력하도록 구현되어 있습니다. 메서드 오버로딩은 메서드 이름은 동일하지만 매개변수의 개수, 타입, 순서 중 적어도 하나 이상이 다를 때 발생합니다. 반환 타입은 오버로딩에 영향을 주지 않습니다.
본 포스트에서 다뤘던 주제들은 자바 프로그래밍에서 기초적이면서도 중요한 개념들입니다. 올바른 변수 명명 규칙과 사용 범위, 그리고 메서드의 활용은 코드의 가독성과 유지보수성을 높여줍니다. 이를 기반으로 자바 프로그래밍 실력을 더욱 향상시킬 수 있습니다. 다음 블로그 게시글에서는 JAVA에서 제공하는 연산자에 대해 공부하겠습니다!
[자바 CS지식] 캡슐화와 정보 은닉의 차이점 (0) | 2024.02.11 |
---|---|
[자바 CS지식] 접근 제어자의 종류와 특징 (0) | 2024.02.11 |
[자바 CS지식] 스레드 안정성이란 무엇일까? (0) | 2024.02.10 |
[자바 CS지식] String, StringBuilder, StringBuffer의 차이점 (0) | 2024.02.10 |
[자바 CS지식] 자바에서 컴파일러와 인터프리터의 차이점 (0) | 2024.02.10 |