JVM: 자바가 실행되기 위해서 필요: 자바 실행 환경(JRE) -> java
명령어만, 버추얼 머신만 있는 경우
JRE + 개발툴 -> 개발 환경: JDK -> java
+ javac
명령어까지
역사
콘솔 창에
java --version
과 javac --version
을 터미널에 입력하여 설치 여부/버전을 확인한다.명령어 관하여
javac ClassName.java
java ClassName
Error: Could not find or load main class
클래스 경로를 확인하지 못 해서 발생한 문제임;.
을 환경 변수 마지막에 넣어주면, 추가적으로 현재 확인하고 있는 경로에서도 클래스 파일을 찾는다.일일히 자바 파일을 컴파일하는 귀찮다. -> 빌드를 자동화하자: 빌드 툴의 등장
자바의 빌드 툴
Gradle 직접 설치해보기
gradle --version
을 터미널에 입력하여 설치 여부 확인Gradle 사용해보기
프로젝트 생성: gradle init
명령어
프로젝트 구조: tree 명령어 이용해서 보면
├─.gradle
├─app
│ └─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─programmers
│ │ │ └─java
│ │ └─resources
│ └─test
│ ├─java
│ │ └─com
│ │ └─programmers
│ │ └─java
│ └─resources
└─gradle
└─wrapper
build.gradle
빌드 스크립트이다.Task명령어
gradle build
, gradle run
등
build.gradle
에 tasks.named("test")
형태로 작업이 명시되어 있다.
gradle test
를 실행하면 위의 tasks
의 test
라 명명된 작업이 실행된다.그런데, build
. run
의 경우는 위와 같은 task
설명이 없다.
자바 프로젝트에서 공통적으로 많이 쓰이는 부분들의 taskset은 이미 규정되어 있다.
-> plugin
gradle tasks명령어로 종류 확인 가능
------------------------------------------------------------
Tasks runnable from root project 'HelloWorld'
------------------------------------------------------------
Application tasks
-----------------
run - Runs this project as a JVM application
Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles main classes.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the main classes.
testClasses - Assembles test classes.
Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.
Distribution tasks
------------------
assembleDist - Assembles the main distributions
distTar - Bundles the project as a distribution.
distZip - Bundles the project as a distribution.
installDist - Installs the project as a distribution as-is.
Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the main source code.
Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'HelloWorld'.
dependencies - Displays all dependencies declared in root project 'HelloWorld'.
dependencyInsight - Displays the insight into a specific dependency in root project 'HelloWorld'.
help - Displays a help message.
javaToolchains - Displays the detected java toolchains.
outgoingVariants - Displays the outgoing variants of root project 'HelloWorld'.
projects - Displays the sub-projects of root project 'HelloWorld'.
properties - Displays the properties of root project 'HelloWorld'.
tasks - Displays the tasks runnable from root project 'HelloWorld' (some of the displayed tasks may belong to subprojects).
Verification tasks
------------------
check - Runs all checks.
test - Runs the test suite.
gradle tasks
extension 설치하여 간편하게 확인, 실행 가능하다.VS Code(코드편집용)와 gradle, 그리고 extension들을 이용해도 일일히 각각을 실행해 줘야 하는 불편함이 있다.
-> 통합 개발 환경(IDE; Integrated Development Environment)이 필요한 까닭
자바 개발자들이 주로 사용하는 IDE
IDE는 생산성을 증대시켜준다.
단축키를 적절히 사용하면 생산성이 더 증가한다.
자바를 쓴다고 해서 포인터를 몰라서는 안 된다!
alloc/free
를 개발자가 신경 쓰지 않아도 될 뿐이다.자바의 primitive value를 제외한 모든 것은 reference value다!
primitive: boolean
, byte
, int
, short
, long
, float
, double
, char
int a =100
일 때, a
를 전달 -> 값을 전달
Integer b = 100
일 때, b
를 전달 -> b
의 레퍼런스를 전달
Call by value / Call by reference
array는 reference처럼 취급한다.
int[]
, boolean[]
문자열을 만드는 방법
String
클래스의 생성자를 사용해서 만드는 방법 String stringByConstructor = new String("Hello, World!")
String stringByLiteral = "Hello, World!"
생성자를 이용할 경우
new 연산자에 의해 메모리가 할당되기에
항상 새로운 인스턴스가 생성
아래의 코드에서
String stringByConstructor1 = new String("Hello, World!");
String stringByConstructor2 = new String("Hello, World!");
두 변수 stringByConstructor1
, stringByConstructor2
는 동일한 인자를 받지만
두 String
가 참조하는 주소는 서로 다르다. 같은 값("Hello, World!")을 저장한 메모리가 두 군데라는 것이다.
따라서 stringByConstructor1 != stringByConstructor2
이다!
리터럴을 이용할 경우
이미 존재하는 값을 재사용하는 것
문자열 리터럴 값은 클래스가 메모리에 로드될 때 자동적으로 미리 생성된다!
아래의 코드에서
String stringByLiteral1 = "Hello, World!";
String stringByLiteral2 = "Hello, World!";
두 변수 stringByLiteral1
, stringByLiteral2
은 동일한 주소를 참조한다.
생성자로 String
변수를 생성하는 것과 달리 이 경우 메모리가 낭비되지 않으며,
stringByConstructor1 == stringByConstructor2
이다!
따라서 문자열을 비교할 때는 ==
연산자를 사용하지 말고 equals()
메서드를 사용하자.
==
연산자의 경우 두 값이 동일한 인스턴스인가를 비교한다. (동등성, identity)
반면 equals()
는 동치성(equity)에 대한 비교를 목표하는, 모든 객체에 적용되는(Object
) 메서드이다.
String
은 인코딩 방식이 같으며, 문자열 내용의 값이 동일한 경우 true
를 리턴하는 식으로 equals()
를 오버라이드 했다.
모든 문자열 리터럴 값은 컴파일 시에 클래스 파일에 저장된다.
동일 내용의 문자열 리터럴은 한 번만 저장된다.
문자열 리터럴도 String
의 인스턴스이고, 불변이기에 같은 값이면 - 하나의 인스턴스를 공유하면 되기 때문이다.
소스파일에 포함된 모든 리터럴의 목록을 담은 클래스 파일이 있다.
이 파일이 클래스 로더에 의해 메모리에 올라갈 때, 리터럴들은 JVM 내의 상수 저장소(Constant pool)에 저장된다.
자바가 String
클래스를 특수하게 관리하는 수단
String s = "";
for (int i = 0; i < 10; i++) {
s += i;
}
System.out.println("s = " + s);
위의 코드가 실행될 경우
Contstant Pool에는 "", "0", "01", "012", ...이 모두 저장된다.
따라서 String
에는 +=
연산을 사용하는 것이 성능상 좋지 않다.
StringBuffer
를 사용하라.
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 10; i++) {
sb.append(i);
}
System.out.println("sb = " + sb);
길이가 0인 배열이 존재할 수 있듯이,
길이가 0인 char[]
를 value
로 가지고 있는 String
이 있을 수 있다 -> 빈 문자열
String emptyString = ""
은 가능하지만,
char emptyChar = ''
은 불가능하다.
char
자료형 변수에는 반드시 하나의 문자를 지정해야 한다.초기화
String s = null;
char c = '\u0000';
이런 방식의 초기화도 가능하지만,
String s = "";
char c = ' ';
이런 방식의 초기화가 권장된다.
String
관련 유용한 정보String[] split(String regex)
: 인자로 받은 regex
로 구분하여 문자열을 자른다.
자바 8에서는 다음 두 기능이 추가되었다:
join()
static String join(CharSequence delimiter, CharSequence... elements)
static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
split()
과 반대로 구분자로 문자열을 결합한다.
StringJoiner
StringJoiner()
생성 인자로 구분자를 받는다.add(String s)
:로 합칠 String
을 받는다.2byte
: 즉 16bit
문자체계다.20bit
로 확장하였다: 보충 문자(supplementary characters), (JDK 1.5부터 지원)byte
크기 자료형인 char
가 아니라 int
로 다뤄야 하는 경우가 생겼다.getBytes(String charsetName)
을 이용하여 인코딩 변환한 byte[]
를 리턴받을 수 있다.Charset
자료형으로도 받을 수 있다(오버라이딩).printf()
와 사용법이 동일하다.
기본형 → String
: valueOf()
를 이용하는 방식
+ ""
해주는 방식보다 성능적으로 좋다.Wrapper클래스
로 값이 반환되지만, 오토박싱에 의해서 기본 자료형으로 자동 변환된다.String
→ 다른 자료형(기본형도 포함): toString()
toString()
메서드는 Object
의 메서드, 따라서 모든 객체에 존재한다.
새 클래스를 만들 경우 적절히 오버라이드 하라.
StringBuffer
와 StringBuilder
String
클래스는 Constant Pool
에 의해 관리되는 특이한 클래스로, 불변이기에
+
연산이 메모리 낭비를 일으킬 수 있다.
→ StringBuffer
를 사용하면 해결 가능
StringBuffer
String
과 유사한 구조
char[] value
에 값을 저장하는구조버퍼(buffer)
문자열을 저장하고 편집하기 위한 공간
value
를 버퍼로 사용한다.
Thread-safe하다!
StringBuffer
인스턴스가 생성될 때, 인자로 버퍼의 크기를 지정 가능하다.
미지정시 16으로 초기화된다.
버퍼의 길이가 부족해질 경우 버퍼의 크기를 늘려주는 작업이 이루어진다.
배열의 복사는 메모리를 잡아먹기 때문에 적절한 양을 할당해주는 것이 필요하다.
append()
: 추가 기능, 현재 주소를 반환한다.
append(StringBuilder sb)
가 규정되어 있기 때문에
sb.append("a").append("b")
형태의 연쇄 호출이 가능하다.`
StringBuffer
vs StringBuilder
StringBuffer | StringBuilder |
---|---|
Thread-safe(동기화) | 동기화 기능을 뺐음 |
성능 면에서 손해 있음 | 성능 면에서 더 나음 |
StringBuffer
에서 동기화 기능만 뺀 클래스가 StringBuilder
StringBuffer
쓰자.모든 객체의 최상위 객체
즉, 모든 객체에는 Object
의 메서드를 호출할 수 있음
이 글에서는 간단하게 다루고 추후 이펙티브 자바 요약 정리 링크와 별도의 학습 포스트로 연결할 예정
포함해선 안 될 파일들
*.class
, *.jar
, build/
단 라이브러리에 dependency 걸린 것들은 남기거나, 다운 받을 수 있게 해야gradle
, gradlew
, gradle.bat
등 -> gradle wrapper
명령어로 생성 가능로컬 환경에 의존적인 절대경로
간단하게 처리하는 방식: gitignore.io
gradle wrapper를 ingore하느냐에 대한 논쟁
포함하지 않아야 한다
포함해야 한다
참고
gradle wrapper
를 포함시킨다.개인적인 결론
학습 환경에서는 gradle wrapper
를 포함시키지 않는다.
운영하고자 하는 프로젝트의 경우 포함시키는 것을 우선하되,
당연히 팀 컨벤션에 따라간다.
String
부분은 남궁성, <자바의 정석>의 요약 + a임