본문 바로가기
Java Tutorials

#2 Lesson: Language Basics - Variables

by xogns93 2024. 7. 17.

Variables

이전 강의에서 배웠듯이 객체는 자신의 상태를 fields 에 저장합니다 .

int cadence = 0;
int speed = 0;
int gear = 1;

 

객체란 무엇인가? 토론을 통해 필드에 대해 소개했지만 아마도 다음과 같은 몇 가지 질문이 있을 것입니다. 필드 이름을 지정하는 규칙과 규칙은 무엇입니까? 게다가 int, 어떤 다른 데이터 유형이 있나요? 필드를 선언할 때 필드를 초기화해야 합니까? 명시적으로 초기화되지 않은 경우 필드에 기본값이 할당됩니까? 이번 강의에서는 이러한 질문에 대한 답을 살펴보겠습니다. 하지만 그 전에 먼저 알아야 할 몇 가지 기술적 차이점이 있습니다. Java 프로그래밍 언어에서는 "필드"와 "변수"라는 용어가 모두 사용됩니다. 둘 다 종종 동일한 것을 참조하는 것처럼 보이기 때문에 이는 새로운 개발자들 사이에서 흔히 발생하는 혼란의 원인입니다.

 

Java 프로그래밍 언어는 다음과 같은 종류의 변수를 정의합니다.

  • Instance Variables 인스턴스 변수(Non-Static Fileds 비정적 필드) 기술적으로 말하면 개체는 "비정적 필드", 즉 static 키워드 없이 선언된 필드에 개별 상태를 저장합니다. 비정적 필드는 해당 값이 클래스의 각 인스턴스 (즉, 각 객체) 에 고유하기 때문에 인스턴스 변수 라고도 합니다 . 한 자전거의 currentSpeed는 다른 자전거의 currentSpeed와 독립적입니다.
  • Class Variables 클래스 변수(Static Variables 정적 필드) 클래스 변수는 static 수정자로 선언된 필드입니다. 이는 클래스가 인스턴스화되는 횟수에 관계없이 이 변수의 복사본이 정확히 하나만 존재한다는 것을 컴파일러에 알려줍니다. 특정 종류의 자전거에 대한 기어 수를 정의하는 필드는 static개념적으로 동일한 수의 기어가 모든 인스턴스에 적용되므로 다음과 같이 표시될 수 있습니다. 코드 s tatic int numGears = 6; 이러한 정적 필드를 생성합니다. 또한 기어 수가 절대 변경되지 않음을 나타내기 위해 final 키워드를 추가할 수 있습니다.
  • Local Variables 지역 변수 객체가 자신의 상태를 필드에 저장하는 방법과 유사하게 메소드는 종종 임시 상태를 지역 변수 에 저장합니다 . 지역 변수를 선언하는 구문은 필드를 선언하는 것과 유사합니다(예: int count = 0;). 변수를 지역 변수로 지정하는 특별한 키워드는 없습니다. 해당 결정은 변수가 선언된 위치, 즉 메서드의 여는 중괄호[{]와 닫는 중괄호[}] 사이에서 전적으로 이루어집니다. 따라서 지역 변수는 해당 변수가 선언된 메서드에서만 볼 수 있습니다. 나머지 클래스에서는 액세스할 수 없습니다.
  • Parameters 매개변수 Bicycle 클래스와 "Hello World!" 어플리케이션의 main 메소드 모두에서 파라미터의 예를 이미 보았습니다. 애플리케이션. main 메서드의 시그니처는 public static void main(String[] args)입니다. 여기서 args 변수는 이 메소드에 대한 파라미터입니다. 기억해야 할 중요한 점은 파라미터는 항상 "필드"가 아닌 "변수"로 분류된다는 것입니다. 이는 이 자습서의 뒷부분에서 배우게 될 다른 파라미터 허용 구문(예: 생성자 및 예외 처리기)에도 적용됩니다.

하지만 이 튜토리얼의 나머지 부분에서는 필드와 변수를 논의할 때 다음과 같은 일반 지침을 사용합니다. "일반 필드"(지역 변수 및 파라미터 제외)에 관해 이야기하는 경우 간단히 "필드"라고 말할 수 있습니다. 논의가 "위의 모든 것"에 적용된다면 간단히 "변수"라고 말할 수 있습니다. 문맥상 구별이 필요한 경우에는 특정 용어(정적 필드, 지역 변수 등)를 적절하게 사용합니다. 가끔 "member"이라는 용어도 사용되는 것을 볼 수 있습니다. 타입의 필드, 메소드 및 중첩 타을 집합적으로 해당 멤버 라고 합니다 .

"수정자"는 객체 지향 프로그래밍에서 멤버 변수나 메서드의 동작을 변경하거나 제어하는 키워드를 말합니다. Java에서 "수정자(modifier)"는 클래스, 변수, 메서드에 적용되며, 해당 요소의 특성을 수정하거나 제한합니다. 예를 들어, "static" 수정자는 클래스 변수를 선언할 때 사용되며, 해당 변수가 클래스 수준에 속하고 인스턴스 간에 공유됨을 나타냅니다. 또한 "final" 수정자는 변수를 상수로 선언하여 한 번 할당된 값을 변경할 수 없게 합니다. 따라서 수정자는 변수나 메서드의 동작에 대한 특성을 조절하고 제한하는 데 사용됩니다.
"타입"이란 말은 일반적으로 특정 클래스나 구조체, 또는 데이터 유형을 가리킵니다. 그러므로 동일한 클래스나 구조체에 속하는 모든 멤버들은 해당 타입의 멤버들이 됩니다. 따라서 클래스나 구조체에 속하는 필드, 메서드, 중첩된 타입(내부 클래스 또는 중첩된 구조체) 등을 통틀어서 해당 클래스나 구조체의 "멤버"라고 부릅니다. 이러한 멤버들은 해당 클래스나 구조체의 기능과 상태를 정의하고 구성합니다.

Naming 명명

모든 프로그래밍 언어에는 사용할 수 있는 이름 종류에 대한 고유한 규칙과 규칙이 있으며 Java 프로그래밍 언어도 다르지 않습니다. 변수 이름 지정 규칙과 규칙은 다음과 같이 요약할 수 있습니다.

  • 변수 이름은 대소문자를 구분합니다. 변수의 이름은 문자로 시작하거나 달러 기호 "$", 또는 밑줄 문자 ""로 시작할 수 있는 Unicode 문자와 숫자로 이루어진 길이 제한이 없는 시퀀스입니다. 그러나 관례적으로 변수 이름을 항상 문자로 시작하며, "$"나 ""로 시작하지 않습니다. 또한, 관례적으로 달러 기호는 전혀 사용하지 않습니다. 일부 자동 생성된 이름에 달러 기호가 포함된 경우가 있을 수 있지만, 변수 이름을 지정할 때는 항상 달러 기호를 피해야 합니다. 밑줄 문자에 대해서도 유사한 관례가 존재합니다. 기술적으로는 변수의 이름을 밑줄 문자 "_"로 시작하는 것이 가능하지만, 이러한 관행은 권장되지 않습니다. 공백은 허용되지 않습니다.
  • 이어지는 문자는 문자, 숫자, 달러 기호 또는 밑줄 문자가 될 수 있습니다. 이 규칙에도 관례(그리고 상식)가 적용됩니다. 변수의 이름을 선택할 때는 약어 대신 완전한 단어를 사용하세요. 이렇게 함으로써 코드를 읽고 이해하기 쉬워집니다. 많은 경우 이러한 방법은 코드 자체가 자기 설명적이 되도록 만듭니다. 예를 들어, cadence, speed, gear와 같은 필드 이름은 s, c, g와 같은 약어보다 훨씬 직관적입니다. 또한 선택한 이름이 키워드나 예약어가 아니어야 합니다.
  • 선택한 이름이 한 단어로만 이루어져 있다면, 그 단어를 모두 소문자로 씁니다. 두 개 이상의 단어로 이루어진 경우, 각 단어의 첫 글자를 대문자로 씁니다. gearRatio와 currentGear라는 이름은 이 관례의 대표적인 예입니다. 변수가 상수 값을 저장하는 경우(static final int NUM_GEARS = 6와 같이), 관례가 약간 변경되어 각 글자를 대문자로 쓰고 연속된 단어는 밑줄 문자로 구분합니다. 관례적으로 밑줄 문자는 다른 곳에서는 사용하지 않습니다.

 

Primitive Data Types 기본 데이터 타입

자바 프로그래밍 언어는 정적으로 타입이 지정되어 있어 변수를 사용하기 전에 반드시 선언해야 합니다. 이는 변수의 타입과 이름을 명시하는 것을 포함합니다. 예를 들어:

int gear = 1;


이렇게 함으로써 프로그램에게 "gear"라는 이름의 필드가 존재하고 숫자 데이터를 보유하며 초기 값은 "1"이라고 알려줍니다. 변수의 데이터 유형은 해당 변수가 포함할 수 있는 값과 그에 대한 연산을 결정합니다. 자바 프로그래밍 언어는 int를 포함한 총 여덟 가지의 기본 데이터 유형을 지원합니다. 기본 유형은 언어에 의해 미리 정의되며 예약된 키워드로 명명됩니다. 기본 값은 다른 기본 값과 상태를 공유하지 않습니다. 자바 프로그래밍 언어에서 지원되는 여덟 가지 기본 데이터 유형은 다음과 같습니다:

  • byte: 8비트 부호 있는 2의 보수 정수입니다. 최소 값은 -128이고 최대 값은 127(포함)입니다. byte 데이터 유형은 메모리를 절약할 수 있는 큰 배열에서 메모리를 저장하는 데 유용할 수 있습니다.
  • short: 16비트 부호 있는 2의 보수 정수입니다. 최소 값은 -32,768이고 최대 값은 32,767(포함)입니다.
  • int: 기본적으로 int 데이터 유형은 32비트 부호 있는 2의 보수 정수로, 최소 값은 -231이고 최대 값은 231-1입니다.
  • long: 64비트 2의 보수 정수입니다. 부호 있는 long의 최소 값은 -263이고 최대 값은 263-1입니다.
  • float: 단일 정밀도 32비트 IEEE 754 부동 소수점입니다.
  • double: 이중 정밀도 64비트 IEEE 754 부동 소수점입니다.
  • boolean: 두 가지 가능한 값인 true와 false가 있습니다.
  • char: 단일 16비트 유니코드 문자입니다.

기본 데이터 유형 외에도 자바 프로그래밍 언어는 java.lang.String 클래스를 통해 문자열에 대한 특별한 지원을 제공합니다. 큰 따옴표로 문자열을 둘러싸면 새 String 객체가 자동으로 생성됩니다. 문자열 객체는 변경할 수 없으므로(불변), 한 번 생성되면 값이 변경될 수 없습니다. 문자열 클래스는 기본적으로 기본 데이터 유형이 아니지만 언어에서 특별한 지원을 받으므로 대부분 기본 데이터 유형으로 간주됩니다. 문자열 클래스에 대해 자세히 알아보겠습니다.

 

Default Values

필드를 선언할 때 항상 값을 할당할 필요는 없습니다. 선언은 되었지만 초기화되지 않은 필드는 컴파일러에 의해 디폴트값으로 설정됩니다. 일반적으로 이러한 디폴트 값은 데이터 유형에 따라 0 또는 null이 됩니다. 그러나 이러한 디폴트 값에 의존하는 것은 일반적으로 좋지 않는 프로그래밍 스타일로 간주됩니다.

다음 차트는 위의 데이터 유형에 대한 디폴트 값을 요약합니다.

Data Type Default Value (for fields)
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000'
String (or any object)   null
boolean false

 

지역 변수는 약간 다르며, 컴파일러는 초기화되지 않은 지역 변수에 기본값을 할당하지 않습니다. 변수를 선언하는 위치에서 변수를 초기화할 수 없는 경우, 사용하기 전에 값을 할당해야 합니다. 초기화되지 않은 지역 변수에 액세스하면 컴파일 시간 오류가 발생합니다.

public class Main {
    public static void main(String[] args) {
        int x; // Declaring a local variable 'x' without initializing it
        System.out.println(x); // Trying to use 'x' without initializing it will result in a compile-time error
    }
}

 

위 코드를 빌드하고 main 메소드를 실행하면 다음과 같은 에러를 콘솔에서 확인할 수 있습니다.

Main.java:4: error: variable x might not have been initialized
        System.out.println(x);
                           ^
1 error

 

 

Literals

기본(Primitive) 타입의 변수를 초기화할 때 new 키워드를 사용하지 않습니다. 기본 타입은 언어에 내장된 특수한 데이터 타입으로, 클래스에서 생성된 객체가 아닙니다. 리터럴은 고정된 값의 소스 코드 표현입니다. 리터럴은 계산을 필요로하지 않고 직접 코드에 표현됩니다. 아래에 나와 있는 것처럼 리터럴을 기본 타입의 변수에 할당할 수 있습니다:

boolean result = true;
char capitalC = 'C';
byte b = 100;
short s = 10000;
int i = 100000;

 

Integer Literals

정수 리터럴은 L 또는 l로 끝나면 long 형이며, 그렇지 않으면 int 형입니다. 소문자 l은 숫자 1과 구별하기 어려우므로 대문자 L을 사용하는 것이 권장됩니다.

byte, short, int 및 long 유형의 값은 int 리터럴에서 생성할 수 있습니다. int의 범위를 초과하는 long 유형의 값은 long 리터럴에서 생성할 수 있습니다. 정수 리터럴은 다음과 같은 숫자 체계로 표현할 수 있습니다.

  • 10진수: 숫자 0부터 9까지로 구성된 10진법은 일상적으로 사용하는 숫자 체계입니다.
  • 16진수: 숫자 0부터 9와 문자 A부터 F로 구성된 16진법은 0x로 표시됩니다.
  • 2진수: 숫자 0과 1로 구성된 2진법은 0b로 표시됩니다. (Java SE 7 및 그 이후 버전에서 2진 리터럴을 생성할 수 있습니다.)

일반적으로 프로그래밍에서는 10진수를 사용되는 경우가 많습니다. 그러나 다른 숫자 체계를 사용해야 하는 경우 다음 예제와 같이 올바른 구문을 사용할 수 있습니다. 0x는 16진법을 나타내고 0b는 2진법을 나타냅니다:

// 10진수에서의 숫자 26
int decVal = 26;
// 16진수에서의 숫자 26
int hexVal = 0x1a;
// 2진수에서의 숫자 26
int binVal = 0b11010;

 

Floating-Point Literals

부동 소수점 리터럴은 F 또는 f로 끝나면 float 형이 되고, 그렇지 않으면 double 형이 되며, 선택적으로 D 또는 d로 끝날 수 있습니다.

부동 소수점 유형(float 및 double)은 E 또는 e(과학적 표기법을 위한), F 또는 f(32비트 부동 소수점 리터럴), D 또는 d(64비트 double 리터럴; 이것이 기본값이며 관례에 따라 생략됩니다)를 사용하여 표현할 수 있습니다.

double d1 = 123.4;
// 같은 값이지만, 과학적 표기법으로 표현된 d1
double d2 = 1.234e2;
float f1  = 123.4f;

 

 

Character and String Literals

char 및 String 유형의 리터럴은 어떤 유니코드 (UTF-16) 문자든 포함할 수 있습니다. 에디터와 파일 시스템이 허용하는 경우, 해당 문자를 직접 코드에 사용할 수 있습니다. 그렇지 않은 경우에는 '\u0108' (대문자 C에 양호 기호), 또는 "S\u00ED Se\u00F1or" (스페인어로 Sí Señor)와 같은 "유니코드 이스케이프"를 사용할 수 있습니다. char 리터럴에는 '단일 따옴표'를 사용하고 String 리터럴에는 "이중 따옴표"를 사용합니다. 유니코드 이스케이프 시퀀스는 char 또는 String 리터럴뿐만 아니라 프로그램의 다른 곳 (예: 필드 이름)에서도 사용할 수 있습니다.

Java 프로그래밍 언어는 또한 char 및 String 리터럴에 대해 몇 가지 특수한 이스케이프 시퀀스를 지원합니다:

\b (backspace),

\t (tap),

\n (line feed),

\f (form feed),

\r (carriage return),

\" (이중 인용부호),

\' (단일 인용부호), 및 \\ (backslash).

또한 참조 타입의 값으로 사용할 수 있는 특별한 null 리터럴이 있습니다. null은 기본 타입의 변수를 제외한 모든 변수에 할당할 수 있습니다. null 값으로 할 수 있는 것은 그 존재 여부를 테스트하는 것뿐입니다. 따라서 프로그램에서 null은 어떤 객체가 사용 불가능하다는 표시로 종종 사용됩니다.

마지막으로, 클래스 리터럴이라는 특별한 종류의 리터럴이 있습니다. 이는 타입 이름을 취하여 ".class"를 추가한 것으로, 예를 들어 String.class입니다. 이는 타입 자체를 나타내는 객체 (Class 유형의 객체)를 참조합니다.

Class<String> stringClass = String.class;

 

위의 코드에서 String.class는 String 타입을 나타내는 클래스 리터럴입니다. 이것은 Class<String> 타입의 객체를 참조합니다.

 

Using Underscore Characters in Numeric Literals

Java SE 7 및 이후 버전에서는 숫자 리터럴 내의 숫자 사이에 밑줄 문자 (_)를 어디에나 사용할 수 있습니다. 이 기능을 사용하면 예를 들어 숫자 리터럴 내의 숫자 그룹을 분리하여 코드의 가독성을 향상시킬 수 있습니다.

예를 들어 코드에 많은 자릿수를 가진 숫자가 포함된 경우, 쉼표나 공백과 같은 구두점을 사용하여 세 자리씩 숫자 그룹을 구분하는 것과 유사하게 밑줄 문자를 사용할 수 있습니다.

다음 예제는 숫자 리터럴에서 밑줄을 사용하는 다른 방법을 보여줍니다:

long creditCardNumber = 1234_5678_9012_3456L;
long socialSecurityNumber = 999_99_9999L;
float pi = 3.14_15F;
long hexBytes = 0xFF_EC_DE_5E;
long hexWords = 0xCAFE_BABE;
long maxLong = 0x7fff_ffff_ffff_ffffL;
byte nybbles = 0b0010_0101;
long bytes = 0b11010010_01101001_10010100_10010010;


밑줄은 숫자 사이에만 위치할 수 있으며 다음과 같은 위치에 밑줄을 넣을 수 없습니다:

  • 숫자의 시작 또는 끝에
  • 부동 소수점 리터럴의 소수점과 인접한 위치
  • F 또는 L 접미사 앞에
  • 숫자 문자열이 예상되는 위치

다음 예제는 숫자 리터럴에서 유효하고 유효하지 않은 밑줄 배치를 보여줍니다:

// 유효하지 않음: 소수점과 인접한 위치에 밑줄을 놓을 수 없음
float pi1 = 3_.1415F;
// 유효하지 않음: 소수점과 인접한 위치에 밑줄을 놓을 수 없음
float pi2 = 3._1415F;
// 유효하지 않음: L 접미사 앞에 밑줄을 놓을 수 없음
long socialSecurityNumber1 = 999_99_9999_L;

// 유효함 (10진수 리터럴)
int x1 = 5_2;
// 유효하지 않음: 리터럴 끝에 밑줄을 놓을 수 없음
int x2 = 52_;
// 유효함 (10진수 리터럴)
int x3 = 5_______2;

// 유효하지 않음: 0x 진수 접두사에 밑줄을 놓을 수 없음
int x4 = 0_x52;
// 유효하지 않음: 숫자의 시작 부분에 밑줄을 놓을 수 없음
int x5 = 0x_52;
// 유효함 (16진수 리터럴)
int x6 = 0x5_2;
// 유효하지 않음: 숫자의 끝에 밑줄을 놓을 수 없음
int x7 = 0x52_;



Arrays 배열

배열은 단일 유형의 일정한 개수의 값을 보관하는 컨테이너 객체입니다. 배열이 생성될 때 배열의 길이가 결정됩니다. 생성 후에는 그 길이가 고정됩니다. 이미 "Hello World!" 애플리케이션의 main 메서드에서 배열의 예를 보았습니다. 이 섹션에서는 배열에 대해 더 자세히 다룹니다.

 

An array of 10 elements

 

 

배열의 각 아이템을 element라고 하며, 각 엘리먼트는 숫자 인덱스로 액세스됩니다. 이전 그림에서와 같이 번호 매기기는 0부터 시작됩니다. 예를 들어, 9번째 엘리먼트는 인덱스 8에서 액세스됩니다.

다음 ArrayDemo 프로그램은 정수 배열을 생성하고 배열에 일부 값을 넣은 다음 각 값을 표준 출력에 출력합니다.

class ArrayDemo {
    public static void main(String[] args) {
        // declares an array of integers
        int[] anArray;

        // allocates memory for 10 integers
        anArray = new int[10];
           
        // initialize first element
        anArray[0] = 100;
        // initialize second element
        anArray[1] = 200;
        // and so forth
        anArray[2] = 300;
        anArray[3] = 400;
        anArray[4] = 500;
        anArray[5] = 600;
        anArray[6] = 700;
        anArray[7] = 800;
        anArray[8] = 900;
        anArray[9] = 1000;

        System.out.println("Element at index 0: "
                           + anArray[0]);
        System.out.println("Element at index 1: "
                           + anArray[1]);
        System.out.println("Element at index 2: "
                           + anArray[2]);
        System.out.println("Element at index 3: "
                           + anArray[3]);
        System.out.println("Element at index 4: "
                           + anArray[4]);
        System.out.println("Element at index 5: "
                           + anArray[5]);
        System.out.println("Element at index 6: "
                           + anArray[6]);
        System.out.println("Element at index 7: "
                           + anArray[7]);
        System.out.println("Element at index 8: "
                           + anArray[8]);
        System.out.println("Element at index 9: "
                           + anArray[9]);
    }
}

 

이 프로그램의 출력은 :

Element at index 0: 100
Element at index 1: 200
Element at index 2: 300
Element at index 3: 400
Element at index 4: 500
Element at index 5: 600
Element at index 6: 700
Element at index 7: 800
Element at index 8: 900
Element at index 9: 1000

 

실제 프로그래밍 상황에서는 이전 예제처럼 각 라인을 개별적으로 작성하는 대신, 지원되는 루핑 구조 중[for, while...] 하나를 사용하여 배열의 각 엘리먼트를 반복할 것입니다. 그러나 이 예제는 배열 구문을 명확하게 보여줍니다. 제어 흐름 섹션에서 다양한 루핑 구조 (for, while, do-while)에 대해 배우게 될 것입니다.

 

Declaring a Variable to Refer to an Array

이전 프로그램에서 다음 코드 라인을 사용하여 배열 (이름이 anArray인)을 선언합니다:

// 정수 배열을 선언합니다.
int[] anArray;


다른 타입의 변수 선언과 마찬가지로 배열 선언에는 두 가지 구성 요소가 있습니다. 배열의 타입과 배열의 이름입니다. 배열의 타입은 type[]로 작성되며, 여기서 type은 배열에 포함된 엘리먼트의 데이터 타입입니다. 대괄호는 이 변수가 배열을 보유한다는 것을 나타내는 특수 기호입니다. 배열의 크기는 타입의 일부가 아닙니다 (따라서 대괄호가 비어 있습니다). 배열의 이름은 이전에 논의된 명명 섹션의 규칙과 규칙을 따르는 경우에만 원하는대로 정할 수 있습니다. 다른 타입의 변수와 마찬가지로 배열 선언은 실제로 배열을 생성하지 않습니다. 이것은 단순히 컴파일러에게 해당 변수가 지정된 타입의 배열을 보유할 것이라고 알려주는 것입니다.

마찬가지로 다른 타입의 배열을 선언할 수도 있습니다:

byte[] anArrayOfBytes;
short[] anArrayOfShorts;
long[] anArrayOfLongs;
float[] anArrayOfFloats;
double[] anArrayOfDoubles;
boolean[] anArrayOfBooleans;
char[] anArrayOfChars;
String[] anArrayOfStrings;


대괄호를 배열 이름 뒤에 놓을 수도 있습니다:

// 이 형식은 권장되지 않습니다.
float anArrayOfFloats[];


그러나 관례적으로 이 형식은 권장되지 않습니다. 대괄호는 배열 타입을 식별하며 타입 표시와 함께 나타나야 합니다.

 

Creating, Initializing, and Accessing an Array

배열을 만드는 한 가지 방법은 new 연산자를 사용하는 것입니다. ArrayDemo 프로그램의 다음 문은 충분한 메모리를 할당하여 10개의 정수 타입의 엘리먼트를 가진 배열을 생성하고 이를 anArray 변수에 할당합니다.

// 정수 배열을 생성합니다.
anArray = new int[10];


만약 위 코드가 생략되었다면, 컴파일러는 다음과 같은 오류를 출력하며 컴파일이 실패합니다.

ArrayDemo.java:4: Variable anArray may not have been initialized.


다음 몇 줄은 배열의 각 엘리먼트에 값을 할당합니다.

anArray[0] = 100; // 첫 번째 요소 초기화
anArray[1] = 200; // 두 번째 요소 초기화
anArray[2] = 300; // 이와 같은 방식으로 초기화 진행


각 배열 엘리먼트는 해당하는 숫자 인덱스로 액세스됩니다.

System.out.println("인덱스 0의 요소: " + anArray[0]);
System.out.println("인덱스 1의 요소: " + anArray[1]);
System.out.println("인덱스 2의 요소: " + anArray[2]);


대신 다음과 같은 단축 구문을 사용하여 배열을 생성하고 초기화할 수도 있습니다.

int[] anArray = { 
    100, 200, 300,
    400, 500, 600, 
    700, 800, 900, 1000
};


여기서 배열의 길이는 중괄호 사이에 제공된 값의 개수에 의해 결정됩니다.

또한 두 개 이상의 대괄호를 사용하여 배열의 배열 (다차원 배열이라고도 함)을 선언할 수도 있습니다. 예를 들어 String[][] names와 같이 사용합니다. 

자바 프로그래밍 언어에서 다차원 배열은 그 구성 엘리먼트 자체가 배열인 배열입니다. 이는 C나 Fortran의 배열과는 다릅니다. 이로 인한 결과는 행의 길이가 다를 수 있다는 것입니다. 아래의 MultiDimArrayDemo 프로그램에서 보여주는 것처럼.

class MultiDimArrayDemo {
    public static void main(String[] args) {
        String[][] names = {
            {"Mr. ", "Mrs. ", "Ms. "},
            {"Smith", "Jones"}
        };
        // Mr. Smith
        System.out.println(names[0][0] + names[1][0]);
        // Ms. Jones
        System.out.println(names[0][2] + names[1][1]);
    }
}


이 프로그램의 출력은 다음과 같습니다.

Mr. Smith
Ms. Jones


마지막으로, 내장된 length 속성을 사용하여 모든 배열의 크기를 알 수 있습니다. 다음 코드는 배열의 크기를 표준 출력에 인쇄합니다.

System.out.println(anArray.length);


Copying Arrays
System 클래스에는 하나의 배열에서 다른 배열로 효율적으로 데이터를 복사하는 데 사용할 수 있는 arraycopy 메서드가 있습니다.

public static void arraycopy(Object src, int srcPos,
                             Object dest, int destPos, int length)


두 Object 아규먼트는 복사할 src 배열과 이 복사한 src 배열을 복사할 dest 배열을 지정합니다. 세 개의 int 아규먼트는 src 배열의 시작 위치, dest 배열의 시작 위치 및 복사할 src 배열 엘리먼트의 수를 지정합니다.

다음 ArrayCopyDemo 프로그램은 String 요소의 배열을 선언합니다. System.arraycopy 메서드를 사용하여 배열 구성 요소의 일부를 두 번째 배열로 복사합니다.

class ArrayCopyDemo {
    public static void main(String[] args) {
        String[] copyFrom = {
            "Affogato", "Americano", "Cappuccino", "Corretto", "Cortado",   
            "Doppio", "Espresso", "Frappucino", "Freddo", "Lungo", "Macchiato",      
            "Marocchino", "Ristretto" };
        
        String[] copyTo = new String[7];
        System.arraycopy(copyFrom, 2, copyTo, 0, 7);
        for (String coffee : copyTo) {
            System.out.print(coffee + " ");           
        }
    }
}


이 프로그램의 출력은 다음과 같습니다.

Cappuccino Corretto Cortado Doppio Espresso Frappucino Freddo

 

 

Array Manipulations

배열은 프로그래밍에서 사용되는 강력하고 유용한 개념입니다. Java SE는 배열과 관련된 일반적인 조작 작업 (복사, 정렬 및 배열 검색과 같은)을 수행하기 위한 몇 가지 메서드를 제공합니다. 예를 들어, ArrayCopyDemo 예제는 src 배열의 엘리먼트를 수동으로 반복하고 각 엘리먼트를 dest 배열에 배치하는 대신 System 클래스의 arraycopy 메서드를 사용합니다. 이는 내부적으로 수행되며, 개발자가 메서드를 호출하기 위해 한 줄의 코드만 사용할 수 있도록 합니다.

편리성을 위해, Java SE는 java.util.Arrays 클래스에서 배열 조작을 수행하기 위한 여러 메서드를 제공합니다. 예를 들어, 이전 예제를 java.util.Arrays 클래스의 copyOfRange 메서드를 사용하도록 수정할 수 있습니다. 이는 ArrayCopyOfDemo 예제에서 볼 수 있습니다. 차이점은 copyOfRange 메서드를 사용하면 메서드를 호출하기 전에 dest 배열을 생성할 필요가 없다는 것입니다. 왜냐하면 dest 배열이 copyOfRange 메서드에 의해 반환되기 때문입니다.

class ArrayCopyOfDemo {
    public static void main(String[] args) {
        String[] copyFrom = {
            "Affogato", "Americano", "Cappuccino", "Corretto", "Cortado",   
            "Doppio", "Espresso", "Frappucino", "Freddo", "Lungo", "Macchiato",      
            "Marocchino", "Ristretto" };
        
        String[] copyTo = java.util.Arrays.copyOfRange(copyFrom, 2, 9);        
        for (String coffee : copyTo) {
            System.out.print(coffee + " ");           
        }            
    }
}

 

이 프로그램의 출력 결과가 ArrayCopyDemo의 main method의 출력과 동일하다는 것을 알 수 있습니다. copyOfRange 메서드의 두 번째 파라미터는 복사할 범위의 초기 인덱스를 포함하고 있으며, 세 번째 파라미터는 복사할 범위의 최종 인덱스를 배제합니다. 이 예제에서 복사할 범위에는 인덱스 9에 있는 배열 엘리먼트가 포함되지 않습니다 (이는 문자열 "Lungo"를 포함합니다).

java.util.Arrays 클래스의 메서드들이 제공하는 몇 가지 유용한 작업에는 다음과 같은 것들이 있습니다:

  • 배열에서 특정 값을 검색하여 해당 값이 위치한 인덱스를 얻는 작업 (binarySearch 메서드).
  • 두 배열을 비교하여 동일한지 여부를 결정하는 작업 (equals 메서드).
  • 배열의 각 인덱스에 특정 값을 배치하는 작업 (fill 메서드).
  • 배열을 오름차순으로 정렬하는 작업. 이는 순차적으로(sort 메서드를 사용) 또는 병렬적으로(parallelSort 메서드를 사용하여 Java SE 8에서 소개됨) 수행할 수 있습니다. 다중 프로세서 시스템에서 큰 배열을 병렬적으로 정렬하는 것이 순차적인 배열 정렬보다 빠릅니다.
  • 배열을 소스로 사용하는 스트림을 생성하는 작업 (stream 메서드). 예를 들어, 다음 문장은 이전 예제와 같은 방식으로 copyTo 배열의 내용을 출력합니다:
java.util.Arrays.stream(copyTo).map(coffee -> coffee + " ").forEach(System.out::print);


스트림에 대한 자세한 내용은 Aggregate Operations을 참조하십시오.

  • 배열을 문자열로 변환하는 작업. toString 메서드는 배열의 각 엘리먼트를 문자열로 변환하고, 쉼표로 구분한 후 대괄호로 둘러싸는 작업을 수행합니다. 예를 들어, 다음 문장은 copyTo 배열을 문자열로 변환하고 출력합니다:
System.out.println(java.util.Arrays.toString(copyTo));

 

이 statement는 다음과 같이 출력됩니다:

[Cappuccino, Corretto, Cortado, Doppio, Espresso, Frappucino, Freddo]

 

Summary of Variables

자바 프로그래밍 언어에서 "필드"와 "변수"라는 용어를 모두 사용합니다. 인스턴스 변수(정적이 아닌 필드)는 클래스의 각 인스턴스마다 고유합니다. 클래스 변수(정적 필드)는 static 수식자로 선언된 필드입니다. 클래스가 몇 번이나 인스턴스화되었는지에 관계없이 클래스 변수의 복사본이 정확히 하나 있습니다. 지역 변수는 메서드 내부에서 임시 상태를 저장합니다. 파라미터는 메서드에 추가 정보를 제공하는 변수입니다. 지역 변수와 파라미터는 항상 "변수"로 분류됩니다(필드가 아님). 필드나 변수를 명명할 때는 따라야 하는 규칙과 규칙이 있습니다.

여덟 가지 기본 데이터 타입은 다음과 같습니다: byte, short, int, long, float, double, boolean 및 char. java.lang.String 클래스는 문자열을 나타냅니다. 컴파일러는 위의 타입의 필드에 디폴트값을 할당할 수 있습니다. 지역 변수에는 디폴트 값이 할당되지 않습니다. 리터럴은 고정된 값의 소스 코드 표현입니다. 배열은 단일(동일한) 타입의 고정된 수의 값을 보유하는 컨테이너 객체입니다. 배열의 길이는 배열이 생성될 때 설정됩니다. 생성 후에는 길이가 고정됩니다.