diff --git a/.vscode/ChangeSeparator.bat b/.vscode/ChangeSeparator.bat new file mode 100644 index 0000000..5f571e7 --- /dev/null +++ b/.vscode/ChangeSeparator.bat @@ -0,0 +1,13 @@ +@echo off + +@REM Usage: get_package_name.bat + +set "java_file=%1%" + +@REM Convert path separators to dots +set "package_name=%java_file:\=.%" + +@REM Remove ".java" extension +set "package_name=%package_name:.java=%" + +echo %package_name% diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..051cfeb --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type" : "java", + "name" : "Debug java", + "request" : "launch", + "mainClass" : "${file}", + "console" : "integratedTerminal", + "cwd" : "${workspaceFolder}", + "internalConsoleOptions" : "neverOpen", + } + ], +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..f6952a2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,18 @@ +{ + "workspaceKeybindings.CustomTasks.enabled": true +} +// User >> keybindings.json +// [ +// { +// "key" : "ctrl+shift+j", +// "command" : "workbench.action.tasks.runTask", +// "when" : "config.workspaceKeybindings.CustomTasks.enabled", +// "args" : "Run Java" +// }, +// { +// "key" : "ctrl+shift+i", +// "command" : "workbench.action.tasks.runTask", +// "when" : "config.workspaceKeybindings.CustomTasks.enabled", +// "args" : "Clean Java class files" +// } +// ] \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..d2b5243 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,128 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + + // List of variables in VsCode : + // https://code.visualstudio.com/docs/editor/variables-reference + + "version" : "2.0.0", + + // basics for general + "type" : "shell", + "options" : {"cwd" : "${workspaceFolder}"}, // should be project's directory + "problemMatcher": [], + + // terminal properties for each platform + "windows" : {"options": {"shell": { + "executable": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", // absolute path to Powershell + "args" : [ + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command" + ]}}}, + "linux" : {}, + "osx" : {}, + + // revealing options for general + "presentation" : { + "echo" : true, + "reveal" : "always", + "focus" : true, + "panel" : "shared", + "showReuseMessage" : true, + "clear" : false, + "revealProblems" : "onProblem" + }, + "promptOnClose" : false, + + "tasks" : [ + { + "label" : "Build Java", + "group" : "build", + + "command" : "javac", + "args" : [ + "-g", + "${file}" + ], + + "detail" : "Compile current Java file", + "icon" : { + "id" : "file-code", + "color" : "terminal.ansiBlue" + }, + }, + + { // Keyboard Shortcuts : cmd + shift + J + "label" : "Run Java", + "group" : "build", + + "command" : "java", + "dependsOn" : ["Build Java"], + + // CLI for window powershell | in window, `\` is used as separator, causing `java.lang.NoClassDefFoundError` + "windows" : { + "command" : "${workspaceFolder}${/}.vscode${/}ChangeSeparator.bat", // use `ChangeSeparator.bat` to convert separator like unix + "args" : [ + "${relativeFileDirname}/${fileBasenameNoExtension}", + "|", + "ForEach-Object", + "{", + "java", + "$_", + "}" + ], + }, + + // CLI for unix shell | in unix, `/` is used as separator + "linux" : {}, "osx" : {}, + "args" : ["${relativeFileDirname}/${fileBasenameNoExtension}"], + + "presentation" : {"clear": true}, // clear terminal before execution + "detail" : "Compile & Execute current Java file", + "icon" : { + "id" : "run-all", + "color" : "terminal.ansiGreen" + } + }, + + { // Keyboard Shortcuts : cmd + shift + I + "label" : "Clean Java class files", + "group" : "none", + + // CLI for window powershell + "windows" : { + "command" : "Get-ChildItem", + "args" : [ + "${workspaceFolder}", + "-Recurse", + "|", + "Where{$_.Name", + "-Match", + "'class'}", + "|", + "Remove-Item" + ] + }, + + // CLI for unix shell + "linux" : {}, "osx" : {}, + "command" : "find", + "args" : [ + "${workspaceFolder}", + "-name", + "\\*.class", + "-type", + "f", + "-delete" + ], + + "detail" : "Clean every Java class files in Working Directory", + "icon" : { + "id" : "clear-all", + "color" : "terminal.ansiCyan" + }, + } + ], +} diff --git a/makefile b/makefile index 8648a99..10050a8 100644 --- a/makefile +++ b/makefile @@ -1,8 +1,4 @@ Project_directory = ~/Desktop/Coding/God_of_java_practice -Practice_directory = ${Project_directory}/Practice -Scripts_directory = ${Project_directory}/scripts -Code_directory = ${Scripts_directory}/*/code - clean: - rm -rf ${Practice_directory}/*.class ${Code_directory}/*.class + find ${Project_directory} -name \*.class -type f -delete diff --git a/scripts/ch_03/extra/reserved_words_in_java.md b/scripts/ch_03/extra/reserved_words_in_java.md index 524aa03..d6858d5 100644 --- a/scripts/ch_03/extra/reserved_words_in_java.md +++ b/scripts/ch_03/extra/reserved_words_in_java.md @@ -119,7 +119,7 @@ ###### `private`, `protected`, `public` : `접근 제어자`, `access modifier` - `접근 제어자` 키워드는 클래스 내 메서드, 필드, 내부 클래스 등의 접근을 제어하는 키워드이다. - `private` 키워드를 이용할 시, 해당 클래스의 내부에서만 접근 가능하다. -- `protected` 키워드를 이용할 시, 해당 클래스의 내부와 해당 클래스를 상속받은 클래스 내부에서만 접근 가능하다. +- `protected` 키워드를 이용할 시, 해당 클래스의 내부와 해당 클래스를 상속받은 클래스 내부에서만 접근 가능하다. 더불어 같은 `package` 에 속한 경우에도 접근 가능하다. - `public` 키워드를 이용할 시, 해당 클래스 외부에서도 접근 가능하다. ###### `abstract` diff --git a/scripts/ch_08/README.md b/scripts/ch_08/README.md index 9b16684..c1251f0 100644 --- a/scripts/ch_08/README.md +++ b/scripts/ch_08/README.md @@ -6,6 +6,7 @@ - [`10. Pass by value, Pass by reference`](./section_10_11.md) - [`11. 매개 변수를 지정하는 특이한 방법`](./section_10_11.md) +--- ### What I learned from this chapter diff --git a/scripts/ch_09/README.md b/scripts/ch_09/README.md new file mode 100644 index 0000000..5eec3e4 --- /dev/null +++ b/scripts/ch_09/README.md @@ -0,0 +1,18 @@ + +### Chapter 09 : 자바를 배우면 패키지와 접근 제어자는 꼭 알아야 해요 + +- [`1. 패키지는 그냥 폴더의 개념이 아니에요`](./section_01_04.md) +- [`2. 패키지 이름은 이렇게 지어요`](./section_01_04.md) +- [`3. import 를 이용하여 다른 패키지에 접근하기`](./section_01_04.md) +- [`4. 자바의 접근 제어자`](./section_01_04.md) + +--- + +### What I learned from this chapter + +이번 챕터에서는 `Java` 의 `package` 에 관해 배웠다. + +애초에 큰 관점에서 봤을 때, 다른 언어의 모듈, 라이브러리와 다른 점이 없기에 어려운 점은 없었다. +다만 세부적으로 봤을 때, 어느 클래스들이 같은 `package` 에 속해있으면 참조 가능하다는 점, `import` 구문은 `class body` 속에 선언될 수 없다는 점 등이 달랐다. + +그리고 내용이 조금 널널한 김에 `Run Java`, `Clean Java class files` 같은 `task` 를 만들었다. 이를 단축키로 지정했고 좀 더 편하게 공부할 수 있을 것 같다. diff --git a/scripts/ch_09/code/README.md b/scripts/ch_09/code/README.md new file mode 100644 index 0000000..a1dc50b --- /dev/null +++ b/scripts/ch_09/code/README.md @@ -0,0 +1,9 @@ + +### Chapter 09 : 자바를 배우면 패키지와 접근 제어자는 꼭 알아야 해요 - 정리해 봅시다. + +- `[1]` : `godofjava` 폴더 아래에 `b` 라는 폴더를 만들자. +- `[2]` : `b` 폴더 아래에 `array`, `control`, `operator`, `variable` 이라는 폴더를 만들자. +- `[3]` : `ArrayMain.java` 파일을 `godofjava/b/array` 폴더로 옮기자. +- `[4]` : `ArrayMain.java` 파일을 열어 `b.array` 라는 패키지로 선언하자. +- `[5]` : `ArrayMain` 클래스가 제대로 컴파일 되는지 확인해 보자. +- `[6]` : `b.control` 폴더에는 `ControlIf`, `b.operator` 폴더에는 `OperatorConditional`, `b.variable` 폴더에는 `VariableTypes` 클래스를 각각 이동하고, 패키지를 선언한 뒤 컴파일해 보자. diff --git a/scripts/ch_09/code/b/array/ArrayMain.java b/scripts/ch_09/code/b/array/ArrayMain.java new file mode 100644 index 0000000..d7bcc87 --- /dev/null +++ b/scripts/ch_09/code/b/array/ArrayMain.java @@ -0,0 +1,7 @@ +package scripts.ch_09.code.b.array; + +// file compiles successfully + +public class ArrayMain { + +} diff --git a/scripts/ch_09/code/b/control/ControIf.java b/scripts/ch_09/code/b/control/ControIf.java new file mode 100644 index 0000000..c935211 --- /dev/null +++ b/scripts/ch_09/code/b/control/ControIf.java @@ -0,0 +1,7 @@ +package scripts.ch_09.code.b.control; + +// file compiles successfully + +public class ControIf { + +} diff --git a/scripts/ch_09/code/b/operator/OperatorConditional.java b/scripts/ch_09/code/b/operator/OperatorConditional.java new file mode 100644 index 0000000..b62360c --- /dev/null +++ b/scripts/ch_09/code/b/operator/OperatorConditional.java @@ -0,0 +1,7 @@ +package scripts.ch_09.code.b.operator; + +// file compiles successfully + +public class OperatorConditional { + +} diff --git a/scripts/ch_09/code/b/variable/VariableTypes.java b/scripts/ch_09/code/b/variable/VariableTypes.java new file mode 100644 index 0000000..2bcc4ee --- /dev/null +++ b/scripts/ch_09/code/b/variable/VariableTypes.java @@ -0,0 +1,9 @@ +package scripts.ch_09.code.b.variable; + +// file compiles successfully + +public class VariableTypes { + public static void main(String[] args) { + + } +} diff --git a/scripts/ch_09/code/solution.md b/scripts/ch_09/code/solution.md new file mode 100644 index 0000000..0dd004d --- /dev/null +++ b/scripts/ch_09/code/solution.md @@ -0,0 +1,9 @@ + +### Chapter 09 : 자바를 배우면 패키지와 접근 제어자는 꼭 알아야 해요 - 정리해 봅시다. + +- [`문제 설명`](./README.md) + +--- + +문제에서 제시한 그대로 만들면 된다. +다만 `"정리해 봅시다"` 중 `import 는 클래스 내에 선언해도 되나요?` 문항이 있는데, 이는 사용될 수 없다. diff --git a/scripts/ch_09/section_01_04.md b/scripts/ch_09/section_01_04.md new file mode 100644 index 0000000..4e5990f --- /dev/null +++ b/scripts/ch_09/section_01_04.md @@ -0,0 +1,211 @@ + +### Chapter 09 : 자바를 배우면 패키지와 접근 제어자는 꼭 알아야 해요 + +- [`1. 패키지는 그냥 폴더의 개념이 아니에요`](#1-패키지는-그냥-폴더의-개념이-아니에요) +- [`2. 패키지 이름은 이렇게 지어요`](#2-패키지-이름은-이렇게-지어요) +- [`3. import 를 이용하여 다른 패키지에 접근하기`](#3-import-를-이용하여-다른-패키지에-접근하기) +- [`4. 자바의 접근 제어자`](#4-자바의-접근-제어자) + + +--- + +### `1. 패키지는 그냥 폴더의 개념이 아니에요` + +`"Java 애플리케이션을 개발할 때 클래스들을 분류하지 않으면 이름이 중복되거나, 어떤 클래스가 어떤 일을 하는지 혼동되는 일이 발생한다."` + +`Java` 에서 `package` 를 이용하는 정확한 이유가 책에 실려있어 인용했다. + +`package` 를 이용할 때는 다음과 같은 규칙을 따라야 한다. +- 1. `package` 선언은 소스의 가장 첫 줄에 있어야만 한다. +- 2. `package` 선언은 소스에 단 하나만 존재할 수 있다. +- 3. `package` 이름과 현재 소스가 위치한 폴더 이름이 같아야 한다. 이를 어길 경우 `java.lang.NoClassDefFoundError` 와 같은 에러가 나올 수 있다. +- 4. `package` 이름은 `java` 로 시작해선 안된다. `(Java 는 된다)` 이를 어길 경우 `java.lang.SecuritySeception` 이 발생한다. + +--- + +### `2. 패키지 이름은 이렇게 지어요` + +`Java` 패키지 `naming` 은 다음과 같은 관용이 있다. + +|`패키지 시작 이름`|`내용`| +|---|---| +|`java`|`Java` 기본 패키지 `(Java 벤더에서 개발)`| +|`javax`|`Java` 확장 패키지 `(Java 벤더에서 개발)`| +|`org`|일반적으로 비 영리단체 `(오픈소스)` 의 패키지| +|`com`|일반적으로 영리단체 `(회사)` 의 패키지| + +또한 `package` 이름은 모두 소문자로 쓰는 관용이 있으며, ~~(정말 당연히)~~ `Java` 의 예약어를 사용하지 않는 관용이 있다. + +--- + +### `3. import 를 이용하여 다른 패키지에 접근하기` + +`Java` 에서 `package` 가 있을 때, 같은 `package` 에 있는 클래스들과 `java.lang` `package` 에 있는 클래스들만 찾을 수 있다. 그래서 다음과 같이 파일이 존재해도 참조 가능하다. + +``` +javapackage +├── Package1.java +├── Package2.java +└── sub + └── Sub1.java + └── Sub2.java + +2 directories, 3 files +``` +```java +// Package1.java +package javapackage; + +public class Package1 { + Package2 temp1; // available + Appendable temp2; // available | java.lang 에 속하는 클래스 중 하나 + ... +} +``` + +하지만 `import` 를 이용해 다른 패키지의 클래스에 접근할 수 있다. + +```java +// Package2.java +package javapackage; + +// import javapackage.sub.*; --> imoprt every class in `javapackage.sub` directory +import javapackage.sub.Sub1; + +public class Package2 { + Sub1 temp1; // available + Sub2 temp2; // available + ... +} +``` + +위 `import` 를 보면 `*` 를 사용한 것을 볼 수 있다. 하지만 `*` 을 사용할 시, **해당 `package` 에 속한 클래스들** 불러온다. **하위 패키지에 속한 클래스는 불러오지 않음에 유의하자.** + +덧붙여 `JKD 1.5` 이후 버전부터 `import static` 이라는 것이 추가되었다. 이는 `static` 한 것들 `(클래스 변수, static 메서드)` 을 불러오고자 할 때 용이하다. + + +``` +javapackage +├── PackageStatic.java +└── sub + └── SubStatic.java + +2 directories, 2 files +``` +```java +// sub/SubStatic.java +package javapackage.sub; + +public class SubStatic { + public final static String CLASS_NAME = "SubStatic class"; + public static void substaticmethod() + { + System.out.println("This is sub static method"); + } +} +``` +```java +// PackageStatic.java +package javapackage; + +import javapackage.sub.SubStatic; + +import static javapackage.sub.SubStatic.CLASS_NAME; +import static javapackage.sub.SubStatic.substaticmethod; + +// import every "statics" in SubStatic class +import static javapackage.sub.SubStatic.*; + +// before JDK 1.5 +SubStatic.CLASS_NAME; +SubStatic.substaticmethod(); + +// onward JDK 1.5 +CLASS_NAME; +substaticmethod(); + +// both ways are available + +// not allowed +// import static javapackage.sub.* +``` + +`JDK 1.4` 까지는 `SubStatic.CLASS_NAME` 와 같은 방법을 이용해야 했다. 하지만 `1.5` 부터는 `CLASS_NAME` 처럼 사용할 수 있다. + +만약 `*` 를 이용해 `import` 하면 `SubStatic` 속한 모든 `"static 한 것들"` 을 가져온다. + +`*` 를 이용해 가져오려면 `import` 의 마지막은 `package` 가 아니라 특정 클래스로 명시해 줘야 한다. `(import static javapackage.sub.* 처럼 사용할 수 없다)` + +만약 `import` 하면서 어느 클래스, 메서드 등의 이름이 중복된다면, `"참조가 애매하다"` `(reference is ambiguous)` 라는 컴파일 에러를 뱉어낸다. 이를 해결하려면 클래스의 `FQN` `(Fully Qualified Name)` 을 이용해 사용해야 한다. + +```java +package javapackage; + +import javapackage.sub.SubPackage1; + +// not available +// import javapackage.sub.sub_sub.SubPackage1; + +SubPackage1 temp1; // <-- javapackage.sub.SubPackage1 +javapackage.sub.sub_sub.SubPackage1 temp2; // <-- javapackage.sub.sub_sub.SubPackage1 +``` + +만약 `import` 한 것들 중 현재 `scope` 에서 중복되는 것이 있다면, `inner scope` 에 있는 것을 우선시해 인식한다. `(C/C++ 의 scope 와 비슷하게 생각하면 된다)` + +```java +package javapackage; + +import static javapackage.sub.SubPackage.CLASS_NAME; + +public class SupPacakge { + // In this class, SubPackage.CLASS_NAME will never be referenced directly + public static CLASS_NAME = "SupPacakge"; + + public static void main(String[] args) + { + System.out.println(CLASS_NAME); + TempClass test = new TempClass(); + test.method(); + } +} + +class TempClass { + public void method() + { + System.out.println(CLASS_NAME); + } +} +``` +``` +SupPacakge +SubPackage +``` + +`System.out.println(CLASS_NAME)` 은 클래스 변수를 참조한 반면, `test.method` 는 `SubPackage.CLASS_NAME` 을 참조한 것을 확인할 수 있다. + +--- + +### `4. 자바의 접근 제어자` + +`Java` 의 `접근 제어자` `(Access modifier)` 에는 4 가지 가 있다. + +- 1. `public` + 어디서든 접근 가능하다 + +- 2. `protected` + 같은 패키지 내에 있거나, 상속받는 경우에만 접근할 수 있다 + +- 3. `package-private` + 아무런 접근 제어자를 적어주지 않을 때이며, `package-private` 라고도 불린다. 같은 패키지 내에 있을 때만 접근할 수 있다. + +- 4. `private` + 해당 클래스 내에서만 접근 가능하다 + +이 중 `package-private` 제어자는 처음 들어봤다. 그런데 관련 내용을 찾아보니 `"정말로 유용"` 한지는 조금 의문점이 있는 듯 하다. [`[1]`](#1--java-package-private-은-안쓰나요---hyeon9maks-tec-blog) + + +--- + +### Reference + +- ##### [`[1] : Java package-private 은 안쓰나요? - Hyeon9mak's Tec blog`](https://hyeon9mak.github.io/Java-dont-use-package-private/)