Java/심화 개념설명

[1]enum(상수값들의 집합)

 - 프로그램에서 미리 정해놓아야할 값들(상수들)이 존재할 때, 사용한다.

 - 문법 형식 : 


 public enum FoodMenu {

  PIZZA("피자"), KIMCHI("김치), CHIKEN("치킨");

 }

  그외에, 필드 와 생성자를 내부에 가질 수 있다.


 - 실제로는 java.lang.Enum 클래스의 자식 클래스로 생성된다. 많이 쓰는 메소드로 enum변수.name(), ordinal()이 가장 많이 쓰인다.

 - 자동적으로 제공되는 메소드 :  values() - return 타입 : E[]에다가 안에 있는 상수들을 다 뽑아 낼 수 있다 valueOf(String name) - E 타입 하나를 뽑아 낼 수 있다

 - 사용은 Enum명.상수명 을 이용해서 불러와, Enum변수에다가 집어넣어서 --> 보통 swtich -case문에 많이 사용한다. 

    FoodMenu f = FoodMenu.KOREAN

f.na



[2] 가변형 인자(var args) (String... a)

 - 인자값(파라미터, argumen)의 개수를 정하지 않는 것

 - 배열과 같게 취급이 되어, 확장for문  for(String s : a) 형식으로 사용된다.

 - 문법 형식 : 

   public void method(String... a){

for(String s : a) {

System.out.println(s);

}

   }

  인자값이 1개가 됬든, 10개가 됬든, String형 배열에 담겨서 그것들을  확장for문으로 뽑아낼 수 있다.

 - 반드시 마지막 인자값으로 가변형 인자가 들어가야한다. (String a, int b, String... c)


[3] 추상 클래스(abstract Class)

 - class이지만, 객체를 생성할 수 없다. 불완전한 설계도이므로 상속받는 자식클래스에서 객체를 생성해야한다.

 - 추상메소드를 가지는 것은 인터페이스와 동일하다. 하지만 , 필드와 일반메소드들도 가질 수 있는 점에서 인터페이스와 차이가 난다.

 - 목적미리 만들어진 메소드를 자식클래스가 반드시 오버라이딩해서 가지도록 하기위해서이다.(인터페이스가 더 추상적이라 설계적인 측면에서 선호된다)

 

[4] 중첩 클래스(nested class)  : 3가지가 존재한다.

 - 클래스안에 클래스가 들어간다는 의미이다. 

   만약 클래스안의 클래스인데, static이 붙어있으면, static-nested class라 한다.

   만약 클래스안에 들어간 클래스가 static이 없으면, inner class라고 부른다.

   만약, 클래스이름이 없고, 인터페이스를 상속(new Runnable(){})해서 바로 body{}만 있는 것이라면, anonymous - inner class라 부란다




   my) 클래스는 객체를 생성하기 위한 것이다. 만약 static이 붙어서 클래스의 것이 되면, 외부에서 객체생성 못한다.

         대신 클래스 내에서는 객체생성이 가능하다.


  래스안에 클래스(중첩클래스)가 존재하는 것은 3가지 경우이다.

1) static이 붙은 중첩클래스 : 스태틱이 붙어 있으므로, 클래스의 것 => 클래스 내부에서만 객체생성이 가능하다.

2) static이 안붙은 이너클래스스태틱이 안붙어 있으므로, 객체의 것 => 어디서든 객체를 생성해서 사용한다.

3) 클래스의 이름이 없이 인터페이스를 상속한 new Runnable() { } 클래스 : 어노니머스-이너클래스 => 클래스이름이 없고 바로 내부에 실행매쏘드를 가진다.


 - 목적 : 오로지 한 클래스 안에서만 필요한, 클래스(외부에서 객체를 만들필요가 있을 경우)가 필요할 때 사용한다.

  encalsulation이 강화된다. 프로세스가 돌아갈 때, 안쪽 한군데서만 돌아가도록 하고, 메소드를 통해서, 통신만 하도록 하게 하는 것이 강해진다.

 - 가장 많이 쓰이는 곳 : Swing(ui), android에서 이벤트 처리용으로 많이 사용한다.

 

 static-nested class의 static은 소유제한자이며, class의 것이다. 클래스에서 객체를 생성해서 사용한다.

 

public class Outer {

private static class StaticNested { } : static이 붙은 [ 중첩클래스 ]이며, 클래스내에서만 객체가 생성 가능하다.

private class Inner{ } : static이 안붙어 있는, 클래스안의 클래스를  [ 이너클래스 ]라고 한다. static이 안붙었기 때문에, 객체의 것이므로, 객체를 생성해서 사용해야한다.

private Runnable run = new Runnable(){ } : [anonymous - inner class]로, java.lang.패키지에 있는 Runnable이라는 인터페이스이다.

}

- new Runnable( ) { } 이라는 것이 Runnable이라는 인터페이스의 객체를 생성하는 것 처럼 보이지만, 사실은 인터페이스를 상속하고 있는 또다른 클래스를 만드는 과정이다. 그래서 {  }안에는 필드와 메소드가 들어간다. 

  - 인터페이스를 상속받고 있는 클래스이지만, 이름이 없다.

 


 -  중첩클래스의 객체를 생성하는 문법 형식

1)static-nested class(스태틱- 중첩클래스) :  <클래스 내부에서> 클래스명.중첩클래스명  변수 = new 클래스명  .중첩클래스명();

2)inner class(이너 클래스) :   클래스명.이너클래스명  변수 = new 클래스명(). new 이너클래스명(); 

   [ Outer객체 > Inner클래스 ] -- [ Inner객체 ]

3)anonymous-inner class(어노니머스-이너클래스 ) : 인터페이스명  변수 = new 인터페이스명() { 오버라이딩 메소드 };

   - 인터페이스 객체를 생성하는 것이 아니라 인터페이스를 상속하는 어노니머스 이너클래스를 만드는 과정



[5] annotation(애노테이션)

 - 프로그램에 대한 정보를 제공하는 것이다.

 - 목적 : 컴파일러에게 정보제공 / 컴파일 시 자동으로 소스를 만들어줌  /  xml을 생성기능 / 실행시에 검사하기 위해서

 - 활용 : Spring 프레임워크에서 많이 사용된다.


 - 컴파일러에게 정보제공 할 때 쓰이는 방식

  @Deprecated : 더이상 쓰지 말아야할 곳에 쓴다

  @Override : 반드시 오버라이딩 해야할 곳

  @SuppressWarnings : Generics( )를 제대로 사용하지 않았거나, Deprecated된 메소드를 사용할 때 Warning이 발생하는 곳에 막아주는 기능


[6] final

 - 변수 앞에 붙어서 상수로 만들어준다

 - 메소드 앞에 붙어서 자식이 오버라이딩(재정의) 못하게 한다

 - 클래스 앞에 붙어서 자식이 상속할 수 없게 한다.



[7] 실습


1. 메인메소드를 가진, package enumpack, public class TestEnum 를 만들어준다.

(1) 중첩클래스처럼, 내부에 enum을 만들어준다.

     public class TestEnum {

public enum Language{

}

(2) 대문자로 상수를 만들어준다.

KOREAN, ENGLISH, JAPANESE;


(3)[  ctrl+space ] 를 눌러서 생성자를 넣어준다. (사용은 안할 것이다)


(3) 보통 메인함수에서 참조형 변수를 생성한 뒤에 Language.상수명을 넣은 다음, 변수를  switch case문에 넣어서 사용한다.

public static void main(String[] args) {


Language l = Language.ENGLISH;

switch(l) {

case KOREAN : System.out.println("한글입니다."); break;

case ENGLISH : System.out.println("영어입니다 " + Language.ENGLISH); break;

}

}

(4) 이제 enum명. values()를 이용해서 선언한 상수들을 모두 배열에 넣은다음, 확장for문을 이용해 하나씩 꺼내보자.

     for문안에서는 사용된 변수.name()을 상수명을, 변수.ordinal()을 이용해서 index순서도 같이 찍어주자.


for(Language lang : Language.values()) {

System.out.println(lang.name() +"은 "+ lang.ordinal()+"번째 상수입니다.");

}


2. abs패캐지, abstract 클래스를 만들자. 메인함수도 넣어주자.

(1) class앞에 abstract를 추가해주자.

(2) 메소드를 만드는데 반환형 앞에다가 abstract를 넣어줘야한다. 순서바뀌면 안됨.

(3) 인터페이스와는 다르게, 일반메소드도 넣어줄 수 있다. 


package abs;

public abstract class TestAbs {

public abstract void test() ;

 

public void test2() {

System.out.println("추상클래스안의 일반메소드");

}

 

public static void main(String[] args) {


}


}



(4) abs패키지안에, 추상클래스를 상속받을 자식클래스를 만들어주자. [browse]를 눌러서 부모클래스를 TestAbs를 선택해주자. 메인함수도 포함시키자

 - 부모클래스가 추상클래스이므로, 자식클래스가 반드시 오버라이딩 해야하는 매쏘드가 , 자동으로 작성되어있다.


public class TestAbsSub extends TestAbs {


@Override

public void test() {

// TODO Auto-generated method stub


}

(5) 메인메소드에서 사용해보자. 

*** 나는 객체를 생성해서, 변수에 넣고, 변수.메소드()를 호출하지만 , 변수 없이 바로 객체생성후.메소드()를 호출 할 수 있다.

클래스의 메소드를 사용하는 것은 [ new 생성자() ] 의 객체가 메소드를 사용해서 통신


public static void main(String[] args) {


//객체를 생성해서 변수에 넣고 이용하는 방법

TestAbsSub tab = new TestAbsSub();

tab.test();

//객체 생성하자마자 바로 메소드를 이용하는 방법

new TestAbsSub().test();

//부모인 추상클래스의 일반 메소드를, 자식이 사용하기

new TestAbsSub().test2();

}



3. 중첩클래스를 만들어보자.

(1) 클래스안에,  Runnable인터페이스를 상속받는 [이너클래스]를 만들자. -> Runnable인터페이스안의 추상메소드를 상속해야한다.

(2) run()함수안에는 for문으로 0부터 9까지 출력시키는 코드를 넣어주자.


//이너클래스

private class Target implements Runnable {


@Override

public void run() {

for(int i=0;i<10;i++) {

System.out.println("i : "+i);

}

}

}


(3) 메인메소드에서 Target클래스의 객체를 만들자. 하지만 이너클래스는 static 이너클래스인 메인메소드 안에 바로 들어갈 수 없다.

    바깥쪽 TestOuter객체를 만들고 그것을 이용해야한다.

   ***** 이너클래스의 객체는 바로 생성하지 못한다 ==> 현재 바깥 클래스의 객체를 만들고 난 뒤, 변수를 선언할 때는, 클래스명. 을 / 객체를 생성할 때는, 객체명. 을 써서 생성한다.

   ***** [바깥 클래스명].[이너클래스명]  변수명    =    [바깥 클래스 객체]. new [이너클래스명](); 

    왜냐면, 변수 선언은   [설계도 클래스명]이 앞에 오고 / 객체 생성은, [객체]에서 비롯 되기 때문이다.

public static void main(String[] args) {


TestOuter out = new TestOuter();

TestOuter.Target t = out.new Target(); 

}


(4) 쓰레드를 하나 만들어고, 파라미터에는 Runnable인터페이스를 상속한 클래스의 변수를 넣어준다.

    - Runnable 인터페이스의 run()메소드는 쓰레드의 파리미터에 넣어서 실행된다. 그것을 상속한 자식의 run()메소드도 쓰레드에서 실행된다.


Thread th = new Thread(t);

th.start();


(5) anonymous-inner class를 메인함수에서 바로 만들어주자.

     먼저 쓰레드 객체를 생성하고, 파라미터에는 new Runnable() {  }을 만들어준 다음, ctrl+space로 run()매소드를 오버라이딩 하자.


//어노니머스 이너클래스

Thread th2 = new Thread(new Runnable() {

@Override

public void run() {

for(int i=0;i<10;i++) {

System.out.println("i : "+i);

}

}

});

th2.start();


단축키) 

생성자/겟셋터 : ALT +SHIFT + S

한줄 삭제 : Ctrl + d

자바독 : ALT+SHIFT+J



[1] 인터페이스(interface)


안드로이드에서 인터페이스는 어떤동작을 듣고 있는 귀이다. 귀를 달아준 뒤 귀에 들릴 때, 행동할 것은 우리가 적어서 한다.


리모콘의 버튼을 누르는 것이 인터페이스이다.  노래방 기계 개발자가 노래목록을 api로 제공하는 것이 인터페이스다.

예를 들어서, 1111을 누르면, 자동으로 노래를 불러온다. 하지만, 리모콘을 눌러도, 안쪽에 캡슐화가 되어있기 때문에 어떻게 돌아가는지는 모른다.


1. 인터페이스의 문법적 특징 

 - final이 붙어 있는 상수가 존재한다.(인터페이스 내부의 필드들은 다 상수다. final이 없다면 생략된 것이다.)

 - 메소드는 선언으로만 이루어진다.(내용(body부분 {  }) 은 비어있고 나중에 인터페이스를 상속하는 곳에서 내용을 채워 사용한다. 

   예를 들어, 안드로이드의 버튼의클릭 리스너는 내용은 비어있다)

 - 모든 상수와 메소드는 public이다.

 - 여러개 상속이 가능하다.

 - 클래스와 달리 객체 생성(new 생성자)은 불가능하다.

   (변수는 생성가능하다. 해당 인터페이스를 상속한 자식 클래스의 객체가 생성된 것을 참조할 수 있다.)

 - 서브클래스(상속받는 자식클래스)는 메소드 내용 구현이 필수적이다.

 - 인터페이스가 인터페이스를 상속할 때는, extends로 상속한다. 클래스가 상속할 때는 implements로 한다.


public interface InterSub extends Inter1, Inter2 { // 인터페이스가 인터페이스를 상속할 때는, extends로 상속한다. 클래스를 상속할 때는 implements로 한다.

public static final int HEIGHT = 768; // 인터페이스에서 필드를 선언하지만, 모두 상수값이 된다.

int width = 1024; // public static final은 생략이 가능하다. 인터페이스에서 선언한 필드는 다 상수다.


public abstract void open(); //인터페이스의 매쏘드는 { }의 내용이 구현되어 있지 않다.

void close(); // 인터페이스의 public abstract는 생략이 가능하다. 인터페이스에서 선언한 [반환형 + 매쏘드()]는 다 내용이 구현되어 있지 않다.


}


* abstract : 메소드의 body{ }가 없는 경우에 붙이게 되는 예약어이다. 인터페이스들의 메소드는 다 abstract를 가지고 있는데 생략되어 있다.

* 나중에 메소드를 추가 혹은 변경 하고 싶다면, 해당 인터페이스를 상속받는 자식 인터페이스를 만드는 것을 추천한다. 

  왜냐하면, 인터페이스는 외부에 공개가 되는 것이다. 전세계 사람들이 open(), close()메소드를 쓰고 있을 것이다. 이것을 변경하면 안된다.


[2] JavaDoc(/**  */)

 -  // 한줄주석, /* */ 여러줄 주석, 그리고 바로 /** */ (안드로이드의 초록색 주석)--> javadoc

 - [api용 문서]로 사용이 된다. (커서를 갖다놓으면 자바독이 바로바로 뜬다)

 - 내용으로는 인터페이스 생성 정보, 메쏘드에 대한 설명 등을 인터페이스를 사용하는 사용자들에게 정보를 제공하는 문서가 된다.


[3] 상속(inheritance)

 - 부모클래스가 자식클래스에게 필드와 메소드를 물려주는 것

 - is a 관계

 - 계층구조도 맨 꼭대기에는 Object라는 클래스가 있다. 모든 클래스는 Object를 상속하고 있다. 모든 클래스는 Object이다.

 - 필드와 메소드만 물려주기 때문에, 생성자는 상속되지 않는다.


[4] 형변환 (Type Casting)

 - Reference Type 변수(참조형 변수, 대문자로 시작하는 클래스 변수)의 type을 변환하는 것이다. ( 실제로 객체가 변하는 것은 아니다)

 - 암시적 형변환 :  

Human h = new Human(); 에서,  new Human();은 <하위계층>인 사람 클래스의 객체를 <참조형 변수>가 받았다

Obeject o = h; 에서, <하위계층>인 사람클래스의 참조형 변수 h는 <상위계층>인 Object클래스의 참조형 변수 o에 형변환(캐스팅)없이 바로 대입 할 수있다

 - 명시적 형변환 :  

Object o = new Human(); 에서, <하위계층>인 사람 객체를 , <상위계층>인 객체의 참조형 변수에 넣었다. 암시적 형변환으로 형변환 없이 바로 작은 것을 큰것에 넣을 수 있다

Human h = (Human) o; 에서, <상위계층>인 Object 클래스의 참조형 변수 o<하위계층>에 넣을 때는, 반드시 형변환을 해줘야한다.


  my) 큰 단위(Object)에 <=====더 작은 단위(human)을  대입할 때는 형변환 캐스팅 없이 암묵적으로

        더 작은단위(Human)에 <==큰 단위(Object)를  대입할 때는, 큰것 앞에다가 ( )로  형변환 캐스팅 해줘야한다.


[5] 오버라이딩(Overriding) - my)부모 메소드 재정의

 - 부모클래스에서 상속받은 메소드를  <현재 클래스에 맞는 형태로 재정의>하는 것이다.

 - ***규칙 : 부모 메소드와 똑같은 선언부를 가진다.(내용만 원하는대로 재정의한다) or 접근제한자가 더 넓은 범위를 써야한다.(부모 protected - > 자식 public or protected)


[6] 다형성(Polymorhism)

- 하나의 객체가 -->  다양한 형태로 모습(부모의 변수 or 자식의변수에 대입)이 변하는되는 것 : 형변환( or 오버라이딩 : 메소드명은 같으나 내용이 재정의 되어있다.)

- 다른 형태인 형변환( or 오버라이딩) 상태에서 처음생성된 해당 객체의 메소드가 실행되는 것 : 다형성

 ex> 오버라이딩 : 부모클래스의 메소드를  자식클래스가 오버라이딩해서 사용한다면, 부모의 메소드와는 전혀 다른 자식의 메소드가 실행된다.

 ex> 형변환 : new 사람() 객체는 동물객체가 될 수 있다.(is a 관계). 이때, 사람객체를 형변환해서 동물객체에 넣고, 동물객체.움직인다()를 호출하더라도,                      new 로 생성한 객체는 사람이다. new뒤에 붙은 객체의 메소드 ,사람객체.움직인다()가 실행된다.


     - new 뒤에 적힌것만 보고 어느계층의 메소드()가 호출되는지 판단하면 된다.******************



Human extends Animal

Monkey extends Animal 상황에서


Animal a = new Animal();

Animal h = new Human(); //작은 것(하위계층)을 대입한, 암시적 형변환

Animal m = new Monkey();// 작은 것(하위계층)을 대입한 암시적 형변환


이때, 메소드를 출력하면

a.move(); // Animal 클래스의 move()메소드가 호출됨

h.move(); // Animal  변수에 담겨있지만, new 뒤의 Human클래스의 오버라이딩 한 move()메소드가 호출

m.move();// Animal 변수에 담겨있지만, new 뒤의 Monkey클래스의 오버라이딩 한 move()메소드가 호출


[7] super 사용( 클래스의 생성자 or 메소드의 오버라이딩 )

 - this는 클래스 자기자신의 객체를 뜻한다. 그래서 this.필드명 을 치면 private한 필드에도 접근이 가능하다.

 - super는 부모 클래스의 객체를 뜻한다. 


 사용방법은 2가지

1. [자식클래스의 버라이딩 된 메소드 안에서] 오버라이딩된 자식메소드가 아닌, <부모클래스 속의 메소드>를 그대로 호출할 때, 메소드 안에 적어준다.  그 뒤에 추가로 재정의 할 수 도 있다.


@overridng

 void move(){

super.move(); //부모클래스객체 super.를 이용해서 부모의 메소드 move()를 그대로 호출한다.

System.out.printlm("사람이 움직인다"); // 추가적으로 자식클래스의 오버라이딩 메소드만의 추가적인 재정의를 더해줄 수 있다.

 }


2. [자식클래스의 생성자를 만들 때], 부모클래스의 필드를 초기화하기 위해, 부모생성자를 호출한다.

 - 모든 생성자의 첫번째 줄에는 부모생성자가 생략되어있다!! 컴파일러가 자동으로 super();를 자동으로 넣어준다.

 public class Human extends Animal {

public Human() {

super(); //자식클래스의 생성자에서는 부모클래스의 생성자를 먼저 호출한다. 없다면 생략된 것이다.

}

 }

  

 - 만약 부모클래스에 <파라미터가 비어있는> 기본생성자가 없고,  <파라미터를 가진 > 사용자정의 생성자( public Human(int height) {  this.height = height }  )를 가지고 있다면

    자식클래스에서는  super();를 생략하면 컴파일 오류가 난다. super( 초기화할 값 );  super ( 10, 20); 등 사용자가 정의한 생성자의 초기값을 파라미터로 넣어줘야한다.







[8] 실습 (javase07)

1. 자바프로젝트의 src> 우클릭 >new> interface를 선택해준다. 패키지명은 song, 인터페이스명은 [ Singable ]로 준다.

 (1) 인터페이스의 필드를 만든다. 인터페이스의 필드는 상수이므로, 대문자로 변수를 선언한다. (상수를 의미하는 public static final이 생략되어있다)

      아래의 상수는 다른 것 같지만 2개 모두 절대 변하지 않는 인터페이스의 상수이다.


String NO_1111= "미안해요";

public static final String NO_1234 = "제발";


 (2)  인터페이스의 메소드를 만든다. public abstract는 생략되어있다. 반환형과 메쏘드( )명, 그리고 파라미터도 하나 넣어준다.


int sing(String songNo);


 * 문법적으로는 완성되었지만 아직 미완성이다. 실제 인터페이스는 외부에 공개가 되어있는 것이므로, JavaDoc을 붙혀줘야한다.


package song;


public interface Singable {

String NO_1111= "미안해요";

public static final String NO_1234 = "제발";


int sing(String songNo);

}



 4. song 패키지에 우클릭해서 Singable 인터페이스를 상속받는 클래스 [ Singer ]를 만든다. 이때, [ add ]버튼을 눌러서 만든 Singable.java 인터페이스를 상속한다. 메인메쏘드도 추가해준다.

 (1) 새롭게 만든 Singer 클래스는 , Singable이라는 인터페이스를 implements(상속)했기 때문에, 인터페이스의 sing()메쏘드를 자동으로 @overridng 하고 있다.

      인터페이스를 상속한 클래스는 반드시 body{}가 없었떤 것을 구현화 해줘야하기 때문이다.

 (2) //TODO 주석은 [Ctrl + D] 로 지워준다.

 (3) song()메소드에는 구현화하는 내용으로, [1] 넘어오는 songNo의 노래를 불렀다고 출력문 + [2] 몇분동안 불렀는지 int 시간을 return 해준다.


5. 메인메소드에서 Singer 객체를 만들어서 참조형변수에 넣어준다.

***(1) 인터페이스 Singable의  new Singable이라는 객체를 생성할 수 없다

        하지만, new Singer객체를 만든 것을, 부모인 인터페이스 Singable의  변수에는 넣을 수 있다.

클래스끼리 만이 아니라, 클래스->인터페이스로 형변환해서 대입해주는 것이 가능하다.( 인터페이스를 클래스가 상속하고 있으니, 인터페이스 객체가 더 상위계층)


Singer s = new Singer();

Singable s1 = s; //클래스끼리만이 아니라, 클래스->인터페이스로 형변환이 가능하다.  인터페이스가 부모이므로, 더 상위계층이라 캐스팅 없이 바로 대입가능


 (2) heap Area의 같은 객체 new Singer()을 공유하는, s.와 s1.을 이용해서 매쏘드를 사용해보자.

s.sing(NO_1111);

s1.sing(NO_1234);


 (3) 출력값 

미안해요노래를 불렀다.

제발노래를 불렀다.


6. Singable 인터페이스는 외부에 공개하는 api이므로, JavaDoc을 붙혀줘야한다. ( 단축키 : ALT+SHIFT+J )

 - 인터페이스 선언부에 커서를 대고, [ALT + SHIFT + J]를 눌러보자.

 - @를 입력하면 자동완성으로 각종 title을 고를 수 있다.

 -  필드, 메소드에도 자바독을 달 수 있다.


package song;


/**

 * @author cho

 * 노래를 부르고, 노래시간을 반환하는 인터페이스

 * @since 2018. 02. 20

 * @version 1.0

 */

public interface Singable {

/** 김건모의 미안해요 자바독*/

String NO_1111= "미안해요";

public static final String NO_1234 = "제발";


/** 메소드에도 자바독을 달 수 있다. 인자값 : 노래번호를 받아서, 노래제목을 출력, 노래시간을 반환하는 메소드

* @param songNo Singable에 선언된 필드값을 노래번호로 넣어라.

* @return 노래한 시간을 반환한다.

*/

int sing(String songNo);

}


 - 자바독을 다 완성하고 난 뒤에는 

    [ 자바프로젝트(jaavase07)  우클릭 ] > [ Export ] >  [java폴더] > [JavaDoc ] 클릭

    [Configure ]버튼을 눌러서 javadoc.exe 위치를 잡아줘야한다 (C:\Program Files\Java\jdk1.8.0_144\bin\javadoc.exe)  > [Finish]

 - 콘솔창에 자바독이 만들어지는 과정이 보인다.

 - 자바프로젝트 > doc폴더가 보인다 > index.html 을 실행해보자. 자세한 설명이 나와있다.

 - 이제 Singer클래스에서 쓰인 인터페이스의 메소드 song()에 마우스를 갖다대변 자세한 설명이 나온다.


7. Singer클래스를 상속받는 BalladSinger를 만들어보자. 메인메소드도 추가해준다.

(인터페이스는 add버튼으로 만들 때 바로 상속가능, 클래스의 상속은 직접 extends 적어줘야한다)


(1) sing메소드를 오버라이딩 하자.  [ sing을 치고, ctrl+space로 자동완성해야지 오버라이딩 할 수 있다]

(2) return super.sing(songNo); 를 보자. 아직 구체적으로 오버라이딩해서 return값을 재정의 안해준다면, 부모의 메소드를 호출해서 return을 미리 채워놨다.

(3) 먼저, super.sing(NO_1111);을 호출하자. [ 생성자가 아닌 메소드 오버라이딩에서의 super는 부모 메소드내용을 그대로 갖다쓴다는 의미이다.]

     참고로, 부모 Singer의 sing()메소드는,, 인터페이스를 구현화 했는데,, 출력문이 이미 존재했다. 또 출력문이 발생할 것이다.

     부모의 sing()메소드는 int 노래시간을 return하므로, int로 받아준다.


int i = super.sing(NO_1111);


(4) return은 부모메소드에서 반환될 값 필요 없이, 10으로 그냥 넣어준다.


public class BalladSinger extends Singer {


@Override

public int sing(String songNo) {


int i = super.sing(NO_1111);

System.out.println(songNo + "란 노래를 발라드싱어가 불러요. ");

return 10;

}


8. BalladSinger의 메인함수에서, Singer객체, BalladSinger 객체 -> 더 상위계층 부모인 Singer 변수에 담아서(암묵적 형변환)  sing()을 호출해보자.

public static void main(String[] args) {


Singer s = new Singer();

Singer s2 = new BalladSinger();

s.sing(NO_1111);

s2.sing(NO_1234);

}


9. 출력값을 확인하면 출력문이 3개 인 것을 알 수 있다.


미안해요노래를 불렀다.

미안해요노래를 불렀다.

제발란 노래를 발라드싱어가 불러요. 


 (1) 첫 줄은, Singer가 Singable인터페이스를 상속한다음, sing()을 구체화하는 과정에서 출력문을 넣었다.

 (2) 2,3번째 줄은, BalladSinger가, Singer를 상속하여 sing()메소드에 이미 출력문1개를 가진 상태에서 , 오버라이딩으로 또 출력문을 하나 더 추가했다.


10. 가장 상위계층인 인터페이스의 Singable 변수에 new Singer();객체와 new BalladSinger();객체를 넣어 형변환시켜서 대입해도 제대로 작동한다. 


Singable s = new Singer();

Singable s2 = new BalladSinger();

s.sing(NO_1111);

s2.sing(NO_1234);




*** 객체 지향의 꽃 : 상위계층의 변수에, 하위계층(자식)들의 객체(new 클래스();)를 암묵적 형변환으로 대입해서도 바로 사용할 수 있다. 

                           어떠한 메소드를 호출한다면, 상위계층의 메소드가 아닌, 생성한 객체의 메소드가 호출된다. 


11. 새로 song패키지에, Excute라는 클래스를 메인함수를 포함해서 만들자. 

    그리고 메소드를 만드는데, 파라미터(인자값)으로 Singable변수 s와, String songNo를 받도록 하고, body{}에다가 s.sing(songNo);로 호출해보자.


void execute(Singable s, String songNo) {

s.sing(songNo);

}


 - Execute 클래스와 <--> Singable만 연결된 것 처럼 보인다. ( Singer나 BalladSinger 클래스와는 상관없어보인다.)

   그러나 파라미터 자리에 Singable 객체가 아니라, 자식인 Singer나 BalladSinger 객체를 넣으면, Singer나 BalladSinger의 sing()이 호출된다.


(1) BalladSinger의 메인함수에서 Execute 객체를 만들고, 변수에 참조해준다. 그리고 e.execute(  ,  );를 호출해준다.

*** 이때, 파라미터에는 Singerable의 변수가 들어가야 하나,  new BalladSinger() 객체를 생성해서 넣어준다.


Execute e = new Execute();

e.execute( new BalladSinger(),Singable.NO_1111);


(2) 실제 실행은 Execute클래스의 execute()메소드에서 Singable 변수 s.sing();으로 호출되지만, 

     Singable 변수 뿐만 아니라 그 자식들인 Singer 객체, BalladSinger객체가 들어와도 아무 상관이 없이 잘 작동하게 된다.

    위에 처럼 BalladSing 객체가 들어간다면, BalladSinger의 sing() 메소드 (출력문2개)가 호출되어 출력된다.


[정리]  전혀 상관없어보이는 클래스의 메소드에 파라미터에다가, (부모의 객체타입) 을 받도록 했다면,

          거기에는 상속하고 있는 (자식객체) 아무거나 넣어도 된다. 메소드를 호출할 때도, 부모의 메소드가 호출 되는 것이 아니라 

          자식이 <인터페이스의 메소드의 내용을 구현화 한것 > 또는 <오버라이딩해서 재정의 한 것>의 메소드가 호출된다.


형변환에 의해서 Singeable을 상속하는 무엇이든 그 자리를 차지할 수 있다.


단축키) 

[syso] 치고 + [ctrl + space] : 출력문 자동완성

[Ctrl+Alt+아래 화살표 ] : 한줄복사.



1. 클래스(Class)의 구조

  패키지 선언 >

 import구문(java.lang.* 패키지 안에 것들은 생략되어있음) >

 접근제한자 (public ~) > 클래스 선언 > extends Object(생략, 자바계층구조도의 최상위는 Object) > 인터페이스 implement >

 필드or멤버변수 > 

 생성자 > 

 매쏘드


2. 생성자(Constructor)

 - 생성자 : 객체 생성시 호출이 된다.(new 생성자( 생성자의 파라미터)).  메소드와 형식이 비슷하지만, [이름이 클래스명과 같고 ] [리턴타입이 없다]

       생성자를 통해서, 클래스안의 필드들에 기본값을 넣어준다.

 - 기본생성자(default constructor) : 클래스의 접근제한자와 이름이 같은 것을 가지고, 인자값(파라미터, 매개변수)가 아무것도 없는 생성자.

   만약 생성자가 하나도 없으면, 컴파일러가 자동으로 기본생성자를 만들어준다.


//생성자 생성 [Ctrl + Space]로 default 생성자를 바로 생성할 수 있다.

//default 생성자. 클래스와 똑같은 public이라는 접근제한자를 가진다.

public Car() {

}

//직접 생성자 생성. 접근제한자는 클래스의 접근제한자와 동일하게 해주는 것이 좋다. 파라미터를 추가했다. 

public Car(String owner) {

this.owner = owner; //받은 파라미터를 클래스의 멤버변수(필드)에 대입하려면 this.멤버변수(필드) 에 대입한다.

//다른 방식으로서, 인자를 2개를 가지고 있지 않더라도,인자 1개의 생성자라도 임의의 값을 넣어서 인자 2개인 생성자를 호출할 수 있다.

//this("임의의색으로 다른 생성자 호출", owner);

}

//생성자 오버로딩을 이용해서, 파라미터를 더 추가했다. 

public Car(String color, String owner) {

this.color = color;

this.owner = owner;

}




3. 오버로딩(Overloading)

 - 메소드 혹은 생성자와 같은 이름을 가지나, 인자(파라미터, 매개변수)의 형태나 갯수, 순서가 달라서, 완전히 다른 것으로 인식 되는 것.

 - 개발의 편의성을 위해 존재한다.


//생성자 오버로딩을 이용해서, 파라미터를 더 추가했다. 

public Car(String color, String owner) {

this.color = color;

this.owner = owner;

}



4. this(예약어) - 파라미터로 넘어온 것을, 클래스의 것인 필드(멤버변수)에 대입할 수 있다.

 -  현재 객체의 참조형으로, 예를 들어


 public class Point {


private int x, y; //필드(멤버변수) 2개.


//4개의 생성자가 오버로딩 되어있다.


public Point(int x, int y){ // 1. 파라미터로 넘어온 x를 --> 클래스안의 필드(멤버변수)에다가 집어넣고 싶을 땐, this.x 에 집어 넣는다. 

        클래스안에서 기본값을 넣어준다.

this.x = x; // 즉, 클래스의 x를 this.x <--> 파라미터로 넘어온 것은 그냥 x

this.y = y;

}


public Point(){ // 2. 클래스명과 동일한 접근제한자+이름 을 가진다. 인자(파라미터)에는 아무것도 없으니, 기본 생성자다.

this(0, 0);  // 이때, 이 2번 기본생성자의 this(0,0)는 --> 파라미터가 2개인 1번 생성자 class Point(int x, int y)를 호출해서 x와 y에다가 0,0을 넣어주게 된다.

}


public Point(int x){

this(x,0);

}

public Point(int y){

this(0,y);

}



}


5. 접근 제한자(Access Modifier)

 - 클래스, 멤버변수, 메소드, 인터페이스 등에 붙어서 접근가능여부(사용여부)를 알려주는 예약어 이다.

 - public > protected > default > private 순으로 범위가 좁아진다

(1) private : 클래스 안에서 선언되면, [같은 클래스 안]에서만 쓰인다. 

(2) default : 접근제한자가 없는 것으로, 클래스의 안에서 선언되도, [패키지 안]의 어느 클래스에서나 사용가능하다.

(3) protected : default보다는 넓은 범위로, 한 패키지내에서 다른 클래스가 다 사용가능하고 + [ 다른패키지라도 자식클래스(subclass) ]라면 사용가능한 것이다.

(4) public : [ 제한 없는 것], 다른 컴퓨터에서도 네트워크로도 접근가능하다. 네트워크프로그래밍에서는 필수


 *** 마땅한 이유가 없으면 필드(멤버변수)는 반드시 private로 선언하는 것이 좋다.

 *** 상수(final)이 아닌 경우에는 public을 쓰지 않는 것이 좋다.




6. 소유제한자(Static)

 - 클래스내부의 메소드나 변수 앞에 붙어서 [누구의 것인지]를 나타낸다.

 ex> String s; --> 생성된 각 [객체]의 것, ===> 메인함수에서, 객체.변수명으로 사용

static String s; --> [클래스]의 것     ===> 메인함수에서, 클래스명.변수명으로 사용 && 어느 객체의 객체.변수명으로도 접근이 가능하나, 클래스에 저장된다.

 - static이 붙어 있으면 클래스의 것으로, 객체.를 이용해서 사용하는 것이 아니라, 클래스.을 이용해서 사용하는 것이 좋다.

***여러개의 어느 객체에서든 객체.변수명에 새로운 값을 대입하면, 클래스의 것인 static 변수가 바뀐다. 그러나 정식으로 접근하는 것은 아니다.***

 - static final의 형태로, 상수값 선언할 때 사용한다. (클래스의 단 하나의 것이면서, 안움직이게!)


public class Car{

Stirng color; // static 없으니 객체의 것(객체를 선언해서 거기서 사용) --> Car1.color, Car2.color

static String modelName; // static 있으니 클래스의 것(클래스 내부에서만 저장) --> Car.modelName / Car1.modelName도 가능하긴함

static int maxSpeed = 300;

}


..

public class Car {

public static int height;//static을 붙혔으니, 메인함수에서, 객체없이 [Car.변수명]으로 바로 쓸 수 있다.

}


public static void main(String[] args) {

Car.height = 100; // Car의 객체 car 생성 없이도, 바로 쓸 수 있는, 클래스의 것인 static 변수


...

//객체에서 height 값을 주지 않았으나, 클래스의 것인 static변수 height는 , 어느 객체에서든 --> 클래스의 static 변수로 접근이 가능하며, 클래스내부 1개의 값만 호출한다. 그러나 객체를 통한 접근은 정식접근이 아니다.

System.out.println(c1.height);

//c1에서 클래스의 것인 static변수  height에 값을 대입하면, c2에서 접근하더라도 클래스의 것인 height는 입력한 값이 출력된다.

c1.height=200;

System.out.println(c2.height);

System.out.println(Car.height);


}


---출력값--------------------

100

200

200

------------------------------


7. 객체 생성과 사용

 - new 라는 예약어생성자를 호출하여( new Object()) ---> ReferenceType변수(참조형 변수, 클래스명)에 대입을 하는 것이다.  

   Object o = new Object();

 - 한 클래스 안에 , 다른 클래스의 객체를 , 필드로 가지고 있는 경우 : has a 관계


public class Wheel{

int radius;  // 반지름을 필드로 가지는 Wheel클래스

}


public class Car{

Wheel wheel; // Wheel클래스의 객체를, 필드로 가지는 Car클래스

String meodel;

}


 - 이때, Car는 Wheel을 가지고 있는 has a 관계이다.

 - 이것을 메인함수에서 사용해보면,


Car c = new Car();

Wheel w = new Wheel(); //w에 객체를 생성함

c.wheel = w; // 생성된 객체를 같은 타입의 c.wheel에다가 대입해주니, c.wheel에는 Wheel객체인 w가 참조됨

c.wheel.radius = 100;


 > 객체지향의 특징으로, c는 Car의 객체로서, wheel이라는 Wheel의 참조형변수를 가지고 있다(아직 객체 생성은 안됬다). 거기다가 new생성자를 호출해서 객체를 생성한 w를 대입해주면, c.wheel에는 w객체를 참조하게된다.  c.wheel이라는 객체는 Wheel의 객체와 같으므로, radius라는 필드를 가지니, 거기다 100을 대입했다.

 >  이때, c.wheel.radius =100;과   w.radius=100;은 똑같다.  w 자체가 c.wheel에 담겨 있으므로, w에 대입해주나 c.wheel에 대입해주나 같이 c. 안에 들어가게 된다.    ( 객체지향으로, w는 c.wheel담겨져 참조된다.  w에 대입해도 c.wheel 안에 들어가게 된다 )


8. JVM메모리의 구조

 - Method area / Stack Area / Heap Area로 구분된다.

(1) Method Area : class에 관련된 정보들이 저장된다. (static 등..)

(2) Stack Area : 매쏘드가 실행이되는 부분(main())에서 사용되는 변수들이 저장된다.

(3) Heap Area : 각 객체가 new Car(); 으로 만들어 질 때, 각 객체들의 정보가 저장된다. 

Stack Area에서 Car a = new Car();로 변수에 참조를 할 때, 여기의 객체정보들이 쌓여서 참조된다.


객체HeapArea에서 hashCode를 가지고, StackArea의 각 변수들이 이 hashCode들을 참조하고 있다.


//객체를 출력해보면, 속한 패키지. 클래스명 @ 해쉬코드가 찍힌다.

System.out.println(c1);

System.out.println(c2);


//c2를 c1에 대입하면, heap area의 c2에 연결되던 new Car() 객체 정보가 -> Stack Area의 변수 c1과 연결되서 , 기존 c2와의 연결은 끊어진다.

c1 = c2;

System.out.println(c2);

----

classa.Car@7852e922

classa.Car@4e25154f

classa.Car@4e25154f

---------------------


9. 실습


public class Car {

private String owner;

String name; //접근제한자 default

protected String color;

public static int height;//static을 붙혔으니, 메인함수에서, 객체없이 [Car.변수명]으로 바로 쓸 수 있다.

//생성자 생성 [Ctrl + Space]로 default 생성자를 바로 생성할 수 있다.

//default 생성자. 클래스와 똑같은 public이라는 접근제한자를 가진다.

public Car() {

}

//직접 생성자 생성. 접근제한자는 클래스의 접근제한자와 동일하게 해주는 것이 좋다.

public Car(String owner) {

this.owner = owner; //클래스의 멤버변수(필드)에 대입하려면 this.멤버변수(필드) 에 대입한다.

//다른 방식으로서, 인자를 2개를 가지고 있지 않더라도,인자 1개의 생성자라도 임의의 값을 넣어서 인자 2개인 생성자를 호출할 수 있다.

//this("임의의색으로 다른 생성자 호출", owner);

}

//생성자 오버로딩을 이용해서, 파라미터를 더 추가했다. 

public Car(String color, String owner) {

this.color = color;

this.owner = owner;

}



public static void main(String[] args) {

Car.height = 100; // Car의 객체 car 생성 없이도, 바로 쓸 수 있는, 클래스의 것인 static 변수

Car c1 = new Car();

c1.name = "조재성 카";

//생성자를 이용한 객체 생성. ()안에 ctrl+space로 고를 수 있다.

Car c2 = new Car("조재성");

c2.name = "조재성 카2";

//syso + Ctrl+space를 하면 자동완성된다.!

//객체어서 height 값을 주지 않았으나, 클래스의 것인 static height는 , 어느 객체에서든 --> 클래스의 static 변수로 접근이 가능하다.

System.out.println(c1.height);

//c1에서 클래스의 것인 static변수  height에 값을 대입하면, c2에서 접근하더라도 클래스의 것인 height는 입력한 값이 출력된다.

c1.height=200;

System.out.println(c2.height);

System.out.println(Car.height);

//클래스의 것은, 객체 어디서든 접근가능하나

//객체의 것인, 필드들은, 각각 다르다.

System.out.println(c1.name);

System.out.println(c2.name);

System.out.println(c1.owner);

System.out.println(c2.owner); //c2는 생성자를 통해 각 객체의 것인 필드값에, 소유자를 적어서 생성했으니, null이 안뜬다.


//객체를 출력해보면, 속한 패키지. 클래스명 @ 해쉬코드가 찍힌다.

System.out.println(c1);

System.out.println(c2);


//c2를 c1에 대입하면, heap area의 c2에 연결되던 Car 객체 정보가 -> Stack Area의 변수 c1과 연결되서 , 기존 c2와의 연결은 끊어진다.

c1 = c2;

System.out.println(c2);

}


}

[1]변수(Variable)

변수의 분류 - 객체 변수/ 클래스변수 / 지역변수/ 인자형 변수 or 참조형 변수 / 기본형 변수




1. 객체형 변수 (Instance Variable) - non-static field

- 객체형 변수란 ? 클래스 안에 선언되어있는 변수로 [ 필드 혹은 멤버변수 ]라고 부른다. 

- 필드의 종류도 2가지가 있다. static이 붙어 있는 것과 static이 없는 것이다. 일반적으로 static이 안붙어 있는 것을 [ 필드 혹은 멤버변수 ]라고 한다.

- 클래스로 객체를 생성할 때마다, (객체.변수)로 사용할 수 있다.


2. 클래스 변수(Class Variable) - static field

 - 클래스 변수란 ? 클래스 안에 선언되어 있으면서 static이 붙어 있는 변수로 [ 스태틱 필드 ] 라고 부른다.

 - 클래스에만 하나가 존재하여 저장되는 변수로, 객체형변수와는 다르게, (클래스명.변수)로 사용하며,

   생성된 여러 객체에서도 호출이 가능하나 (객체.변수) but 클래스 안에 하나의 형태로 저장된다.


3. 지역변수(Local Variable)

 - 지역 변수란? 매쏘드()안에 존재하고 있기 때문에, 필드(클래스 안에 존재하는 변수)와 다르게, [반드시 초기화]를 해줘야한다.

 - 멤버변수라 불리는 필드는 초기화가 필요없다. 자동으로 초기화가 된다. 그러나 매쏘드()안에 있는 변수는 반드시 초기화를 해줘야한다


4. 인자형 변수(Parameter)

 - 인자형 변수란? 다른 언어에서는 argument라고도 불리며, 매쏘드()가 실행 될 때, 넘겨 받는 변수다. 


5. 변수의 이름 붙이기(naming) - 식별자(identifier) 규칙

 -  숫자로 시작할 수 없으나 영대 소문자나 숫자가 들어갈 수 있으며, 특수 문자 중 [ _ 와 $ ]를 넣을 수 있다.

 - 관례(convention) : 소문자로 시작하며, $는 사용하지 않으며, _를 쓸 경우에는 맨 앞에 잘 사용하지 않는다.

 ex> String name; (O) String 5name&;(X)  /  int powerPoint; (O) int _name;(세모)


6. 형태(Type)에 따른 구분

 (1) 참조형 변수(Reference Type Variable) : String  name; Test t; Object o; 등 앞글자가 대문자로 시작하여, 내부에 클래스를 가지고 있다.

 -> 필드와 매쏘드()가 사용 가능

 (2) 기본형 변수(Primitive Type Vairable) : int a; float f; char c; 등 소문자로 시작하며, 내부 클래스가 없다. 객체에 속하지 않는 것들임.


[2] 기본형 변수(8)와 참조형 변수

(1) 수치형 변수(6) : 기본형 변수 8가지 중 6가지는 수치를 나타내는 것으로, byte/ short/ int/ long 등 정수형 변수 와 

float/ double의 실수형 변수가 있다.

 - 순서대로 1/2/4/8 byte 와 4/8byte의 크기를 가진다.

 -  bit가 0,1로 이루어져있는데, 1byte는 8bit로 bit가 8개 있으므로, 0000 0000 ~ 1111 1111으로 구성 된다.

 -  byte의 8자리 중 첫번째 bit는 [부호비트]로 0은 양수, 1은 음수를 의미한다. 나머지 7자리의 bit가 숫자를 구성하므로  범위를 따지면 [ -2^7부터 ~ (2^7-1) ]로, 0을 양수에서 -1로 차지한다.

   ex> int는 4byte이므로, bit가 8 x 4 = 32 개 존재한다. 첫번재 부호비트를 제외하고 31자리의 bit가 숫자를 결정하므로, -2^31 ~ (2^31-1)의 범위를 가진다.


(2) 문자형 변수(char) : 문자 하나를 표현하는 것이다. 작은 따음표로 감싸서 문자 1개를 표현한다. ex>'가', 'a'

(3) 논리형 변수(boolean) : true or false를 의미한다.


(4)참조형 변수(String) : 문자의 집합로 큰 따옴표로 표시한다. "a가 b는 아니다"


- 기본형 변수들은 [기본값]을 가진다.

 byte, short, int 0 / long은 0L / float는 0.0f / double은 0.0d 가 기본값이다.

 char'\u0000'의 유니코드 값을 기본값으로 가진다.

 booleanfalse를 기본값으로 가진다.

- 모든 참조형 변수는 기본값이 null이다.


(5) 기본형 변수 표기법

 - 10진수 표기법 int a = 10;

 - 16진수 표기법(0x XXX형식으로 표기) : int a = 0xa; (a는 10을 의미한다)

    cf) 16진수는 0부터 9, A(10) ~ F(15)까지 총 16가지의 문자로 숫자를 표현하는 것을 말한다.

 - 2진수 표기법(0b XXXX형슥으로 표기) : int a = 0b1010;(1010은 2진수로 10을 의미한다.)

 - 실수 일반 표기법 : double d = 123.4;

   지수 일반 표기법 : double d = 1.234e2; (e2는 100을 곱하는 것을 의미한다. d에는 123.4가 들어간다)

 - 문자 표기법 : char 는 ''; / String은 "";

 - 유니코드(UTF-16) 표기법 : 모든 문자는 2byte로 표기가 가능하다. 한글 가 도 2byte이다. '가'의 유니코드 값은 AC00이라는 코드를 가진다. 이런 것들의 모임은 charSet이다.

    char c= '\uAC00';  String s= "\uAC00";

 - Escape Sequence(특수한 표기법, escape문자) : 

   \b (backspace), \t(tab), \n(line feed), \r(carriage return, 엔터키), \"(double quote, 쌍따옴표), \'(single quote,작은 따옴표), \\(back slash)

 - 언더바(_)문자 사용(se7부터 적용) : 숫자의 시작or끝에는 쓸 수 없고, 중간에 넣어서 구분을 위해서 넣어준다. ex> 전화번호, 카드번호 등등


[3] 배열(array)

 - 배열이란? 똑같은 형태의 변수들의 집합체로, 방번호가 붙은 호텔과 같은 개념이다.

 int[] a= new int[6];식으로 선언한다. 마지막의 6은 6개의 방을 만들어라는 의미이다. 

 - 방 번호를 index라 하는데 0부터 시작한다. 0부터 5번방까지 총 6개(length)의 배열이 만들어진 것이다.

 - int클래스x 대문자로시작x인 기본형 변수이므로, default값= 기본값을 0으로 다 가지고 있다. 만약 2번 방을 끄집어 내고 싶다면, 대괄호 a[2]로 끄집어 낸다.

 (1) 생성법은 3가지가 있다

int[] a = new int[6];  - int뒤에 바로 []를 넣어서, 우항에는 방의 번호를 집어넣는다.

int []a = {1, 3, 4, 5, 6, 3}; - 변수앞에 바로 []를 넣어서, 우항에는 값을 집어 넣어, 방번호를 간접적으로 만든다.

int a[] = new int[]{1,2,3,4,5,6}; - 변수뒤에 바로 []를 넣어서, 빈방과 값을 동시에 집어넣는다.


 (2) 2차원 배열 

int[][] a = new int[2][2]; - int뒤에 넣어서, 2차원 방번호를 집어넣는다.

int[][] a = { {1,2}, {3,4}}; - int뒤에 넣어서, 중괄호를 이중으로 해서 값을 집어넣는다.


  

[4] 실습

javase05 자바프로젝트를 만들고, 패키지명은 var, 클래스명은 TestVar, 메인함수까지 포함해서 만든다.


package var;


public class TestVar {

//클래스 안에 적었으니, static이 안붙은 [ 필드(field) 혹은 멤버변수 혹은 객체가 쓰는 객체형 변수 ] 혹은 static이 붙어 있는 [클래스 변수]가 될 수 있다.

String name; //static이 안붙어 있으면, 객체가 쓰는 변수로 [쓰는 곳에서는 클래스 객체가 필요하다! 메인함수에서 객체를 만들어서 써야한다] 

int height;

static int power=100;


public static void main(String[] args) {


//메인 함수 안에 적었으니, 지역변수(Local variable)이다.


byte b = 1;

short s = 4; //int를 제외하고 잘 안쓰는 byte, short는, 엄청 큰 배열일 경우 크기를 고려할 때 byte배열이나 short배열을 사용한다.

int i = 1000;

long l = 10000000000L; //int의 범위(20억)을 넘는 수를 짚어 넣을 수 있다. L을 안붙히면, int로 인식되서 오류가 뜬다.

float f =3.14f;

double d= 3.14;

char c = '가';

boolean boo  = true;

String str = "조재성";

TestVar t = new TestVar();

System.out.println(t.name); //클래스의 객체형 변수, 필드, 멤버변수는 초기화 안해두 null이라는 값으로 자동초기화 되어있다

String name;

System.out.println(name); //메쏘드 안의 지역변수는 , 초기화 하지 않으면, 오류가 뜬다. 지역변수는 반드시 초기화를 해야한다.

String name2="";

System.out.println(name2); //지역변수는, 문자형변수라면 "";로 초기화 해야한다.

}


}

[프로젝트 : javase04 ]


[1] 인터페이스(interface) - 수단


예를 들어, 프린터 포트, vgb포트, usb포트 등 모두 단자, 인터페이스로서 바깥 세상과 통신하기 위한 수단이다.

data encapsulation이란 어떤 객체가 지정된 매쏘드에 의해서 바깥과 통신하는 수단을 구축하는 것이다. 이것을 통해 여러 이익들이 얻어질 수 있다.

이 데이타 인캡슐래이션을 구현화 하는 개념 중 하나가 인터페이스다.


쉽게 설명하면, [노래방 리모콘의 버튼]이라고 생각하면 된다. 숫자를 누르고 시작버튼을 누르면 -> 어떤 객체가 수행할 수 있다는 것을 외부에 알려주면서 통신도 일어나게 한다. 

일반적으로 메세지를 주고 받는데, 객체<->객체간에 주고 받는데, 그 메세지를 주고받기 위한 수단(통로)이 interface이다.

*인터페이스는 매쏘드의 내용이 없고, 선언만 있다.

왜냐면 인터페이스는 외부와 통신하기 위한 수단이므로, 노래방리모콘의 시작버튼일 뿐, 겉에서 볼 땐 노래를 시작하게 하는 것은 아니다.


1. 

public interface Touchable {

void touch();

}


- [public]은 '접근제한자' 라고 한다. 

- [interface]는 인터페이스를 의미한다. 필드와 매쏘드를 가진 클래스라면 class가 들어갈 것이다.

- 클래스와 형식은 보이지만, void라는 [리턴타입]과 Touch()라는 [매쏘드]만 있고 {   }중괄호로의 내용은 없이 바로 끝이난다. 이런형태가 인터페이스이다.

즉, 매쏘드의 선언만 있을 뿐이다.


2. 다형성(Polymorhism)

public class SmartPhone implements Touchable {


public void touch(){

System.out.println("터치를 하다.");

}

}


- 클래스 SmartPhone은 인터페이스 Touchable을 상속하였다(implements). 상속이라는 것은 부모클래스가 자식클래스에게, 자기가 가진 필드와 매쏘드를 물려주는 것인데, 인터페이스도 상속이 된다.

- 클래스의 상속은 [extends]를 쓰지만, 인터페이스의 상속은 [implements]라는 예약어 쓴다.

* 클래스의 상속은 구현화안해도 되지만, 인터페이스의 상속은, 인터페이스에는 실제적인 내용이 없기 때문에, 상속받는 SmartPhone이라는 클래스에서 반드시 구현을 해줘야한다.

 위 코드에서 Touch()매쏘드가  { }중괄호가 열리면서 내용을 작성하였다.

* 인터페이스는 상속(implements)시 여러개의 상속이 가능하다.



[2] 패키지와 API(package & API)


패키지(package) :  interface나 class(객체를 찍어내는 틀, 공통 필드와 매쏘드를 쓰게함)들을, 목적이 비슷한 종류끼리 모아놓은 폴더 같은 것

API(Application Programming Interface) : 프로그램을 만드는데 필요한, 미리 제공되는 패키지(interface+class 모음 폴더)들의 집합 by JDK

*나는 

패키지=class + interface의 모음/ 

API = class+interface의 모음인 패키지들이 제공되는 것 = 라이브러리

이라 기억할 것임.

가장 먼저 볼 패키지는 Java.lang이라고 하는 패키지이다. 실습시간에 살펴본다.

구글에서 Java SE 8 API 검색 하면된다. 라이브러리라고도 한다.


총정리)

자바는 OOP의 개념으로 이루어진 객체지향언어이다. 객체끼리 메세지를 주거받거나 객체를 매쏘드로 이용하는 것

객체는 모든 것이다.

클래스는 객체를 만들어내는 틀이다.

상속(inheritance)는, 클래스만으로 부족하여, 부모클래스가 자식클래스에게 Field와 Method를 물려주는 것이다.

인터페이스(interface)는 다른 객체와 통신하기 위한 수단이다.(내용물은 x , 쓰는놈이 구현화해야함)

패키지(package)는 class와 interface들인데, 비슷한 목적을 가진 것들을 분류해놓은 폴더이다. ex> java.lang



[3] 실습 [javase04]

(1) 새로운 프로젝트(javase04)를 만들고, src > 우클릭 > java > interface >  Package(클래스+인터페이스 모음) : test / Name : Touchable 이라 만든다.

(2) 내부에 void touch(); 매쏘드를 만들자. 인터페이스는 { } 중괄호를 이용해서 매쏘드의 [body]를 만들어주면 오류가 뜬다.  내용물은 비어있어야한다.


package test; //패키지 선언이다. 인터페이스 Touchable은 test라는 패키지안에 들어있게 된다.


public interface Touchable {

void touch();

}


(3) 이제 Touchable을 상속받는 클래스 SmartPhone을 만들어본다. 

 *test패키지 우클릭 >new>class> 

Package : test확인 후 / Name에 SmartPhone / Interfaces > Add... > Touchable을 검색해서 상속할 인터페이스를 추가 / main매쏘드 추가(실행할 클래스니까)


package test;


public class SmartPhone implements Touchable {


@Override

public void touch() {

// TODO Auto-generated method stub


}


public static void main(String[] args) {

// TODO Auto-generated method stub


}


}


(4) 생성해보면 위와같이, touch()라는 매쏘드가 자동으로 오버라이딩 되어있다. ( touch()에 에러가 나면, 이클립스를 다시시작하면 없어진다.)

(5) touch()매쏘드 내부에는 출력문을 하나 적어준다. 

(6) 메인매쏘드에서는 SmartPhone의 객체를 하나 만들어보고, 클래스의 touch()매쏘드를 호출해서, 실행시켜보자. 

public static void main(String[] args) {

// TODO Auto-generated method stub

SmartPhone s = new SmartPhone();

s.touch();


}


(인터페이스의 빈 매쏘드-> 구현화로서, 내용을 적어주고 -> 객체를 생성해서 사용) : 

굳이.. 빈 매쏘드를 채워서 사용하는지 아직까지는 필요성을 못느끼겠다.



[4] API문서(비슷한목적의 class/interface를 모아놓은 패키지를 제공해주는 것 = 라이브러리) 보기

1. 구글에 'java se 8 api'라고 검색한 뒤, 오라클 홈페이지의 문서를 보자(프로그램 제거에서 나의 자바버전 확인했다)

- https://docs.oracle.com/javase/8/docs/api/

2. api문서에서 첫번째 화면에 Packages가 나와있다. java.***.*** 이 설명과 함께 제공된다.

3. java.lang을 찾아가보자. 자바프로그래밍 언어의 디자인에 대한 기본적인 클래스들이라고 나와있다. 클릭해보자.

4. Interface Summary 와 Class Summary가 있다. 여기서 눈여겨볼 것은 Class Summary의 Object다.(클래스, 인터페이스는 대문자 시작)

- Object는 모든 클래스 계층구조(hier archy)의 뿌리. 이말은, 우리가 만든 모든 클래스의 머리에는 Object가 부모로 존재한다.

5. Object를 클릭해보면, 생성자(Constructors)에 대한 설명이 나온다. 그리고 Method에 대한 것들이 나온다. 

6. 우측의 hashCode()라는 매쏘드를 써보자.설명에는 객체에 대한 해쉬코드를 리턴해주는 매쏘드라 나와있다.


7. 실습화면에서

(1) SmartPhone객체를 참조한 변수 s.hashCode();를 작성해보자. (즉, 우리가 만든 클래스 SmartPhone이라는 것은, 클래스이므로 object클래스의 자식이고, 그 Object라는 클래스속 매쏘드 .hashCode();를    우리가 만든 클래스의 객체인 s에서도 사용이 가능한 것이다.)

(2) 이걸로 끝이 아니다 hashCode();에 마우스를 갖다 대면 리턴타입으로 int라고 나와있다. 좌항에서 int변수에 결과값을 받는다. 그 값을 출력해보자.

-hashCode();는 객체마다 고유의 int값을 리턴한다.


SmartPhone s = new SmartPhone();

s.touch();

int i = s.hashCode();

System.out.println(i);


8. 중요한 것은,  우리가 만든 클래스일지라도, SmartPhone 이라는 클래스는 Object를 상속받고 있고, 그 Object의 매쏘드인 hashCode();라는 매쏘드를 쓸 수 있다.

 

[프로젝트 : javase03 ]


[1] 데이터 캡슐화(data encapsulation)


캡슐화란 캡슐처럼 안쪽 내용물이 전혀 보이지 않게 된다. 이때, 안쪽의 내용물은 데이터 혹은 필드(속성)을 의미한다. 

그리고 그 속에 필드와 같이 정의된 매쏘드를 통해서 필드는 외부와 통신하게 된다.


*캡슐화에 따른 이익

1. Modularity(모듈화) : 객체 안에다가 쓰인 소스코드가 <독립적>으로 존재할 수 있게 되어, 어디서든 쓰일 수 있는 <유연성>이 생긴다.

2. information-hiding(정보 은닉) : 가장 기본적인 특징이다. 정보은닉의 대표적인 예가 데이터캡슐화라고 할 수 있다. 안쪽의 상세내용을 숨기면서 매쏘드를 통해 외부와 통신한다.

3. Code re-use(코드 재사용) : 잘 만들어진 객체는, 다른 개발자들이 가져와서 재사용할 수 있다. 모듈화를 해놨기 때문에 가져와서 붙혓다가 뗄 수 있는 것이다.

4. Pluggability and debugging ease : 플러거빌리티는 마음대로 뺏따 꼽았다 하며 대체될 수 있다는 뜻이고, 하나의 모듈로서 다른 것과 맞물리지 않기 때문에 디버깅 하기 쉽다. 고장나면 바꿔끼면 된다.




[2] 상속(inheritance)


부모클래스가 자식클래스가 <필드와 메소드>를 물려주는 것. is a(이즈 어) 관계라고 한다.



예를 들어)  

[생물] 이라는 클래스는  

[동물] 과 [식물] 클래스로 나뉘어진다.(자식클래스로 가진다)


이때, 포함관계를 생각하여 반대로 화살표(uml, 상속을 나타내는 화살표)는 거슬러서 올라간다고 생각하면, 

[동물->생물] or [식물-> 생물]의 관계가 된다고 생각할 수 있다.

 [동물] is a [생물] , [식물] is a [생물] 이 된다.

[동물]도 [포유류]와 [조류] 로 나눌 수 있고, [포유류]도 [인간]과 [원숭이]로 나눌 수 있다.

이러한 것을 계층구조도 [hierarchy(하이어러키)] 라고 한다.

화살표가 위로 갈수록 <일반화> 내려갈수록 <구체화>가 되는 것이 계층구조도의 특징이다.


이때, 부모클래스는 필드와 매쏘드를 물려준다고 했으니, [생물]이 살아있다()라는 매쏘드를 가지고 있다면, [동물]과 [식물]모두 살아있다()라는 매쏘드를 가지고 있게 된다.

[동물]이 움직인다()매쏘드를 가지고 있으면, [포유류], [인간] 과 [원숭이] 다 같이 움직인다() 가지게 된다. 

그러므로 굳이 [인간]은 움직인다()라는 것을 매쏘드를 만들어 놓을 필요가 없게 된다. 

=> 반복적으로 들어가야하는 코드를 줄여주는 상속의 가장 큰 특징이 있다. 형변환에 있어서 가장 큰 힘을 발휘하는 것이 상속이다.


자바의 구조는 모든 계층구조도의 위(root)에는 Object(객체)라는 클래스를 가진다. 

Object(객체)라는 클래스에 있어서 위로 올라가는 <is a>관계를 생각해보면, [생물]도 Object(객체)고, [동물]도 객체고, [포유류]도 객체고, [인간]도 객체가 되게 된다.



public class Car{


String color; // [ 필드 ]  혹은 [ property ] 혹은 [ member variable(멤버변수) ] 3가지로 불린다.

void run(){   //매쏘드

System.out.println("차가 달립니다"); 

}

}


public class Avante extends Car{   // Avante클래스는 위에서 만든 Car라는 클래스를 상속하였다.

public static void main(String[] args){

Avante a = new Avante(); // 객체를 만들어서, a라는 변수에 넣어줬다. 

a.color = "빨간색"; // Car클래스를 상속한 Avante의 객체는 Car클래스의 필드(color)를 사용할 수 있따.

a.run();    // Car클래스를 상속한 Avante의 객체는, Car클래스의 매쏘드run()을 사용할 수 있다.


}

}


*멤버변수 = 클래스 내 필드 라 생각하는 버릇을 가지자


(1) extends는 상속의 예약어(다른데서 쓸수 없음) 이다.

(2) 구조는 [Car]라는 클래스가 있고, [Car]에는 color와 run()매쏘드가 있다. 그리고 [Avante]는 [Car]를 상속했다.

    -> Avante는 Car의 필드와 매쏘드를 모두 쓸 수 있다.

(3) 메인매쏘드라는 것은, 클래스를 실행할 때, 실행되는 매쏘드이다.

(4) [Car]는 [부모클래스] = [super class], [Avante]는 [자식클래스] 혹은 [sub class]



[3] 실습


1. 이클립스 폰트 설정 바꾸기

(1) 구글에서 naver개발의 '나눔고딕코딩' 글자를 다운받는다. 영문과 고정폭을 가지고 있어서 쓰기가 좋다

 - https://github.com/naver/nanumfont

(2) 다운받은 파일을 더블클릭해 설치한다.

(3) 이클립스의 window>preferences> General > Appearance > Colors and Fonts > Basic > [ Text Font ]를 선택 - Edit버튼을 눌러, 

나눔고딕코딩 글꼴을 선택 & 글자크기도 조절한다.

* 나는 기존에 것이 더 맘에 들어서 default 눌러서 다시 돌아왔음.

* 만약 줄번호가 보이지 않는다면, 회색부분에서 우클릭으로 show line numbers를 선택해준다.

*  우측 상단에 J 모양의 아이콘은 Perspective(펄스펙티브)아이콘으로, 자바클래식에서 다양한 시각으로 왔다갔다 할 수 있다. 

이것을 끌어다가 PackaageExplorer의 왼쪽 패널로 이동시키고, show text로 바꿔주자. 


2. 실습하기


(1) 새로운 프로젝트 javase03으로 만든다.

(2) src폴더에 우클릭 > new class> Car라는 클래스이름으로 생성하고, 

나중에 만들 클래스에서 필드와 매쏘드만 상속하고, 실행은 안시킬 것이기 때문에 메인함수 생성은 체크하지않는다.

안에 필드와 매쏘드를 만들어 준다.


public class Car {

String color; //필드, 멤버변수


void run() {  //매쏘드

System.out.println("차가 달려요");

}

}


(3) src폴더 우클릭> new class> Avante클래스를 만드는데, superclass에 기본 <java.lang.Object>로 되어있는 것을 [edit]를 눌러,

 <Car>를 쳐서 검색하여 선택한다. 메인매쏘드도 체크를 해준다.


(4) Avante클래스의 메인함수에다가, 객체를 생성하여 변수 a에 넣어준다. a. 만 쳐도, 상속한 Car클래스의 필드와 매쏘드가 자동완성 항목으로 뜨게 된다.

public class Avante extends Car {


public static void main(String[] args) {

// TODO Auto-generated method stub

Avante a = new Avante();

a.color ="빨간색";

a.run();

System.out.println(a.color);


}


}



[프로젝트 : HelloProject ]


1. 객체지향프로그래밍(Object Oriented Programming)

-프로그램을 객체들의 모임으로 구성한다. Object(객체)가 모든 것이다.

-이에 비해 c언어는 명령형 프로그래밍으로 취급한다.


2. Class는 Object(객체)를 만들어내는 틀이다.

- 클래스는 설계도의 개념으로 ---> 실제 객체들1,2,3을 만들어낸다.

- 클래스 안에는 객체들의 공통된 [ 속성(Field, propery)-값을 가지는 명사 ] 와  [ 메쏘드(Method)-어떤행위를 하게하는 동사 ]들이 선언된다. 

  객체가 만들어질 때, 클래스에서 선언된 [속성]과 [메쏘드]를 가지고 있게 된다.


3. 자바에서 실제 구현

(1) 클래스 생성

public class Avante {


private String color; //필드(속성)


public void openDoor(){ //메쏘드

System.out.println("문이 열렸다");

}


}


(2) 객체 생성 : 메인매쏘드(실행시킬 때, 필수적으로 만들어주는 것) 안쪽에서, 객체를 생성해본다.


Avante avante1 = new Avante(); 

- new라는 예약어Avante();라는 생성자를 통해 객체가 만들어진다. 여기서 avante1은 변수다.

- 객체들이 클래스에서 만들어지면, 각 객체는 새로운 것이다. 그래서 new라는 예약어를 사용한다.


Avante avante2 = new Avante();

- 변수 avante2 , 예약어 new, 생성자 Avante();를 통해 새로운 객체를 만들었다.

- 변수들이 실제 객체를 반영한다. 이를 변수가 객체를 '참조한다'라고 한다.

- 이때, Avante();라는 부분은 생성자(Constructor) 부분이다. 실제로 객체를 생성하는 부분이다. 


avante1.color = "빨간색";

- 첫번째 객체가 클래스에 선언된 필드를 이용했다. 클래스에서는 private String으로 선언한 문자형 변수다(초기화 없이 변수선언한 것과 동일). 이걸 필드라 하고 사용방법은 위와 같다.


(3) 실습 [프로젝트명 HelloProject ]

-Hello라는 클래스를 메인함수를 포함해서 만들어준다. 간단한 출력문을 기입하고  ctrl+s로 저장하고  실행시킨다.

-이제 본격적인 클래스를 만들기 위해 다시 src에서 클래스를 메인함수를 포함해서 만든다.

- 클래스가 가지는 필드와 메쏘드 중, 필드를 추가시켜본다. 

public class Avante {


String color; //필드 선언

void run() { //메쏘드 선언

System.out.println("아반테가 달려요.");


}

-이제 메인매쏘드에서 객체를 생성해본다. 객체 생성시는 new라는 예약어와, 클래스명과 동일한 생성자 Avante();를 통해 생성한다. 객체는 언제나 새롭게 만들어지는 것이다.

new Avante();


- 이제 생성된 객체가 실제로 사용이 되려면 Avante타입의 변수를 선언해서 참조해야만 사용가능하고, 계속 사용할 수 있다.

Avante a1 = new Avante();


- 새로운 객체를 만들어보자. 참조할 변수명은 달라야한다

Avante a2 = new Avante();


- 각 객체에 필드를 이용해서 색을 넣어보자.

a1.color = "빨간색";

a2.color = "파란색";


- 이제 출력하는 객체를 이용해서 클래스내부의 메쏘드를 호출해보자.

a1.run();

a2.run();


- 이제 필드를 사용한 객체를 출력해보자.

System.out.println("a1의 색은?"+a1.color);

System.out.println("a2의 색은?"+a2.color);


* (=)대입연산자는 오른쪽값을 왼쪽에 넣어주는 의미이다.

+ Recent posts