on
JAVA(Programmers) - 1
Java 공부 시작!
맨날 공부 시작 시작 말만 하다가 이제서야 제대로 시작하려고 한다. 나의 주력언어로 쓸 것이니 처음 부터 하나하나 꼼꼼히 보도록 할 것이다.
Java의 탄생 - 출처
- 1995년에 썬 마이크로시스템즈에서 발표한 객체지향 언어. 현재는 오라클에 인수됨.
Java의 특징 - 출처
- 쉬운 언어이다.
- C와 C++언어의 문법을 기본으로 차용하여 개발된 언어
- C와 C++ 이 가진 어려운 문법인 포인터와 다중 상속 제거
- C와 C++에 비해 쉬운 언어이다.
- 플랫폼에 독립적이다.
Java
는 JVM 만 있으면 윈도우, 리눅스, 맥등 어떤 플랫폼에서도 실행이 가능
- 객체지향 언어이다.
- 메모리 관리를 자동으로 해준다.
- C에서는 동적으로 메모리를 할당해주면 사용자가 코드 상에 반드시
free()
와 같은 함수로 할당해준 메모리를 해제해줘야 했다. 그러나Java
에서는Garbage Collector(GC)
가 알아서 이러한 메모리들을 알아서 할당 해제 시켜준다.
- C에서는 동적으로 메모리를 할당해주면 사용자가 코드 상에 반드시
JVM(Java Virtual Machine)이란?
JVM은 Java 프로그램뿐 아니라
Java bytecode
로 컴파일된 다른 언어로 작성된 프로그램도 컴퓨터에서 실행할 수 있도록 하는 가상 시스템. - 출처: wikipedia
위에서 Java
는 어느 플랫폼에서도 실행이 가능하다고 했다. 과연 왜 그럴까?
그 이유는 바로 C
와는 달리 Java
는 OS에 상관없이 JVM위에서 실행되기 때문이다. C
처럼 어떤 OS인지에 따라 영향을 받을 수 있는게 아니기 때문에 플랫폼에 독립적이다. Java
에 대한 유명한 말 중 하나인 “Write once, run erveywhere” 이 있는데 어떤 OS인지에 상관없이 동일한 코드가 어느 곳에서든 동일하게 실행이 된다는 뜻이다. 물론 JVM 자체는 OS에 영향을 받기 때문에 해당 OS에 맞는 JVM으로 설치를 해야한다.
C
같은 경우는 소스코드가 컴파일하면 .obj
라는 assembly code
가 되고, 어셈블러로 machine code
가 된다. Java
의 실행단계는 간략하게 말하자면 아래와 같다. (아래 사진과 문항은 해당 블로그를 참고했다)
Hello.java
라는 소스코드를Java compiler
로 컴파일 한다.- 컴파일이 되면,
Hello.class
라는Java byte code
가 생성된다. Java byte code(Hello.class)
를 JVM이 읽고 실행하게 된다.- Java Class Loader : JVM안으로 class파일들을 load한다. Loading 된 class파일들은
Runtime Data Area
에 배치된다.Runtime Data Area
: JVM이 프로그램을 수행하기 위해 OS로 부터 별도로 할당 받은 메모리 공간.
- Execution Engine : Load된 Class의
ByteCode
를 실행하는 Runtime Module이 바로 Execution Engine. Execution Engine은Java bytecode
를 명령어 단위로 읽어서 실행. - 실행 엔진은
Java bytecode
를 명령어 단위로 읽어서 실행.
Java Array
// array declare
final static int arrSize = 5;
int[] arrInt = new int[arrSize];
int[] arrInt2 = new int[]{1,2,3,4,5};
int[] arrInt3 = {1,2,3,4,5};
배열의 크기를 반드시 명시해줘야한다.
Array length
int[] arr1 = new int[20];
int arrLength = arr1.length; // arr1 길이 : 20
Array length vs String length
근데 배열을 배우다가 문득 들었던 생각인데, 분명 나는 Java
에서 length()
라는 method
를 쓴 기억이 있는데 배열에서는 length
를 써야했었다. 뭐가 다르길래 하나는 method
를 쓰고, 하나는 instance variable
를 쓰는 것일까 싶어서 찾아봤다.
해당 링크를 참고하여 정리해봤다.
- Array
length
: 선언될 때 배열같은 경우는 반드시 배열의 크기를 명시해줘야 하고, 이는 고정된 값으로서 바뀔 수 없다. 따라서length
변수는 직접적으로 배열의 크기를 얻기 위해 사용되어진다. - String
length()
: String class의static method
이다.length()
를 사용하여 문자열의 길이를 구한다. 왜냐하면 해당 객체에 다양한 연산이 진행돼서 문자열의 길이가 변할 수 있기 때문에 변수를 사용하여 곧바로 구할 수가 없다.- 여기서 의문이 들었다. programmers라는 사이트의 강의에서 “String은 다른 class와는 다르게 한번 생성되면 변하지 않는다”라고 배웠기 때문이다. 근데 해당 링크는 “length of a string can be modified using the various operations on an object.”라고 돼있었다. 과연 뭐가 맞는 것일까 싶어서 더 찾아봤다.
String literal vs new declare
해당 의문을 해결하기 위해서는 먼저 이것부터 알아야 한다. String object는 2가지 방법으로 선언할 수 있다.
String str1 = "Hello"; // literal
String str2 = new String("Hello"); // new operator
하나는 constructor
를 안쓰고 선언했고, 하나는 constructor
로 선언했다. 여기서 분석을 해보자.
str1, str2
: reference variable.instance
의 위치를 가리키고 있다. 그렇기 때문에 reference인 것.String
: 문자열을 선언할 때 쓰는 class."Hello"
: “상수가 저장되는 memory”에 저장된다.- 상수가 저장되는 메모리 : String Constant Pool. Heap영역에 있다.
literal
선언을 하게 되면, 해당 문자열의 값은String Constant Pool
에 저장된다.
- 상수가 저장되는 메모리 : String Constant Pool. Heap영역에 있다.
new String("Hello")
:constructor
로 선언을 해줬다. Heap영역에 새로운instance
생성.
이렇게 분석을 해봤다. 아직까지는 둘의 차이가 뭔지 잘 모를 수 있다. 더 자세히 말해보도록 하겠다.
먼저 literal
선언을 하게 되면, 해당 문자열은 Heap영역의 String Constant Pool
에 저장이 된다. 근데 또 다른 literal
선언을 했는데 같은 문자열 값을 썼다면, String Constant Pool
에 이미 존재하는 값이므로 2번째로 선언된 reference variable
은 1번째로 선언된 reference variable
와 같은 곳을 가리킨다.
그러나 new String()
으로 선언을 했다면, String Constant Pool
에 같은 문자열이 있든지 말든지 무조건 새로운 instance
를 생성하는 것이다.
이렇게 설명만 들으면 이해가 잘 안갔기에 코드로 구현을 해봤다. Java
에는 System.identityHashCode("reference variable")
라는 함수가 있다.System.identityHashCode()
는 객체의 고유한 hashcode를 리턴하는 method
이다. reference variable
이 어디를 가리키는지를 출력을 해준다. literal
선언된 2개의 변수가 가리키는 instance
가 같다면, 해당 함수의 결과 값 또한 같아야 할 것이다.
public class StringTest{
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "Hello";
String str3 = "Hi";
System.out.println("변경 전 str1(Hello literal)->" + System.identityHashCode(str1));
String str4 = new String("Hello");
String str5 = new String("Hello");
str1 = str1 + " World!";
String str6 = "Hello World!";
System.out.println("변경 후 str1(Hello World literal)->" + System.identityHashCode(str1));
System.out.println("str2(Hello literal)->" + System.identityHashCode(str2));
System.out.println("str3(Hi)->" + System.identityHashCode(str3));
System.out.println("str4(Hello new)->" + System.identityHashCode(str4));
System.out.println("str5(Hello new)->" + System.identityHashCode(str5));
System.out.println("str6(Hello World literal)->" + System.identityHashCode(str6));
}
}
programmers git:(main) ✗ java StringTest
변경 전 str1(Hello literal)->705927765
변경 후 str1(Hello World literal)->366712642
str2(Hello literal)->705927765
str3(Hi)->1829164700
str4(Hello new)->2018699554
str5(Hello new)->1311053135
str6(Hello World literal)->118352462
reference variable
은 Java의 Stack영역에 생긴다. 위 그림은 코드의 reference variable
들이 참조하고 있는 곳을 나타낸 것이다.
-
str1(변경 전), str2
:literal
선언되어"Hello"
라는 같은 문자열 값을 갖는다. 따라서 참조하는 위치는 같다. 코드의 출력 결과 또한변경 전 str1(Hello literal)->705927765 str2(Hello literal)->705927765
으로 같다.
-
str3
:"Hi"
라는 문자열 값을 갖는다.String Constant Pool
에"Hi"
가 저장된다. 따라서 참조하는 위치는"Hi"
라는instance
값이 있는 곳이다. -
str4, str5
: 같은"Hello"
문자열을 갖는instance
를 각각 생성했다. 따라서 가리키는 곳은 서로 다르다. 코드의 출력은str4(Hello new)->2018699554 str5(Hello new)->1311053135
보다시피 다른 것을 알 수 있다. 물론
str1(변경 전), str2
와도 다르다. -
str6
:literal
선언되어"Hello World!"
라는 문자열 값을 가진다. 인스턴스의 위치를 가리키고 있다. -
str1(변경 후)
: instance값을 변경해서"Hello World!"
라는 문자열로 만들었으나 이는 기존의 인스턴스가 변한 것이 아니라 새로운 인스턴스가 생성된 것이다. 따라서str1
에 있는 빨간 점선이 바로 새로 생성된 인스턴스를 가리키는 것이다.변경 후 str1(Hello World literal)->366712642 str6(Hello World literal)->118352462
str1(변경 후)
와str6
이 같은"Hello World!"
라는 문자열 값을 가진다고 해도, 서로str1(변경 후)
는 변경됐을 때 시점으로 새로운 인스턴스가 따로 생성된 것이기 때문에 서로 가리키는 인스턴스가 다르다.
참고 사이트
https://starkying.tistory.com/entry/what-is-java-string-pool
https://www.guru99.com/java-stack-heap.html
https://changhozz.tistory.com/entry/String%ED%81%B4%EB%9E%98%EC%8A%A4%EC%9D%98-%ED%8A%B9%EC%A7%95
https://www.tutorialspoint.com/what-are-the-differences-between-length-and-length-in-java
https://pienguin.tistory.com/entry/JAVA-%EC%9E%90%EB%B0%94-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EC%8B%A4%ED%96%89-%EA%B3%BC%EC%A0%95-%EB%B0%8F-%EA%B8%B0%EB%B3%B8-%EA%B5%AC%EC%A1%B0