Python
을 주로 사용해서 헷갈렸던 Java
문법을 정리해보려 한다.
자바 정리
자바 파일 작성시 주의 사항
- 패키지명은 반드시 소문자로 작성한다.
- 클래스 파일명은 반드시 대문자로 작성한다.
- 클래스명이 파일명이 되어야 한다.
문자열
공백 제거 - trim()
trim()
은 문자열 앞 뒤의 공백을 제거하지만 중간에 있는 공백은 제거하지 못한다.
1
2
3
4
5
6
7
8
9
10
11
12
String str1 = " TEST TEST ";
String str2 = " TEST TEST";
String str3 = "TEST TEST";
System.out.println("[" + str1.trim() + "]");
System.out.println("[" + str2.trim() + "]");
System.out.println("[" + str3.trim() + "]");
// 결과
[TEST TEST]
[TEST TEST]
[TEST TEST]
공백 제거 - replace()
replace(target, replacement)
를 이용하면 모든 공백을 제거할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
String str1 = " TEST TEST ";
String str2 = " TEST TEST";
String str3 = "TEST TEST";
System.out.println("[" + str1.replace(" ", "") + "]");
System.out.println("[" + str2.replace(" ", "") + "]");
System.out.println("[" + str3.replace(" ", "") + "]");
// 결과
[TESTTEST]
[TESTTEST]
[TESTTEST]
문자열 비교 - equals()
1
2
3
4
5
6
7
8
9
10
11
String s1 = "hello";
String s2 = "hello";
if (s1.equals(s2)){
System.out.println("same");
}else{
SYstem.out.println("different");
}
// 결과
same
배열
파이썬의 리스트(배열)와 비슷하지만, 자바에서는 배열을 선언한 후 새로운 값을 추가하기가 까다롭다.
배열을 사용하기보다는ArrayList
를 자주 사용한다고 한다.
배열 초기화
1
2
3
4
5
6
7
// 방법 1.
int[] arr; // 또는
int arr[];
arr = new int[] {1, 2, 3, 4, 5};
// 방법 2.
int[] arr = {1, 2, 3, 4, 5};
배열 출력
1
2
3
4
5
6
7
import java.util.Arrays;
arr = new int[] {1, 2, 3, 4, 5};
System.out.println("Arrays.toString()(으)로 출력 하기 : " + Arrays.toString(arr));
// 결과
Arrays.toString()(으)로 출력 하기 : [1, 2, 3, 4, 5]
1
2
3
4
5
6
7
8
9
// String에서 한글자씩 출력하는 방법
String str1 = "Java String?";
for (int i=0; i < str1.length(); i++){
System.out.print("i = " + str1.charAt(i) + " ");
}
// 결과
0 = J 1 = a 2 = v 3 = a 4 = 5 = S 6 = t 7 = r 8 = i 9 = n 10 = g
Java
에서는 왜 .cahrAt()
을 이용해야 하는가?
문자열은 한글자마다 메모리에 저장되는것이 아닌, 스트링풀에 저장되므로 .cahrAt()
을 이용해야한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 2차원 배열 출력
int [][] data = {
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10},
{11, 12, 13, 14, 15}
};
// 결과
data[0][0] = 1
data[0][1] = 2
data[0][2] = 3
data[0][3] = 4
data[0][4] = 5
⋮
data[2][3] = 14
data[2][4] = 15
for each를 왜 사용하지 않았는가?
for each
로 출력 가능한 자료형은 int
, double
, char
, ArrayList
이다.
for each
문을 사용할 때는 인덱스 정보를 직접 얻기 어렵고, 각 요소의 값만 얻을 수 있다.
배열의 요소 값만 필요한 경우에는 for each
를 사용하면 편리하다.
하지만 인덱스 정보가 필요한 경우에는 for
를 사용하는 것이 더 적합하다.
static
메소드 static
main 메소드 앞에는 반드시
static
을 붙여야한다.
static
메소드는static
메소드만 호출할 수 있다.
1
2
3
4
5
6
7
8
9
class Data{
static void show(){
...
}
public static void main(String[] args){
show(); // static 메소드는 static 메소드만 호출할 수 있다.
}
}
클래스 static
클래스에서 사용되는
static
은 클래스 변수(static variable)로 인스턴스가 공유하는 클래스당 한개만 생성되는 변수이다.
클래스 변수는 클래스.클래스 변수명으로 접근할 수 있다.
클래스 메소드 또한 클래스.클래스 메소드명으로 접근할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class Student {
static int numberOfStudent; // 클래스 변수(값을 공유)
String name; // 인스턴수 변수
Student(){
numberOfStudent++;
}
Student(String name){
numberOfStudent++;
this.name = name;
}
void print(){
System.out.println("name : " + name);
System.out.println("numberOfStudent : " + numberOfStudent);
}
static void print2(){
System.out.println("name : " + name); // 에러 static 변수만 올 수 있다.
System.out.println("numberOfStudent : " + numberOfStudent);
}
static void printNumberOfStudent(){
System.out.println("Student.printNumberOfStudent() : " + numberOfStudent);
}
}
public class Practice {
public static void main(String[] args){
System.out.println("Student.numberOfStudent : " + Student.numberOfStudent);
Student s1 = new Student("Alice");
s1.print();
Student s2 = new Student("Jack");
s2.print();
Student s3 = new Student();
System.out.println("Student.numberOfStudent : " + Student.numberOfStudent);
}
}
// 결과
Student.numberOfStudent : 0
name : Alice
numberOfStudent : 1
name : Jack
numberOfStudent : 2
name : null
numberOfStudent : 3
Student.printNumberOfStudent() : 3
static 블록과 non-static 블록
non-static
블록은 인스턴스를 생성할 때마다 블록이 먼저 수행되고 생성자를 다음으로 수행한다.
static
블록은 첫 번째 인스턴스를 생성하기 전에 딱 한번만 수행된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Student {
String name;
{
System.out.println("인스턴스 생성 전 실행");
}
static {
System.out.println("인스턴스 생성 전 단 한번만 실행");
}
}
public class Practice {
public static void main(String[] args){
Student s1 = new Student();
}
}
// 결과
인스턴스 생성 전 단 한번만 실행
인스턴스 생성 전
실행
클래스
파일에 클래스 한개 있는 경우 클래스명과 파일명이 일치해야한다. 파일에 클래스가 여러개 있는 경우
- 모든 클래스가
public
키워드를 갖지 않는 경우에는 어떤 클래스명도 파일명이 될 수 있다.public
키워드를 갖는 클래스가 있다면 그 클래스명을 파일명으로 해야한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// public 한개인 경우 : 파일명은 Test로 해야한다.
public class Test {
...
}
class Test2 {
...
}
class Test3 {
...
}
// public 여러개인 경우 : Test, Test2, Test3 모두 파일명이 될 수 있다.
class Test {
...
}
class Test2 {
...
}
class Test3 {
...
}
new
new
키워드를 사용하여 객체를 생성할 수 있다.
Class
에 생성자가 없다면new
할 때 디폴트 생성자가 자동으로 호출된다.
디폴트 생성자는 이름이 클래스명과 똑같고, 매개변수가 없다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Student {
static int numberOfStudent; // 클래스 변수(값을 공유)
String name; // 인스턴수 변수
Student(){ // 디폴트 생성자
numberOfStudent++;
}
Student(String name){
numberOfStudent++;
this.name = name;
}
void print(){
System.out.println("name : " + name);
System.out.println("numberOfStudent : " + numberOfStudent);
}
}
this
반드시 생성자 첫 줄에 한번만 사용해야한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Student {
static int numberOfStudent;
String name;
int age;
double score;
Student(String name){
numberOfStudent++;
this.name = name;
}
Student(String name, int age){
this(name); // 첫 줄에 한번 작성.
this.name = name;
numberOfStudent++;
}
Student(String name, int age, double score){
this(name); // 첫 줄에 한번 작성.
this(name, age); // Error.
this.name = name;
numberOfStudent++;
}
}
public, private, default, protected
private
같은 클래스에서만 접근이 가능하다.
- 접근자 :
get<인스턴스 변수명>
을 이용하여 인스턴스 변수의 값을 가져온다.- 변경자 :
set<인스턴스 변수명>
을 이용하여 인스턴스 변수의 값을 변경한다.
protected
패키지가 같거나 달라도 상속 관계에 있으면 접근이 가능하다.
default
상속과 관계없이 같은 패키지 안에서만 접근 가능하다.
public
어디서나 접근 가능하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Student {
public String name;
private int score;
int num;
// 접근자 (다른 접근제어도 사용 가능)
String getScore(){
return score
}
// 변경자 (다른 접근제어도 사용 가능)
void setScore(int score){
this.score = score;
}
}
public class Practice {
public static void main(String[] args){
Student s1 = new Student();
s1.name = "김민수";
s1.score = 10; // 에러
s1.num = 1;
// 변경자 호출
s1.setScore(100);
// 접근자 호출
System.out.println(s1.getScore());
}
}
상속
extends
키워드로 다른클래스를 상속받을 수 있다.
자식 객체를 생성하면 부모 생성자를 호출하고 다음으로 자식의 생성자를 호출한다.
만약 부모 클래스에 디폴트 생성자가 아닌 생성자가 하나라도 있으면 디폴트 생성자를 자동으로 제공하지 않는다.
1
2
3
4
5
6
7
8
9
class Parent {
Parent(int data){
}
}
class Child extends Parent {
Child(){} // 에러 발생
}
super
자식 클래스에서 부모 멤버에 접근하려면 사용하는 키워드이다.
super
를 사용할 때에도this
와 마찬가지로 생성자 맨 첫줄에 적어야한다.
super
와this
를 동시에 사용할 수 없다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Parent {
private String name;
private int age;
Parent(){}
Parent(String name, int age){
}
}
class Child extends Parent {
private String gender;
Child(){}
Child(String gender){
}
Child(String name, int age, String gender){
super(name, age); // 에러발생
this(gender)
}
}
final
final
클래스는 자식 클래스를 가질 수 없는 클래스이다.
인수턴스 변수 앞에final
은 상수라는 뜻이다.
final
메소드는 오버라이딩 할 수 없는 메소드이다.
지역변수로 지정된final
변수는 한번 값이 지정되면 변경이 불가능하다.
1
2
3
4
5
6
7
8
9
10
final class Data { // final 클래스
final private int x; // final 인스턴스 변수 x
final void print(){ // final 메소드
}
void test() {
final int data; // final 지역변수 data
}
}
다형성
다형성은 부모 클래스에 있는 멤버를 접근할 수 있으며, 자식 클래스에 오버라이딩 된 메서드가 존재한다면, 자식클래스의 메서드를 우선 접근하게 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Parent {
void print(){
System.out.println("parent print");
}
void print2(){
System.out.println("parent pirnt2");
}
}
class Child extends Parent {
void print() {
System.out.println("child print");
}
void check(){
System.out.println("child check");
}
}
public class Practice{
public static void main(String[] args){
Parent x = new Child();
x.print();
x.print2();
x.check(); // 에러
}
}
// 결과 ( x.check() 없을시 )
parent print
parent print2
다형성을 사용하는 이유
- 코드 재사용성 향상
- 다형성을 사용하면 하위 클래스들을 공통적으로 처리할 수 있으므로, 코드의 재사용성이 향상된다.
- 동일한 메서드나 기능을 여러 클래스에서 재사용할 수 있다.
- 유연성과 확장성
- 다형성은 새로운 클래스를 추가하거나 기존 클래스를 수정하지 않고도 기존 코드를 확장하고 변경할 수 있게 한다.
- 이로써 소프트웨어의 유지 보수 및 확장이 더 쉬워진다.
- 객체 간의 상호교환이 가능
- 상위 클래스 타입으로 선언된 변수에 하위 클래스의 객체를 할당할 수 있다.
이는 코드의 일반화(generalization)를 가능하게 하며, 코드의 유연성을 높인다.
- 상위 클래스 타입으로 선언된 변수에 하위 클래스의 객체를 할당할 수 있다.