2016년 8월 25일 목요일

java 개념

구조체 vs 클래스, overloading, overriding, this, super, abstract class, interface, upcasting, 예외처리, 쓰레드, 동기화, equal 메소드, instanceof, 접근제어자, 소켓 통신



1. 구조체 vs 클래스
- 구조체와 클래스는 데이터 타입의 생성이라는 측면에서는 같은 역할을 하지만 클래스가 구조체보다 강력한 점은
  접근 제어, 상속의 개념, 메서드의 활용 부분이 클래스에 추가 되었다는 것임.
- C에서는 구조체 안에서 함수 선언이 안됐지만 C++ 구조체 안에 함수 선언 및 정의도 가능하고, 접근제어자 설정도 가능함(class 개념하고 차이가 없어짐).

* 참고
- http://robodream.tistory.com/145

2. overloading
- 매개변수의 개수가 달라야 함.
- 매개변수의 타입이 달라야 함.
- 위의 개수와 타입 중 하나만 달라도 됨.
- 메서드의 리턴타입은 overloading method 구분할 때 사용하지 않음.

3. grandfather class를 father class가 상속하는 경우
- 상속과정에서 상위 레벨의 클래스의 메모리가 생성되지 않는다면 자식 레벨의 메모리는 생성할 수 없음.
  때문에 Father 클래스로 객체를 만들었다면 Father이 상속 받은 모든 상위 레벨의 생성자 메서드가 차례대로 호출 되고 제일 마지막에 자신의 것이 호출됨.

4. 상속과 overriding(method 재정의)
- fafa class를 baby class가 상속 받은 경우,
  fafa f = new baby();
  상위 class의 객체변수가 class의 메모리를 참조하는 것을 업캐스팅이라고 함.
  fafa class에 eat() 라는 method가 정의되었고, baby class에서 이것을 overriding 한경우 f.eat()를 하게되면 baby의 eat()가 호출 됨.

5. this
- this.멤버변수, this.멤버 method
- this : 자신을 참조하는 객체 변수
  public Apple getMySelf(){ return this; } // 자기자신을 참조하는 주소를 반환
- this(매개변수) : this()는 매개변수 없는 자기 클래스의 생성자, this(매개변수)는 매개변수 있는 자기 클래스의 생성자 호출.

6. super
- 상위 클래스 참조 변수
  하위 클래스에서 apple() method를 재정의한 경우 상위 클래스의 apple() method를 호출하기 위해서는 super.apple() 로 호출함.
- 상속을 하면 상위클래스의 생성자부터 호출되고 하위클래스의 생성자가 마지막으로 호출되는데, 상위클래스의 생성자의 매개변수를 넘겨주는 것이 필요함.
  fafa class를 baby class가 상속 받았고, fafa class 생성자에 매개변수가 들어가는 경우, baby class의 생성자에서는 super(매개변수1, 매개변수2, ..); 같이
  매개변수를 넣어줘야할 의무가 있음.

7. abstract(추상) class
- abstract method를 하나라도 가지고 있는 클래스는 추상 클래스로 선언되야 함.
- 추상 메소드를 가지고 있다는 것 빼면 일반 클래스와 다를것 없음(멤버 변수, 생성자 등 사용 가능).
- 추상 메소드는 메소드의 선언만 있고, 정의는 없음.
  예: public abstract void apple();
- 추상 클래스 예
  public abstract class fruit {
      public abstract void apple();
  }
- 추상 클래스는 상속(extends)을 통해 구체화 시켜야 함.
- 추상클래스는 클래스의 구조를 잡기 위한 방법으로 사용. 예를 들어 삼각형, 사각형, 원 class를 만들고, 각 class에 draw()와 delete() method를 구현할 때
  공통되는 method를 추상 클래스로 만들어 수직적으로 분할함.
  즉, shape 추상 클래스를 만들고 draw(), delete()를 추상 메소드로 선언한 후 shape 클래스를 삼각형, 사각형, 원 class에서 상속 받고, 각 method를 구체화함.

8. Interface(인터페이스)
- 추상 클래스의 종류 중 하나.
- 추상 클래스에서는 오직 한개의 메소드만 추상 메소드로 선언되도 되지만, 인터페이스에서는 모든 메소드들이 추상 메소드임.
- 추상 메소드와 static final 변수(상수)만 선언할 수 있음.
- 인터페이스 예
  public interface baby{
     public static final int age = 5;
     public abstract int apple (매개변수 목록) ;
  }
  모든 멤버변수는 static final 이어야 되므로 굳이 static final을 명시않해도 됨.
  모든 메서드가 public abstract 이므로 method 앞에 public abstract를 명시 않해도 됨.
- implements keyword로 구체화 함.
- 자바는 다중상속이 없으므로 이를 해결하고자 Interface를 이용하며, 상속과 같이 업캐스팅에 사용될 수 있음.
- 추상 클래스가 클래스의 구조들을 잡는데 사용된다면 인터페이스는 공동 작업을 위한 인터페이스로 사용됨.
  예: DB는 여러 회사에서 개발하지만 개발자들이 각 회사의 DB가 제공하는 메소드들을 알수는 없음. 따라서 약간식은 다를수 있지만 DB 회사들은
       공통의 인터페이스를 제공함. 즉, insert, update, delete 같은 기능들은 어느 회사든지 거의 비슷한 기능을 하는데, 이를 인터페이스화 시켰기 때문임.
       또한 TV 리모컨도 인터페이스화 된것. TV 회사들이 모두 각자의 기능을 갖는 리모컨을 개발하면 사용자들은 TV를 바꿀때마다 각 리모컨의 기능을 배워야함. 
       하지만 볼륨 업/다운, 채널 업/다운, 전원 버튼 같은 기능들은 어느 리모컨에서든지 모두 같음. 

8. upcasting의 일반적인 구현
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
class Shape {
    public void draw() {
        System.out.println("모양을 그린다");
    }
    public void delete() {
        System.out.println("모양을 지운다");
    }
}
class Circle extends Shape {
    public void draw() { // 재정의
        System.out.println("원을 그린다");
    }
    public void delete() { // 재정의
        System.out.println("원을 지운다");
    }
    public void sayCircle() {
        System.out.println("원");
    }
}
class Triangle extends Shape {
    public void draw() { // 재정의
        System.out.println("삼각형을 그린다.");
    }
    public void delete() { // 재정의
        System.out.println("삼각형을 지운다");
    }
    public void sayTriangle() {
        System.out.println("삼각형");
    }
}
class Rectangle extends Shape {
    public void draw() { // 재정의
        System.out.println("사각형을 그린다.");
    }
    public void delete() { // 재정의
        System.out.println("사각형을 지운다");
    }
    public void sayRect() {
        System.out.println("사각형");
    }
}
public class STMain {
    public static void main(String[] args) {
        Shape s = new Shape();
        s.draw();
        s.delete();
        
        Triangle t = new Triangle();
        t.draw();
        t.delete();
        t.sayTriangle();
        System.out.println();
        
        Rectangle r = new Rectangle();
        r.draw();
        r.delete();
        r.sayRect();
        System.out.println();
        
        // Upcasting의 사용
        Shape c1 = new Circle();
        c1.draw();
        c1.delete();        
        // c1.sayCircle();    // 에러가 발생한다. (Error: The method sayCircle() is undefined for the type Shape)
        System.out.println();
        
        Shape t1 = new Triangle();
        t1.draw();
        t1.delete();
        // t1.sayTriangle();  //에러가 발생한다. (Error: The method sayTriangle() is undefined for the type Shape)
    }
}
cs
- 업캐스팅(upcasting)을 사용하여 객체를 생성한 것이 아래부분임.
  Shape c1 = new Circle();
  Shape t1 = new Triangle();
  Shape r1 = new Rectangle();
  만약 c1, t1, r1은 Shape의 객체변수이므로 재정의된 메소드를 호출하게 되면 Shape class의 것이 호출됨.
  하지만 만약 하위클래스에 재정의된 메소드가 존재한다면 재정의된 메소드를 호출하게 됨. 
  따라서 위의 코드에서 c1.draw()는 Shape class의 것이 아닌 Circle class의 draw() 메소드가 호출됨.
- Shape class의 객체변수가 참조할수 있는 메소드는 draw(), delete() 뿐임.
  따라서 c1, t1, r1으로는 하위 클래스에서 정의한 sayCircle(), sayTriangle() 메소드를 참조할수 없음.

9. 에러처리
- try - catch - finally 순서로 진행됨.
- 사용자가 에러를 발생시키는 것: throw new Exception("error occur");
- 에러처리를 미루는 것.
  예: 메소드 선언 옆에 throws MalformedURLException 처럼 선언하면 됨.
       에러처리는 해당 메소드를 호출한 곳에서 처리를 해줘야 함.

10. 쓰레드
- 쓰레드 생성 방법
  ① Thread 클래스를 상속 받는 방법
  ② Runnable 인터페이스를 구현하는 방법
- Thread class 상속 받는 방법
1
2
3
4
5
6
7
8
9
10
11
12
13
import java.lang.Thread;
// Thread 클래스를 상속 받는 방법
class NewThread extends Thread {
    // To do something…
    // 반드시 run 메서드 재정의를 해야함.
    public void run() {
        // ........
        // Thread Body
        // ........
    }
}
cs
  쓰레드가 실행되면 run 메소드가 시작되고, run 메소드의 수행이 끝나면 쓰레드는 종료됨. 
  따라서 run 메소드안에서 while 문을 사용하여 무한 루프로 반복수행을 하게 함.

  * Thread 클래스를 상속 받았을 경우 쓰레드를 실행하는 방법

  NewThread n = new NewThread(); // 스레드의 생성

  n.start(); // 스레드의 시작


- Runnable 인터페이스를 구현하는 방법
1
2
3
4
5
class NewRunnableThread implements Runnable {
    public void run() {
        // Thread Body
    }
}
cs
  * Runnable 인터페이스를 이용하여 스레드를 생성하고 시작하는 방법
  Thread t = new Thread(new NewRunnableThread());
  t.start();

- 쓰레드 대기상태 만들기
  Thread.sleep(1000);  // 1초. 단위는 밀리세컨드

- 멀티쓰레드 동기화
  ① 시스템에 동기화를 미루는 방법: synchronized
  ② 프로그래머가 직접 동기화 수행: wait와 notify

- synchronized 예
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class SyncStack {
    private Vector buffer = new Vector();
    public synchronized char pop() {
        char c;
        c = ((Character)(buffer.remove(buffer.size()-1))).charValue();
        return c;
    }
    public void push(char c) {
        synchronized(this) {
            Character charObj = new Character(c);
            buffer.addElement(charObj);
        }
    }
}
cs
  synchronized 를 사용하는 방법은 위와 같이 2가지가 있음.

- wait(), notify(), notifyAll()
  쓰레드가 동기화된 공유자원에 접근할 때 다른 쓰레드가 사용하고 있다면 wait() 메소드 대기하게 만듦.
  해당 자원을 wait하고 있는 쓰레드가 있을 때는 notify 또는 notifyAll을 통해 사용할 수 있다는 것을 알려줌.
  예:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public synchronized char pop() {
    char c;
    while(buffer.size()==0) {
        try {
            System.out.println("stack대기:");
            this.wait();
        } catch(Exception e) {}
    }
    Character cr = ((Character)buffer.remove(buffer.size()-1));
    c = cr.charValue();
    System.out.println("stack삭제:" + c);
    return c;
}
public synchronized void push(char c) {
    this.notify();
    Character charObj = new Character(c);
    buffer.addElement(charObj);
    System.out.println("stack삽입:" + c);
}
// 출처: 소설같은 
cs
  

- equals method
  Object 클래스가 제공하는 equals 메소드는 비교되는 두 객체가 갖는 값이 같은지를 검사함. '==' 비교연산자는 두 객체를 비교할 때 객체의 레퍼런스를 비교함.
  예:
1
2
3
4
5
6
7
8
9
10
11
public class Equals {
    public static void main(String[] args) {
        String str1 = new String("안녕하세요");
        String str2 = new String("안녕하세요");
        
        System.out.println("str1" + str1); 
        System.out.println("str2" + str2); 
        System.out.println("str1==str2:"+(str1==str2));      // 참조값의 비교
        System.out.println("str1.eqauls(str2):"+ str1.equals(str2));  // 내용의 비교
    }
}
cs
  '==' 연산자는 참조값 비교를 하므로 'str1 == str2'는 false 이다.
  equals는 문자열의 내용을 비교하기 때문에 true 이다.

11. instanceof
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
class C1 {
    public C1() {}
}
class C2 extends C1{
    public C2() {}
}
class C3 extends C2 {
    public C3() {}
    
}
public class JavaTest {
    public static void main(String[] args) {
        C1 class1 = new C1();
        C2 class2 = new C2();
        C3 class3 = new C3();
        
        if(class1 instanceof C1)  //class1이 C1의 객체인경우 true
            System.out.println("class1 is C1's object 1");
        if(class2 instanceof C1)  //class2가 C1의 하위클래스인 C2의 객체인경우 true
            System.out.println("class1 is C1's object 2");
        if(class3 instanceof C1) //class3이 C1의 하위 클래스인 C2의 하위클래스인 C3의 객체인경우 true
            System.out.println("class1 is C1's object 3");
        if(class2 instanceof C3) //class2가 C3의 하위클래스이므로 false
            System.out.println("class1 is C1's object 4");
        if(class2 instanceof C2) //class2가 C2의 객체이므로 true
            System.out.println("class1 is C1's object 5");
    }
}
cs
  * 출처: http://arer.tistory.com/52
  참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 instanceof 연산자를 사용함.
  instanceof의 왼쪽에는 참조변수, 오른쪽에는 타입(클래스명). 
  instanceof의 연산결과가 true하면 참조변수가 검사한 타입으로 형변환이 가능하다는 것.

12. 접근제어자
- public : 모든 클래스에서 접근 가능함.
  protected : 동일 패키지에 속하는 클래스와 하위클래스 관계의 클래스에 의해 접근 가능함.
  private : 클래스 내에서만 접근가능 함.

- 접근 권한  
종류
클래스 내부
하위 클래스
동일 패키지
모든 클래스
private
O
X
X
X
default
O
X
O
X
protected
O
O
O
X
public
O
O
O
O
  private: 멤버 변수와 멤버 함수를 자기 자신 클래스 내에서만 이용하게 함.
  default: 접근 제어자를 지정하지 않았을 경우 적용되는 것. 동일패키지에 속하는 클래스만 접근 가능(패키지안에 패키지에서는 접근 안됨).
  protected: 동일패키지와 동일패키지는 아니지만 하위 클래스 관계에 있는 클래스에서 접근 가능.
  public: 모든 클래스에서 접근 가능. 즉, 접근 제약이 없음.

13. 소켓 통신


* 출처
- http://zewtion.tistory.com/261


14. 개념들 (출처: http://www.java2novice.com/, others)
- static method를 오버라이드 할수있는가
  static method는 객체가 아닌 클래스에 속해 있음. 상속은 클래스 멤버에 적용되지 않음.
- super()와 this() 차이점
  this는 같은 클래스의 생성자를 호출하는데 사용. super()는 상위 클래스의 생성자를 호출하는데 사용함.
- method의 오버라이딩을 방지하는 방법은?
  method에 final 키워드를 적용하여 상속을 막을 수 있음.
- 추상메소드 없이 추상클래스를 만들수 있는가
  가능함.
- transient 변수란
  private transient int foo; 같이 변수를 선언하면 foo 변수는 직렬화되지 않음.
- 예외처리의 try 블록에서 return을 할 경우 finally 블록은 실행되는가
  try 블록에서 System.exit()를 하지 않는 이상 finally는 무조건 실행됨.
- boolean 변수의 기본값은 무엇인가
  false
- 자바에서 각각의 쓰레드는 별도의 스택을 사용하는 가
  자바의 모든 쓰레드가 자신만의 별도의 런타임 스택을 유지함. 단, 동일한 메모리를 공유함.
- finalize 메소드란
  객체가 gc 되기전 런타임 시스템에서 finalize()를 호출하면 gc 전에 시스템 자원이 회수 됨.
- wait()와 sleep()의 차이는?
  둘다 쓰레드를 not runnable 하게 만듦. sleep은 일정 시간동안 멈추고, wait도 일정시간동안 멈추게 할수 있지만 특정 조건이 만족될때까지
  멈추게하는데 사용됨. wait는 notify() 메소드와 함께 쓰임.
  sleep()은 Thread class의 메소드. wait()는 Object class 메소드.
- wrapper class란
  자바에서 자료형인 int, double, char 등은 객체가 아님. 따라서 이것들을 객체화 시킨 것이 wrapper class 임.
- exception과 error의 차이점
  error은 런타임에 처리가 안되서 발생하는 에러.
  exception은 런타임에 발생할 것을 예측하고 처리하는 방법.
- 초기화 안된 final 변수들을 초기화할 수 있는가
  오직 non-static 인경우 생성자에서만 초기화 가능.
- main method를 private 선언할수 있는가
  가능. 하지만 런타임시 main을 실행 못시켜 에러 날듯.
- 생성자를 private 선언할 수 있는가
  가능. 싱글턴 패턴이나 팩토리 패턴에서 private 생성자를 사용함.
- Interface 에서 method를 선언하고 정의할수 있는가?
  자바 1.8 버전 부터 가능. 'default' 키워드를 메소드 앞에 붙이면 됨. default method는 하위 클래스에서 재정의되어질수 있음.
  또한 static method를 정의할수도 있음. (public static void apple(){...})
- 아래 코드 출력 결과는?
1
2
3
4
5
6
7
8
9
public static void main(String a[]){ 
    int price = 6
    switch (price) { 
        case 2System.out.println("It is: 2"); 
        defaultSystem.out.println("It is: default"); 
        case 5System.out.println("It is: 5"); 
        case 9System.out.println("It is: 9"); 
    } 
}
It is: default
It is: 5
It is: 9
- true, false, null 은 키워드인가?
  아님. 문자열임. (키워드로 오인할 수 있음)
- 아래 코드 출력 결과는?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String [] args){
    try{
        methodA();
        System.out.println("2");
    }catch(IOException e){
        System.out.println("3");
    }finally{
        System.out.println("4");
    }
    System.out.println("5");
}
static void methodA(){
    throw new IOException();
    System.out.println("1");
}
cs
3
4
5
- 접근지정자 중 접근범위가 좁은것부터 나열하라
  private - protected - default - public
- 아래 코드 출력 결과는?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String [] args){
    HashSet set = new HashSet();
    set.add("A");
    set.add("B");
    set.add("C");
    set.add("A");
    System.out.println(set.size());
    ArrayList list = new ArrayList();
    list.add("A");
    list.add("B");
    list.add("A");
    System.out.println(list.size());
}
cs
3
3  (set은 중복을 허용하지 않고, list는 중복을 허용함)
- 아래 코드 출력 결과는?
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
class A{
    private String name;
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name;
    }
}
class B{
    public void p1(A obj){
        obj.setName("apple");
    }
    public void p2(A obj){
        obj = new A("orange");
    }
}
public class Test{
    public static void main(String[] args){
        A objA = new A("ITC");
        B objB = new B();
        
        objB.p1(objA);
        System.out.println(objA.getName());
        objB.p2(objA);
        System.out.println(objA.getName());
    }
}
cs
apple
apple
- 문자열 비교
1
2
3
4
5
6
7
8
9
10
String a = "aaa";
String b = a;
String c = new String("aaa");
        
System.out.println(a.equals(b));        // 값 비교, true
System.out.println(a.equals(c));        // 값 비교, true
System.out.println(b.equals(c));        // 값 비교, true
System.out.println(a==b);        // 주소비교, true
System.out.println(a==c);        // 주소비교, false
System.out.println(b==c);        // 주소비교, false
cs
- call by value & call by reference
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
class inte {
    public int a;
    public int b;
}
private static void swap(int a, int b) {
        int temp = a;
        a = b;
        b = temp;
    }
    private static void swap(Integer a, Integer b) {
        Integer temp = a;
        a = b;
        b = temp;
    }
    public static void swap(inte temp) {
        int n = temp.a;
        temp.a = temp.b;
        temp.b = n;
    }
    public static void main(String[] args) {
        int a = 1;
        int b = 2;
        System.out.println("a => " + a);
        System.out.println("b => " + b);
        swap(a, b);
        System.out.println("------- swap 후 -------");
        System.out.println("a => " + a);
        System.out.println("b => " + b);
        System.out.println();
        Integer aa = new Integer(1);
        Integer bb = new Integer(2);
        System.out.println("aa => " + aa.intValue());
        System.out.println("bb => " + bb.intValue());
        swap(aa, bb);
        System.out.println("------- swap 후 -------");
        System.out.println("aa => " + aa.intValue());
        System.out.println("bb => " + bb.intValue());
        System.out.println();
        inte n = new inte();
        n.a = 1;
        n.b = 2;
        System.out.println("aaa => " + n.a);
        System.out.println("bbb => " + n.b);
        swap(n);
        System.out.println("------- swap 후 -------");
        System.out.println("aaa => " + n.a);
        System.out.println("bbb => " + n.b);
    }
cs
결과
a => 1
b => 2
------- swap 후 -------
a => 1
b => 2

aa => 1
bb => 2
------- swap 후 -------
aa => 1
bb => 2

aaa => 1
bbb => 2
------- swap 후 -------
aaa => 2
bbb => 1


댓글 없음:

댓글 쓰기