Ch02. Java 언어의 기본 문법
"Hello POCU" 출력하기
package academy.pocu;
public class HelloPocu {
public static void main(String[] args){
System.out.println("Hello POCU");
}
}
- Java에서는 언제나 클래스가 필요
- 한 .java 파일에는 최고 레벨 public 클래스가 하나만 있어야 함
- 클래스 안에 다른 클래스를 넣을 수 있음
- 내포(nested) 클래스
- 내포 클래스는 public 이어도 상관 없음
- main 함수는 반드시 이 시그내처대로 만들어야 함
- 매개변수 : String[] args
- 문자열 배열
- 커맨드 라인으로부터 받은 인자
Java에도 printf()가 있다
String name = "Mumu";
int score = 64;
System.out.printf("%s's score: %d\n", name, score);
- print() 대신 format() 메서드를 사용해도 동일하게 동작
올바른 새 줄 문자 추가 방법
String name = "Mumu";
int score = 64;
System.out.printf("%s's score: %d%s", name, score, System.lineSeparator());
- 플랫폼에 알맞은 새 줄 문자를 반환하는 메서드
가변인자
public PrintStream printf(String format, Object... args);
- ... 앞에 '자료형'을 반드시 넣어야 함
- 해장 '자료형'의 데이터만 인자로 전달 가능
- Object라는 자료형을 쓸 경우 모든 자료형을 넣을 수 있음
package
package academy.pocu;
- 연관된 클래스들끼리 묶는 기법
- C#의 namespace와 비슷
패키지 종류
- 자바 기본(built-in) 패키지
- 이름이 java로 시작하는 패키지들
- ex) java.lang, java.util, ...
- 프로그래머가 직접 만든 패키지(user-defined)
패키지의 목적
- 이름 충돌 문제를 해결
패키지 이름 짓기
- 패키지 이름의 중복을 최소화해야 함
- 보통 회사의 도메인 명을 패키지 이름에 사용(단, 역순으로)
주의: 패키지 이름만 적으면 안 됨!
- 패키지명과 똑같은 폴더 트리에 .java 파일을 넣어야 함
커맨드라인에서 컴파일하기
hellopocu>javac -d class\ src\academy\pocu\*.java
javac 명령어
javac -d <컴파일 결과물을 저장할 경로> <컴파일할 .java 파일>
- .java 파일이 무사히 컴파일 되면 .class 파일이 나옴
- 이름은 .java 파일과 동일
- 이 .class 파일에는 바이트 코드가 들어있음
- 옵션: -d
- .class 파일을 저장할 경로
- '컴파일 결과물을 저장할 경로' 안에 .java 파일의 패키지 구조와 동일한 폴더가 생김
java -classpath <class 파일 위치> <클래스 이름>
- 바이트 코드를 실행하는 명령어(*.class)
- '클래스 이름'
- 이 .class 파일에는 반드시 main 함수가 들어 있어야 함
- 클래스 이름 앞에 반드시 패키지 이름을 붙어야 함(academy.pocu.HelloPocu)
jar <option> <jar 파일 이름> <최상위 패키지 경로>
- .jar 파일을 만드는 명령어
- 옵션: -cf
- c: create(생성)
- f: 만들어질 .jar 파일의 이름을 지정. f 뒤에 파일명이 와야 함
Manifest 파일
- 자바 애플리케이션의 정보를 담고 있는 메타데이터 파일
- .jar 파일을 만들 때 이 파일을 같이 넣어줄 수 있음
- .jar 파일의 시작점(메인 함수)에 대한 정보를 넣어야 함
다시 .jar 파일 만들기
hellopocu\class> jar -cfm ..\lib\hellopocu.jar ..\src\Manifest.txt academy
- 추가된 옵션: -m
- .jar 파일을 만들 때 manifest 파일도 함께 넣겠단 의미
import
import java.util.Random;
import java.util.*;
java.lang
- 기본 패키지
- 모든 .java 파일에 자동으로 임포트
- System은 java.lang 안에 있는 클래스 중 하나
부호 있는 자료형만 존재
- 예외: char는 부호 없는 자료형만
- 음수 배열 색인과 음수 나이
- 이런 걸 예방하도록 코드를 방어적으로 작성해야 한다는 의미
- 다른 언어들은 대부분 부호 없는 자료형을 지원
부호 없는 자료형 부재의 또다른 문제
- 보통 컴퓨터에서 색상을 저장할 때 8비트를 사용(0~255)
- Java에서 포현하려면 byte로 불가능
- 그래서 short를 씀
Integer 클래스
int num = 4294967295;
int num = Integer.parseUnsignedInt("4294967295");
System.out.printIn(num);
String numStr = Integer.toUnsignedString(num);
System.out.printIn(numStr);
- int의 값을 부호 없는 수처럼 처리할 수 있는 도우미 함수 제공
- parseUnsignedInt()
- compareUnsigned()
- divideUnsigned()
- toUnsignedString()
- 등등
- 그러나 불편함
유니코드지만 16비트인 char
- Java의 유일한 부호 없는 자료형
- char로는 모든 유니코드를 표현할 수 없음
- U+FFFF보다 큰 유니코드를 표현하려면 String을 사용해야 함
불리언형
boolean isStudent = false;
기본 자료형은 모두 '값형'임을 잊지 말자
- 모든 값형은 복사 가능
- 참조형은 그렇지 않음
String
- 클래스는 언제나 참조형
- String 클래스의 구성
- 연속된 문자를 저장하는 메모리
- 위 데이터를 처리할 수 있는 각종 메서드
String과 new 키워드
String name1 = "Nana";
String name2 = new String(name1);
String name3 = new String("Elsa");
- 클래스형이므로 new를 이용해서 개체 생성 가능
Java의 String은 immutable
String name = "Nana";
name[0] = 'C'; // 컴파일 오류
- C++에서는 가능
- 일단 생성된 String 개체는 변경 불가
- 바꾸고 싶다면 새로운 문자열을 만들어야 함
정수 리터럴
int num1 = 1234;
long num2 = 123467890L;
long num3 = 987654321l;
long num4 = 123456784235435; // error
int num1 = 0xFFFF; // 16진수 리터럴
int num2 = 0b11001010; // 2진수 리터럴
int num3 = 01234; // 8진수 리터럴
부동 소수점 리터럴
float num1 = 10.0F;
float num2 = 3.14F;
double num3 = 92341.234D;
double num4 = 2314.56d;
double num5 = 43525.91; // 생략해도 무방
문자, 문자열 리터럴
char ch = 'a';
String helloPocu = "Hello POCU";
String alphabet = "\u03b1\u03b2\u03b3"; //alphabetagamma
String helloWorld = "Hello\nWorld";
- 문자 리터럴
- 문자열 리터럴
- 유니코드 표현
- 이스케이프 문자 : \로 시작
기타 리터럴
String msg = null;
int num = 12_345_678;
float pi = 3.14_15F;
long hexNum = 0xFF_EC_DE_5E
- null
- 참조형에 사용 가능한 리터럴
- 의미 : 참조하는 대상이 없음(C의 널 포인터)
- _
- 큰 숫자의 가독성을 높이기 위해 사용(쉼표 찍듯이)
- Java7부터 사용 가능
Java의 상수형 변수: final 키워드
final int MAX_STUDENT = 10;
MAX_STUDENT = 30; // compile error
final 키워드를 붙일 수 있는 곳
- 지역 변수
- 클래스 멤버 변수
- 메서드 매개변수
- 클래스와 메서드
final과 멤버 변수
public class StudentManager {
public final int MAX_STUDENT = 10;
// ...
}
// 클래스 내부
public static final int MAX_CLASS = 7;
final과 메서드
public int add(final float op1, final float op2){
op1 += 1; // compile error
}
final 변수의 초기화1 : 선언과 동시에
public class StudentManager {
public final int MAX_STUDENT = 10;
public void printScores() {
final int MAX_CLASS = 5;
// ...
}
// ...
}
final 변수의 초기화2 : 사용하기 전에만
public void printScores() {
final int MAX_CLASS;
MAX_CLASS = 5;
System.out.prinf("%d", MAX_CLASS);
}
- C와 C#의 const와는 다르게 final은 선언 후에 초기화 가능
- 지역 변수일 경우 그 final 변수를 사용하기 전에만 초기화해주면 됨
public class StudentManager {
final int MAX_STUDENT;
public void printScores() {
MAX_STUDENT = 10; // compile error
}
}
- 멤버 변수일 경우
- 생성자에서 초기화 가능
- 그 외의 메서드에서 초기화 할 경우 컴파일 오류가 발생
public class StudentManager {
final int MAX_STUDENT; // OK
public void printScores() {
final int MAX_CLASS; // OK
MAX_CLASS = 5; // OK
System.out.printf("%d", MAX_CLASS);
}
public StudentManager() {
MAX_STUDENT = 10; // OK
}
}
Javadoc 주석
/**
* <설명>
* @<태그> <태그>에 대한 설명
*/
- 클래스, 메서드, 멤버 변수, 인터페이스 위에 위치
- 이로부터 자동으로 Java API 문서를 새엇ㅇ
- C#도 ///주석을 통해 비슷한 기능 지원
- C나 C++에서는 Doxygen 사용
- @<태그>를 이용하여 설명을 추가할 수 있음
- @param: 메서드의 매개변수
- @return: 메서드의 반환값
산술 연산자
- 기본저긍로 숫자를 표현하는 자료형만 피연산자로 사용 가능
- 유일한 예외: 문자열 더하기
- 불리언형에 사용 불가
- 문자형(char)은 가능
- 자바에서 char는 정수
문자열은 참조형!
- 문자열 변수에 저장돼 있는 건 값이 아닌 메모리 주소
- 따라서 ==은 주소를 비교
- 그 주소에 있는 실제 문자열을 비교하지 않음
허나 주소를 공유하는 경우가 있음
String name1 = "Nana";
String name2 = "Nana";
- String을 new로 생성하지 않은 경우
equals() 메서드
public boolean equals(Object obj);
boolean isSame1 = name1.equals(name2);
boolean isSame2 = name1.equals(name3);
boolean isSame3 = name1.equals(name4);
boolean isSame4 = name1.equals("Nana");
- 두 String을 비교하는 함수
Java는 연산자 오버로딩을 지원 안 함
- 다행히도 메서드 오버로딩은 지원
- 그러나 Java에서 딱 하나 지원하는 오버로딩 된 연산자
- String용 +와 += 연산자
Java의 문자열 비교 베스트 프랙티스
- 문자열이 참조형이란 사실을 잊지 말 것
- ==을 쓰지 말 것
- 그 대신 equals() 메서드를 사용할 것
>>>연산자
- 부호 없는 비트 연산자
- 오른쪽으로 이동 후 남는 공간을 '0'으로 채움
- Java에는 부호 없는 자료형이 없기에 이렇게 연산자를 따로 만듦
case에 사용 가능한 자료형
- 정수형(char, byte, int...), 열거(enum)형, String
String month = "January";
switch(month){
case "March":
System.out.printIn("Spring");
break;
case "July":
System.out.printIn("Summer");
break;
default:
System.out.printIn("Unknown");
break;
}
case 안에서 break를 빼먹으면?
- switch 문을 탈출하지 않고 그 아래 있는 코드를 계속 실행
- fall-through라고 함
continue, break, goto
- goto는 없음
break와 라벨
break <라벨 이름>;
int[] scores; // {10, 20, 30, 40}
outer:
for (int i=0; i<scores.length; i++){
if(scores[i] > 30){
break outer;
}
System.out.print(" " + scores[i]); // " 10 20 30"
}
- "라벨 이름"이 달린 코드 블록을 탈출함
- C의 goto와는 달리 어느 코드로든 점프할 수 있는 게 아님
- continue 역시 라벨을 사용할 수 있다
foreach 스타일 for문
int[] scores = {10, 20, 30, 40};
for (int score : scores){
System.out.prinf("%d ", score);
}
- 어떤 컬렉션이든 순회할 수 있는 반복문
- C에는 없지만 Java와 C#에는 있음
- 차이점은 C#은 foreach, Java는 기존의 for 키워드를 이용
함수
public static int add(final int op1, final int op2){
return op1 + op2;
}
함수 호출과 참조형 인자
- 참조형을 인자로 넘길 때는 조심해야
- C에서 포인터를 넘기는 것과 마찬가지
- 메서드 안에서 참조형 인자의 값을 바꾸면 원본이 바뀜
final 참조형 매개변수
public static Vector add(final Vector v1, final Vector v2){
// ...
v1.x += 5432.0f; // ok. 주소가 가리키는 값은 변경 가능
v1 = new Vector(20, 30); // 컴파일 오류. 주소 변경은 불가능
// ...
}
- 참조형 변수는 주소를 저장
- 따라서 final이 붙으면 그 주소만 변경 못 함
- 그 주소가 가리키는 값은 여전히 바꿀 수 있음
1차원 배열
<자료형>[] <변수명> = new <자료형>[<크기>];
<자료형> <변수명>[] = new <자료형>[<크기>];
int[] nums = new int[5]; // 더 흔한 방법
int scores[] = new int[20];
- C#처럼 new 키워드를 사용해서 메모리 할당을 해야
다차원 배열
<자료형>[][] <변수명> = new <자료형>[<크기>][<크기>];
<자료형>[][][] <변수명> = new <자료형>[<크기>][<크기>][<크기>];
- C#의 '배열의 배열'이나 C의 '포인터 배열'과 비슷
- 즉, 안쪽 배열의 길이가 다 다를 수 있음
Java의 열거형
// 독자적으로 선언
public enum Subject {
KOREAN,
ENGLISH,
MATH
}
// 클래스 내부에 선언
public class SchoolManager {
public enum Subject {
KOREAN,
ENGLISH,
MATH
}
//...
}
Java의 열거형에서 못 하는 것
// 컴파일 오류
public enum Direction
{
North = 5,
South = 10,
East = 15,
West = East + 10
}
- 각 원소에 원하는 값을 대입하지 못함
Java의 열거형은 클래스형
public enum Subject {
KOREAN,
ENGLISH,
MATH;
private int hours;
public int getHours() {
return hours;
}
}
- 멤버 변수와 메서드를 가질 수 있음
- 그러나 그냥 데이터로만 사용할 것
- 멤버 변수 및 메서드도 있을 경우, 맨 마지막 상수 뒤에 ; 추가
열거형과 생성자
public enum Subject {
KOREAN(2),
ENGLISH(3),
MATH(6);
private int hours;
public int getHours() {
return hours;
}
Subject(int h){ // 언제나 private
hours = h;
}
}
- 생성자도 추가할 수 있음
- 단, 생성자는 암시적으로 private
- public 혹은 protected 불가
- 각각의 원소(상수)가 만들어질 때 생성자 호출
- 위 열거형에서는 총 3번 호출됨
- 따라서, 각 원소들은 생성자가 요구하는 매개변수를 반드시 넘겨줘야 함
열거형과 new 키워드
Subject subject1 = new Subject(); // compile error
Subject subject2; // ok
Subject subject3 = Subject.MATH // ok
- 열거형 개체를 만들 때는 new를 안 씀
var
var num = 10;
var message = "Hello World!";
var error; // compile error
- Java 10 부터 지원
- 컴파일러가 알아서 자료형 추론
- 선언과 동시에 값을 대입해야
var 사용 시 주의할 점
var scores = new int[20]; // ok
var number[] = new int[20]; // compile err
var world = new int[100][200][300]; // ok
var names = {"Lulu", "Nana", "Mama"} // compile err
람다 표현식
() -> System.out.printIn("Hi");
(name) => Systsem.out.printIn("Hi " + name);
- 이름 없는 함수로 내포(nested) 함수라고도 부름
기존 패키지 시스템의 한계
- 애플리케이션이 사용하는 클래스 목록을 찾는 공식적인 방법이 없음
- 누락된 클래스가 있다면 실행 중에 그것을 사용하려 할 때 오류 발생
- 따라서 사용 중인 패키지에 있는 모든 클래스를 같이 배포하는 게 일반적
- 문제점
- Java 버전에 증가함에 따라 Java 자체 제공 라이브러리의 크기가 커짐
- 안 사용하는 클래스까지 같이 배포할 경우 쓸데 없이 용량이 커짐
- 패키지 안에 있는 모든 public 클래스를 아무나 사용할 수 있음
모듈
- Java9부터 지원
- 패키지보다 상위 개념
- 패키지를 내포함
- 장점
- 정말 필요한 패키지만 포함할 수 있음(경량화)
- 프로그램 시작 시 누락된 모듈을 확인 가능
- 어떤 모듈이 사용하는 다른 모듈 목록을 찾기 쉬움
- 모듈 사용자에게 공개할 클래스를 특정할 수 있음
module-info.java
- 모듈 간의 의존관계를 정의한 파일
- 컴파일 과정에서 .class 파일로 바뀜
- 모든 모듈에 반드시 존재해야 함
- 이 파일 안에 들어가는 내용
- 본 모듈 안에서 사용하는 외부 모듈 목록
- 본 모듈 사용자에게 공개할 패키지 목록
module pocu.adademy.core {
exports pocu.academy.core.math;
requires java.sql;
}
- exports : 본 모듈 사용자가 pocu.academy.core.math 패키지를 사용할 수 있게 공개해 줌
- 아무것도 노출하고 싶지 않다면 exports를 생략
- requires : 본 모듈에서 사용하는 외부 모듈
'프로그래머 > Java Managed Programming' 카테고리의 다른 글
[개체지향 프로그래밍] 개체 모델링 | 클래스 다이어그램 | 유연성 | OOP (0) | 2021.02.13 |
---|---|
[개체지향 프로그래밍] 접근 제어자 | getter/setter | 캡슐화 | 추상화 (0) | 2021.02.07 |
[개체지향 프로그래밍] 개체 생성 | 가비지 콜렉터(garbage collector) | 생성자(constructor) (0) | 2021.02.07 |
[개체지향 프로그래밍] 클래스(class) | 접근 제어자(public, private) | 인스턴스(instance) (0) | 2021.02.07 |
[개체지향 프로그래밍] 개체지향 프로그래밍이란? | 개체지향 프로그래밍의 필요성 | 개체지향 프로그래밍 특성 (0) | 2021.01.17 |