[include(틀:상위 문서, top1=Java)] [include(틀:문자 입력시 주의, c1=\\0, c2=\\\\0)] [include(틀:프로그래밍 언어 문법)] [목차] == 개요 == [[Java]](자바)의 문법을 설명하는 문서다. == 기본 == 기본적으로 자바의 코드의 구조는 다음과 같다. [package 이름 명시 (필수는 아님)] [import할 패키지 명시] [주요 클래스 구현] [부차적 클래스 및 함수 구현] 클래스 선언 시에 *.java 파일의 이름과 동일한 이름으로 클래스 이름을 정해야 한다. HelloWorld.java 파일에서는 주요 클래스의 이름이 HelloWorld이여야 한다. 부차적 클래스의 이름을 정할 때에는 상관없다. 하나의 *.java 파일 안에는 하나의 주요 클래스만 정의되어야 한다. C-족 언어답게 아주 기본적인 문법들은 C와 거의 동일하다. for-문, while-문, switch문, if-else if-else문, 산술 연산자 등. 여기에도 그런것들을 다 적으면 중복이 되니까 [[C언어/문법]]을 참고하도록 하자. 다만 자바는 포인터를 제공하지 않으므로 포인터에 관한건 다 무시해주자. == 편집 지침 == 소스 코드로 예시를 들 때 ||\{{{#!syntax java (소스코드) }}}|| 문법을 활용하여 소스코드를 써 주시기 바랍니다. 예시: {{{#!syntax java package myPackage; import java.io.*; public class myClass { public static void main(String[] args) { System.out.println("hello world!"); } } }}} == 메인 클래스 == === 메인 메서드 === 자바 프로그램을 실행하려면 어떤 클래스 안에 있는 메인 메서드가 필요하다. {{{#!syntax java public class Namu { public static void main(String[] args) { System.out.println("Namu Wiki"); } } }}} 자바로 콘솔에 뭔가를 띄우려면 System.out.println() 메서드를 사용하자. === 비메인 메서드 === 메인 메서드가 들어있는 클래스에 다른 정적 (static) 메서드를 써넣는게 가능하다. 양식은 접근자 static 반환형 이름(자료형 패러미터1, ...) {메서드 바디} 위에 있는 간단한 예제를 정적 메서드를 사용해서 구현해보자. {{{#!syntax java public class Namu { public static void main(String[] args) { printNamu(); } public static void printNamu() { System.out.println("Namu Wiki"); } } }}} == 클래스 == === 클래스 정의하기 === 당연하게도 커스텀 클래스를 만들수 있다. 예제를 통해 살펴보자. 클래스는 보통 각자 다른 .java 파일에 들어간다. 내부 클래스라는 개념이 있기는 하지만 그리 중요하진 않으므로 이 문단에서는 무시하자. {{{#!syntax java // Person.java public class Person { private String name; // 사람의 이름. 모든 객체가 각자 name을 얻는다. private static String species = "Homo sapiens"; // 클래스에 하나만 있는 변수. 모든 Person 객체가 이걸 공유. // 생성자 메서드. 객체를 생성할때 new 키워드와 함께 사용된다. public Person(String name) { // 자신의 변수를 참조할때 this를 쓸 수 있다. this.name = name; } public String getName() { return name; // this.name과 동일 } public static String getSpecies() { return species; } } // Main.java public class Main { public static void main(String[] args) { Person myPerson = new Person("John"); // 새로운 객체를 생성하려면 new 키워드를 사용하자 System.out.println(myPerson.getName()); // John System.out.println(Person.getSpecies()); // Homo sapiens } } }}} 클래스안에 비정적 메서드는 'static'을 생략한다. static과 non-static 메서드의 차이점은 간단하다. static 메서드는 객체에 상관없이 호출이 가능하다. 하지만 non-static 메서드는 특정 개체를 대상으로 호출해야 한다. non-static 메서드를 호출하려면 object.method()로 호출, static 메서드는 class.method()로 호출하자. === [[상속(프로그래밍)|상속]] === 상속을 하려면 extends 키워드를 사용하면 된다. 예제로 살펴보자. {{{#!syntax java // Student.java public class Student extends Person { private double gpa; public Student(String name, double gpa) { super(name); // 부모 클래스 Person의 생성자를 호출 this.gpa = gpa; } public double getGPA() { return gpa; } } // Main.java public class Main { public static void main(String[] args) { Student joe = new Student("Joe", 4.0); // Student는 Person이기도 하므로 Person의 getName() 메서드를 사용 할 수 있다. System.out.println(joe.getName()); // Joe. System.out.println(joe.getGPA()); // 4.0 } } }}} 자녀 클래스 내에서 상위 클래스의 메서드를 사용하고 싶다면 super 키워드를 사용하자. 참고로 이 예제에서 name을 사용하려고 하면 에러가 뜰 것이다. Person 클래스에서 name은 private 접근자를 가지는데, private 접근자를 가진 변수는 본 클래스 내에서만 직접 가져올 수 있다. Person 클래스에서 private String name;이 아니라 protected String name;을 쓰면 Student 클래스에서도 name을 자유롭게 사용할 수 있다. == 자료형 == {{{#!syntax java int namu; }}} namu라는 변수를 추가 한다. {{{#!syntax java namu = 3; }}} 같이 namu의 값을 정할 수 있다. {{{#!syntax java int namu = 3; }}} 시작과 동시에 저장 할 수도 있다. {{{#!syntax java System.out.println(namu); }}} 변수의 값을 출력 할 수도 있다. {{{#!syntax java namu = namuwiki; }}} 변수의 값을 이렇게 복사 할 수도 있다. 다음은 Java에서 기본적으로 제공하는 자료형이다. === 원시 자료형 === primitive type. 자바에선 원시 자료형이 몇개가 있는데, 가장 중요한것 몇개를 뽑자면 * int: 정수 (-3, 2, 122...) * double: 소수 (4.45, 1.0, 0.0...) * char: ASCII 문자 (a, C, !...) * boolean: 부울 (참, 거짓) 보다시피 원시 자료형 이름은 전부 소문자로 시작한다. 대문자로 시작한다면 원시 자료형이 아닌 참조 자료형, 즉 객체이다. 대표적인 예가 문자열인 String. 다음은 두 정수의 합을 반환하는 메서드이다. {{{#!syntax java public static int sum(int a, int b) { return a + b; } public static void main(String[] args) { int n1 = 10; int n2 = 12; System.out.println(sum(n1, n2)); // 22 } }}} ==== byte,short,char ==== byte는 -128 ~ 127까지를 저장 할 수 있다. short는 -32768 ~ 32767이다. char은 유니코드로,0~ 65535이다.유니코드란 텍스트를 수로 바꾼 것이다. {{{#!syntax java char namu = 'A'; }}} 면 namu는 65가 된다.A의 유니코드가 65기 때문이다. ==== int,long ==== int는 -2147483648 ~ 2147483647을 저장한다. long은 -9223372036854775808 ~ 9223372036854775807을 저장한다.그리고 long의 값이 int의 범위 (-2147483648 ~ 2147483647)를 초과하면, 수 뒤에 l이나 L을 붙여야 한다. {{{#!syntax java long namu = 1000000000000L; }}} === 래퍼 클래스 === Java에서는 원시 자료형과 관련 내장 함수를 포함하는 래퍼 클래스가 존재한다. Java 5 이상이면 동일한 데이터 형식을 공유하는 원시 자료형과 래퍼 클래스 사이에는 자동적으로 박싱과 언박싱을 할 수 있다. ||<table align=center> '''원시 자료형''' || '''래퍼 클래스''' || '''데이터 형식''' || || - || Object || 임의의 데이터 형식[* Object 클래스는 모든 클래스의 최상위 클래스이다.] || || boolean || Boolean || 부울대수 (true 또는 false) || || byte || Byte || 1바이트 정수 || || short || Short || 2바이트 정수 || || int || Integer || 4바이트 정수 || || long || Long || 8바이트 정수 || || - || BigInteger || 무제한 크기의 정수 || || float || Float || 4바이트 소수 || || double || Double || 8바이트 소수 || || - || BigDecimical || 무제한 크기의 소수 || || char || String || 문자 || === 컬렉션 === 자바에서는 컬렉션을 통해 여러개의 데이터를 저장할 수 있는 [[자료구조]]를 제공한다. 컬렉션에는 저장된 데이터를 관리할 수 있는 내장 함수까지 구현되어 있다. 또한, 컬렉션 중에서 상속으로 구현된 것들도 있다. 컬렉션은 기본적으로 모든 데이터 형식을 사용할 수 있도록 일반화 된 변수를 지원한다. 표에서 '''[컬렉션]<X>'''에 있는 X가 일반화 된 변수를 뜻한다. 즉, X 대신에 int가 들어갈 수도 있고 String이 들어갈 수도 있고 사용자가 정의한 클래스가 들어갈 수도 있다. ||<table align=center> '''컬렉션''' || '''상위 클래스''' || '''자료 구조''' || || List<X> || - || 리스트 기본형 || || ArrayList<X> || List<X> || 가변 배열 구조의 리스트 || || LinkedList<X> || List<X> || 단순 연결 리스트 || || Map<X> || - || 맵 기본형 || || HashMap<X> || Map<X> || 값의 중복을 허용하지 않는 맵 || || LinkedHashMap<X> || Map<X> || 엔트리의 순서를 변경할 수 없는 맵 || || TreeMap<X> || Map<X> || 엔트리의 정렬이 가능한 맵 || 컬렉션 자료구조에 대한 정렬이나 필터링에 필요한 함수는 '''Collections''' 클래스 (java.util.Collections)에서 제공하고 있다. === 일반화 변수 형식 === '''일반화 변수 형식''' (Generic Variable Type)은 어떠한 데이터 형식이던 매개변수나 리턴값으로 사용할 수 있는 일반화된 자료형을 뜻한다. 자세한 내용은 아래 항목에서 설명하고 있으니 참조하면 된다. == 일반화 프로그래밍 == 자바에서의 일반화 프로그래밍에 대한 간단한 서술. === 일반 메서드 === 메서드를 정의할때 패러미터 또는 반환 값을 미리 정해두지 않고 싶을때 사용한다. 일반 자료형은 주로 T나 U같이 대문자 알파벳을 사용한다. 일반 메서드를 사용하려면 일반 자료형을 <> 사이에 넣어주자. 여러개의 자료형을 사용하고 싶다면 사이에 콤마를 넣어주면 된다. {{{#!syntax java public static <T, U> T printAndReturn(T input1, U input2) { System.out.println(input1 + " " + input2); return input1; } public static void main(String[] args) { System.out.println(printAndReturn("Namu", 10)); /* 결과 : Namu 10 Namu */ } }}} === 와일드 카드 === 와일드카드 라는 것도 있다. 일반형 자료와 비슷하지만 간결한 대신 좀 제한적인 개념. 와일드카드를 나타내는 기호는 물음표 ("?"). 아래의 두 메서드는 똑같은 일을 하는데, 전자는 위에서 소개했던 방식이고, 후자는 와일드카드를 사용한 방식이다. {{{#!syntax java public static <T> int getLength1(List<T> myList) { return myList.size(); } public static int getLength2(List<?> myList) { return myList.size(); } }}} 보다시피 와일드카드가 읽기 약간 더 편하다. 따라서 가능하면 와일드카드를 사용하는게 좋다. 물론 그냥 일반 자료형을 사용해야 할때도 많다. === 바운딩 === 부등호 괄호안에 "extends" 또는 "super" 키워드를 사용하는 것. 이러므로써 자료형에 약간 제약을 걸 수 있다. 예를 들어서 <T extends Person>는 Person클래스 또는 Person을 상속하는 클래스를 뜻한다. 이때 상속은 직접적인 상속이 아니어도 된다. 예를 들어서 Person ← Student ← HighSchooler 이런식으로 상속관계가 있다면 HighSchooler도 T extends Person의 조건을 만족한다. 하지만 String 같은 자료형은 만족하지 못한다. "super"은 그와 반대다. <? super Student>라 하면 Student 클래스 또는 그의 부모/조상 클래스들을 의미한다. super는 오직 와일드 카드만이 쓸 수 있다. 예로 리스트에 담긴 숫자의 (부동 소숫점) 합을 구하는 메서드를 보자. {{{#!syntax java // 일반 자료형 public static <T extends Number> double sum1(List<T> list) { double sum = 0; for (T num: list) { sum += num.doubleValue(); } return sum; } // 와일드 카드 public static double sum2(List<? extends Number> list) { double sum = 0; for (Number num: list) { sum += num.doubleValue(); } return sum; } }}} === 일반 클래스 === 객체지향에 매우 충실한 언어답게 클래스를 짤때도 일반화 프로그래밍이 가능하다. 클래스 이름 뒤에 일반 자료형(들)을 <>안에 넣어주면 된다. 예를들면 {{{#!syntax java // Wrapper.java public class Wrapper<T> { private T content; public Wrapper(T content) { this.content = content; } public T getContent() { return this.content; } } // ... 메인 메서드 안 Wrapper<String> myWrapper1 = new Wrapper<>("Namu Wiki"); // new Wrapper뒤에 꼭 <>을 붙여주자. Wrapper<Integer> myWrapper2 = new Wrapper<>(44); System.out.println(myWrapper1.getContent()); // Namu Wiki System.out.println(myWrapper2.getContent()); // 44 }}} == 인터페이스 == Interface. 일부 다른 언어에서는 프로토콜 (Protocol)이라고도 한다. 상속과 다르면서도 미묘하게 비슷한 개념. 상속이 어느 클래스의 속성과 메서드를 '상속'한다면, 인터페이스는 어떤 클래스가 '구현'해야 한다. === 인터페이스 정의하기 === "interface" 키워드를 사용한다. 인터페이스를 만들때는 주로 추상 메서드만을 사용한다. 추상 메서드란 이 인터페이스/클래스에서 정의하지 않고, 구현/상속한 클래스에서 정의하는걸 말한다. 클래스에서는 추상 메서드를 만드려면 abstract 키워드를 붙여야하지만 인터페이스에서는 abstract가 디폴트다. Java 8부터는 비추상 메서드를 'default' 키워드를 써서 정의할 수 있다. {{{#!syntax java // Incrementable.java public interface Incrementable { String interfaceName = "Incrementable"; public void increment(); public default void printMessage() { System.out.println("디폴트 메서드"); } } }}} 인터페이스 내의 변수 (예제의 "interfaceName")는 디폴트로 static final이다. 어느 한 객체에 붙어있지도 않고 다른 변수를 대입할 수도 없다는 뜻. === 인터페이스 구현하기 === 'implements' 키워드를 사용한다. {{{#!syntax java public class Person implements Incrementable { /* 생략 */ // Incrementable의 모든 추상 메서드를 정의 public void increment() { age = age + 1; } } }}} 이제 Person은 Incrementable 인터페이스를 구현했다. 이제 다음과 같은 메서드에 Person 객체를 보낼 수 있다. {{{#!syntax java public static void example(Incrementable implementation) { implementation.increment(); implementation.printMessage(); } }}} 단 한개의 클래스를 상속할 수 있는것과는 달리 하나의 클래스가 여러 인터페이스를 구현할 수 있다. 구현과 상속을 동시에 할 수도 있다. {{{#!syntax java public class SubClass extends SuperClass implements IntOne, IntTwo, IntThree { // ... } }}} === 함수형 인터페이스 === Java 8에 추가된 개념. 단 하나의 추상 메서드를 가지는 인터페이스를 말한다. [[람다식]]을 지원하는 Java 8부터는 매우 특별한 취급을 받는다. [[분류:프로그래밍 언어 문법]]