2011/09/25 01:54

Java 의 철학 - Write Once, Run Evrywhere

과연 이 철학이.....



- The Java Programming Language

객체지향... 이놈은 자바 언어 Software 기술중에 하나.
하지만 가장 큰 특징은 생산성의 극대화, 동적인면임!
Multi-Threding
구조화된 에러 핸들링
Garbage Collection
Dynamic Linking
Dynamic Extension


- The Java Class File Format

compact 한 형태
bytecode 로의 변경
platform 독립적
network byte order 사용

class 파일은 bytecode 를 binary 형태로 담아놓은 것.
bytecode 는 JVM 이 읽을 수 있는 언어.

JVM 은 Class 를 로딩한 후 여기서 Bytecode 를 읽어들여 실행이 가능하도록 Interpret 하는 과정을 거침. Class 가 Load 된 후 JIT Complier 나 Hotspot Compiler 와 같은 Execution Engine 을 거쳐 실행이 된다.

ByteCode 는 Source code 를 단순히 JVM 의 언어로 번역해 놓은 것이기 때문에 Source 파일과 비슷한 크기를 가지고 있다. C++, Delphi 와 같은 언어에 비해 아주 작은 크기. 이렇게 작은 크기를 유지할 수 있는 이유는 Class 파일에는 실제로 참조하는 라이브러리를 포함하고있지 않고, 단지 Symbolic Reference 만을 가지고 있기때문...

Symbolic Reference 는 참조하고자 하는 대상의 이름만으로 참조관계를 구성한 것을 의미. 참조하는 객체의 특정 메모리 번지로 참조관계를 구성한것이 아니고 참조하는 대상의 이름만을 지칭한 것.

Class 파일이 JVM 에 올라가게 되면 Symbolic Reference 는 그 이름에 맞는 객체의 주소를 찾아서 연결하는 작업을 수행함. 이를 Dynamic Linking 이라고 한다. Java 는 이 Dynamic Linking 때문에 Class 파일은 compact 한 형태를 유지할 수 있다.

Class File Format 은 Network Byte Order 를 사용한다. 서로 다른 계열의  CPU 끼리 데이터를 전송 받을 때의 문제점을 해결하기 위해 정해준 일족의 약속임. Big Indian 을 사용.



- The Java Application Programming Interface (Java API)

Runtime Library의 집합. 말 그대로 Java 실행 환경. 여기에는 Java Virtual machine 과 Java API, 그리고 Native Method 등이 포함되어있다.

Java API 는 OS 시스템과 Java 프로그램 사이를 이어주는 가교의 역할을 한다. Native Method 를 통해 OS 자원과 연계되어있고 다른 한 편으로는 Java 프로그램과 맞닥뜨리고 있다. Interface 의 역할을 하고있는 셈.


- The Java Virtual Machine (JVM) 

JVM 은 하나의 스펙.







 
Posted by 개발자 용이~
2011/09/01 22:45

execution([접근자제어 패턴], 리턴타입패턴 [클래스명패턴]메서드명패턴(파라미터패턴))


접근자제어
  - 생략가능 (public, protected 등)

리턴타입
  - 리턴 타입

클래스명,메서드
  - 패키지명부터시작해서 메서드까지
 
파라미터패턴
  - 매칭될 파라미터에 대해서 명시.
      

- 각 패턴은 '*'를 이용하여 모든 값을 표현
- '..'을 이용하여 0개 이상이라는 의미를 표현

Posted by 개발자 용이~
2010/07/28 10:23

tomcat 6 에서 GET 방식으로 파라메터 값을 읽어올 때 사용하는 캐릭터 셋의 기본 값은 ISO-8859-1 이다. 톰캣 6 에서는 두 가지 방법을 이용해서 GET 방식으로 전달된 파라미터를 읽을 때 사용할 캐릭터 셋을 지정할 수 있다.


- server.xml 파일에서 <Connector> 의 URIEncoding 속성의 값으로 원하는 캐릭터셋을 지정하는 방법


- server.xml 파일에서 <Connector> 의 useBodyEncodingForURI 의 속성 값을 true 로 지정하는 방법. 이 때는 request.serCharacterEncoding() 메소드로 지정한 캐릭터셋이 적용됨.



이 두개를 같이 사용할 수 도 있다

Posted by 개발자 용이~
2010/01/06 10:04

체크아웃 연말 이벤트! 100명에게 아이폰을 쏜다! 이벤트 보기
Posted by 개발자 용이~
2009/08/24 21:50

실행가능한 JAR  만들기.

컴파일된 파일들이 classes 디렉토리에 들어있다고 했을 경우.

실행가능한 파일을 만들기 위해서는 main() 메소드가 어떤 클래스에 들어잇는지를 알려주는 manifest파일이 필요합니다.

다음과 같이 manifest파일을 만들어 줍니다.

manifest.txt
Main-Class: MyApp

jar도구를 실행시켜서 classes 디렉토리에 들어있는 모든 파일이 저장된 jar파일을 만듭니다.

$cd classes
$jar -cvmf manifest.txt myapp.jar *.class


jar파일을 실행시킬경우의 명령
$java -jar myapp.jar



패키지를 가지고 만들기~

manifest.txt
Main-Class: com.yoyojy.MyApp

역시 classes디렉토리로 이동후에 명령어들을 써줍니다.
$jar -cvmf manifest.txt myapp.jar com
com 디렉토리만 지정하면 필요한 것들이 모드 jar파일로 들어갑니다.



이 외의 옵션들

-tf : 목록을 출력하고 파일의 내용을 풀어놓는다.
-xf : 파일들을 추출한다.

jar {ctxu}[vfm0M] [jar-file] [manifest-file] [-C dir] files ...
옵션:
    -c  새 아카이브를 만듭니다.
    -t  아카이브에 대한 목차를 나열합니다.
    -x  아카이브에서 명명된 (또는 모든) 파일을 추출합니다.
    -u  기존의 아카이브를 업데이트합니다.
    -v  표준 출력에 대한 자세한 정보 출력을 생성합니다.
    -f  아카이브 파일 이름을 지정합니다.
    -m  지정된 증명 파일에서 증명 정보를 포함시킵니다.
    -0  저장만 수행하며 ZIP 압축을 사용하지 않습니다.
    -M  입력 항목에 대한 증명 파일을 만들지 않습니다.
    -i  지정된 jar 파일에 대한 색인 정보를 생성합니다.
    -C  지정된 디렉토리로 변경하고 다음 파일을 포함시킵니다.
디렉토리인 파일이 하나라도 있으면 재귀적으로 처리됩니다.
'm' 및 'f' 플래그가 지정된 순서대로 증명 파일 이름과 아카이브 파일 이름을 지정해야 합니다.





Posted by 개발자 용이~
2009/08/04 13:39
이글의 거의 대부분은
자바가상기계 메모리 할당을 보여주는비주얼 도구의 개발(경남대학교 컴퓨터공학과 한국전자통신연구원 실시간시스템연구팀) 이라는 자료를 참조 하였습니다.

자바 가상 머신의 구조

클래스 로더 서브시스템(class loader subsystem), 실행 엔진(execution engine), 런타임 데이터영역(runtime data areas)으로 구성되어 있다.

클래스 로더 서브시스템
클래스(class)나 인터페이스(interface)의 타입을 위한 이진 데이터를 찾아 적재(loading)하고, 정확성을 검증한다. 또한 클래스 변수에 대한 메모리 할당과 디폴트 값으로 초기화를 수행하고, 그 타입에 대한 심볼릭 참조를 직접 참조로 변환한다. 그리고 적당한 시작값에 대한 클래스 변수를 초기화하는 자바 코드를 호출한다.

런타임 데이터 영역
자바 가상기계가 프로그램을 실행시키는데 필요한 메모리를 구성하고, 적재된 클래스 파일로부터 추출된 바이트 코드를 포함한 많은 정보들이 저장되는 메모리 영역이다. 세부적으로 메소드 영역(method area), 자바 스택영역(jaa stack area), 힙 영역(heap), PC 레지스터(PC register), 원시 메소드 스택(native method stack)으로 구성된다.

- 메소드 영역
적재된 이진 데이터의 타입에 관한 정보를 저장한다. 즉, 이진 데이터에서 타입에 관련된 정보를 추출해서 저장하는 영역이다. 가상 기계는 호스팅하는 응용 프로그램을 실행시 이 영역에 저장된 타입정보를 찾아 사용한다.

메소드 영역에 저장되는 정보

타입 정보( type information )
------------------------------------------------
     타입의 완전한 이름
     타입의 슈퍼클래스의 완전한 이름
     타입 식별 정보 : 클래스 또는 인터페이스
     타입의 식별자
     슈퍼인터페이스의 완전한 이름에 대한 정렬 리스트
------------------------------------------------
상수 풀( constant pool )
------------------------------------------------
필드 정보( field information )
------------------------------------------------
     필드의 이름
     필드의 타입
     필드의 수식어
------------------------------------------------
메소드 정보( method information )
------------------------------------------------
      메소드 이름
     메소드 반환 타입(또는 void)
     메소드 파라메터의 타입과 개수
     메소드의 수식어
     메소드의 바이트코드
     피연산자 스택, 지역변수 섹션 크기
     예외 테이블
------------------------------------------------
클래스 변수( class variable)
------------------------------------------------
     클래스 로더 클래스
     클래스 클래스


- 힙
프로그램이 실행될 때 자바 가상머신은 프로그램이 인스턴스화한 모든 객체를 힙에 할당한다. 자바 가상머신 인스턴스 내부에는 단 하나의 힙이 존재하기 때문에 런타임시 모든 쓰레드는 힙을 공유하고, 이러한 객체(힙 데이터)에 접근하기 위해서 멀티쓰레드의 적당한 동기화와 관계한다

- 프로그램 카운터
실행되는 프로그램의 각 쓰레드는 자신의 PC레지스터와 자바 스택을 가지는데 이것은 쓰레드가 시작될 때 생성되고, PC레지스터의 값은 실행할 다음 명령어를 가리킨다.

- 자바스택
새로운 쓰레드가 생성되면 자바가상머신은 그 쓰레드를 위한 자바 메소드 호출의 상태(지역변수, 매개변수, 리턴 값, 중간계산)을 저장하고, 현재 클래스와 현재 상수 풀의 트랙을 유지한다. 또한 쓰레드의 스택에 새로운 프레임(frame)을 형성해 푸시(push)와 팝(pop) 두가지 연산을 수행한다.

-스택 프레임
스택 프레임은 지역변수(local variable), 오퍼란드 스택(operand stack), 프레임 데이터(frame data)를 구성한다.
자바 가상머신이 자바메소드를 생성할 때 스택 프레임은 지역변수와 오퍼란드 스택에서 메소드에 의해서 요구되는 워드 수를 결정하기 위재서 클래스 데이터를 검사한다. 자마그택프레임의 지역변수는 위드의 배열로 구성되고, 메소드의 매개변수와 지역변수를 포함한다.컴파일러는 선언되어진 순서에 따라 지역변수 배열에 매개변수와 지역변수를 배치한다.
오퍼란드 스택도 워드의 배열로 구성되어있다. 하지만 지역변수와는 달리 배열 인덱스를 통해서 접근된다. 오퍼란드 스택은 값을 푸시하고 팝하므로써 접근되어지고, 오퍼란드 스택에 값을 푸시했다면, 이후의 명령어는 팝해서 그 값을 사용한다.

- 원시 메소드 스택
쓰레드가 자바로 작성된 메소드가 아닌 다른 언어로 작성된 메소드를 호출하면 이 메소드에 대한 데이터 영역이 생성된다.

실행엔진
적재된 클래스의 메소드들에 포함된 명령어들을 실행한다. 실행 엔진이 명령어들을 실행할 때 자바 가상머신은 현재의 클래스의 상수 풀, 현재 프레임의 지역변수, 현재 프레임의 오퍼랜드 스택의 탑(top)에 놓은 값들을 사용한다.
Posted by 개발자 용이~
2009/06/27 11:40
블록 암호화에서의 운영 모드
이미지의 출처는 위키피디아 입니다. (http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation)

1. ECB (Electronic Code Block) Mode
- 가장 단순한 모드로 블록단위로 순차적으로 암호화 하는 구조이다.
- 한개의 블록만 해독되면 나머지 블록도 해독이 되는 단점이 있다. (Brute-Force Arttack, Dictionary Attack)
- 암호문이 블록의 배수가 되기 때문에 복호화 후 평문을 알기 위해서 Padding을 해야한다.


- error propagation : 각 블록이 독립적으로 동작하므로 한블록에서 에러가 난다고 해도 다른 블록에 영향을 주지 않는다. 해당 블록까지 에러 전파.


2. CBC(Cipher Block Chaining) Mode
- 블록 암호화 운영 모드 중 보안 성이 제일 높은 암호화 방법으로 가장 많이 사용된다.
- 평문의 각 블록은 XOR연산을 통해 이전 암호문과 연산되고 첫번째 암호문에 대해서는 IV(Initial Vector)가 암호문 대신 사용된다. 이 때, IV는 제 2의 키가 될수 있다.
- 암호문이 블록의 배수가 되기 때문에 복호화 후 평문을 얻기 위해서 Padding을 해야만 한다.
- 암호화가 병렬처리가 아닌 순차적으로 수행되어야 한다. (단점이죵~)


- error propagation : 깨진 암호문의 해당블록과 다음블록의 평문까지 영향을 미치게 됩니다. 두번째 복호화 그림을 보고 Ciphertext가 깨졌을 때를 생각해보시면 이해가 되실꺼에요~


3. CFB(Cipher FeedBack) Mode
- 블록 암호화를 스트림 암호화처럼 구성평문과 암호문의 길이가 같다(패딩이 필요 없다)
- 최초의 키생성 버퍼로 IV가 사용되며, 이때 IV는 제2의 키가 될수 있다.
- 스트림의 기본단위를 Bit단위로 설정할 수 있으며, Bit단위에 따라 CFB8~CFB128로 쓰인다.
- 암호화, 복호화 모두 암호화로만 처리할 수 있다.
- CBC모드와 마찬가지로 암호화는 순차적이고, 복호화는 병렬적으로 처리할 수 있다.


- error propagation : CBC모드와 마찬가지로 한 암호문블럭의 에러는 해당평문블록과 다음 평문블록, 이렇게 총 2개의 블록에 전파된다.


4. OFB(Output FeedBack) Mode
- 블록 암호화를 스트림 암호화처럼 구성해 평문과 암호문의 길이가 같다.(패딩이 필요없다)
- 암호화 함수는 키 생성에만 사용되며, 암호화 방법과 복호화 방법이 동일해 암호문을 한번 더 암호화하면 평문이 나온다. (복호화시에 암호화)
- 최초의 키생성 버퍼로 IV가 사용되며, 이 때 IV는 제2의 키가 될수 있다.
- 스트림의 기본 단위를 Bit단위로 설정할 수 있으며, Bit단위에 따라 OFB8~OFB128로 쓰인다.


- error propagation : 해당블록까지만~ 대응되는 한 블록에만 영향을 미치므로, 영상이나 음성과 같은 digitized analog신호에 많이 사용된다.


5. CTR (CounTeR) Mode
- 블록을 암호화할 때마다 1씩 증가해 가는 카운터를 암호화 해서 키스트림을 만든다. 즉 카운터를 암호화한 비트열과 평문블록과의 XOR를 취한 결과가 암호문 블록이 된다.
- CTR모드는 OFB와 같은 스트림 암호의 일종이다.
- CTR모드의 암복호화는 완전히 같은 구조가 되므로 구현이 간단하다.(OFB와 같은 스트림 암호의 특징)
- CTR모드에서는 블록의 순서를 임의로 암/복호화 할 수있다.(비표와 블록번호로부터 카운터를 구할 수 있기때문에)
- 블록을 임의의 순서로 처리 할 수 있다는 것은 처리를 병행 할 수 있다는 것을 의미한다.(병렬처리 가능)

- error propagation : 각 블록이 병렬처리 되므로 같은 블록내에서만 이루어짐.

표준 대칭키 알고리즘의 종류

알고리즘

특징

소유국가

DES

64bit block

56bit key

미국

Triple DES

64bit block

112~168bit key

미국

BlowFish

64bit block

128bit key

미국

RC2

64bit block

128bit key

미국

RC4

Stream Cipher

미국

AES

128bit block

128~256 bit key

벨기에

SEED

128bit block

128bit key

한국

ARIA

128bit block

128~256bit key

한국



*Stream Cipher : 키의 길이가 유동적이며, 키의 길이가 길수록 안전성이 뛰어남.




Posted by 개발자 용이~
2009/06/27 11:28
얼마전에 보안회사에 취직을 하게되었습니다; 앞으로 보안쪽으로 공부를 하면서 정리를 해보려 합니다.

인터넷이 해결해야할 문제


통신상대의 동일성 확인 : 통신상대는 이름 그대로 진정한 상대인가?
통신 메시지의 기밀성 보장 : 통신내용은 제 2자의 도청위험성이 없는가?
통신메시지의 무결성 확인 : 통신내용인 도중에 변조 또는 개조되지 않았는가?
송수신 부인 방지 : 중요한 정보에 대해 통신 당사자가 쌍방의 송수신 책임이 명확한가?

암호란 ?
어떤 내용(정보)을 남모르게 전달하려고 쓰는 신호나 부호.
- 인간 세계에서 정보의 보호와 탈취는 계속적으로 이루어 졌음.
- 정보의 양이 많아질수록 정보보호의 필요성이 절대적으로 증가됨.
- 이에 따른 정보보호 기술도 고도화 되고 있음.

해커 공격의 종류(크게 나누면~)
Passive Attack : 정보를 도청하여 듣거나 그 결과로 얻은 정보를 사용하려는 시도. 데이터에 영향을 끼치지 않음
Active Attack : 전송중인 데이터를 수정하거나 가짜 데이터를 만드는 행위.


대칭키 암호 시스템(Symmetric Cipher System)
- 암호화 할 때 사용하는 키와 복호화 할때 사용하는 키가 동일한 암호 시스템.
- 이때 사용하는 키를 비밀키(Secret Key)라고 함.
- 일반적인 메시지(또는 파일) 암호화에 주로 활용되며, 빠른 암호화 속도가 장점.


대칭키 암호화의 종류

- 블록 암호화(Block Cipher)
평문을 블록단위로 나누어서 암호화를 진행하는 방식.
예전에는 64Bit단위로 암호화를 진행했으나, 현재 컴퓨팅 능력으로 해독할 수 있어 지금은 128Bit 또는 256Bit로 암호화를 진행함.
만약 128Bit(16Byte) 블록암호화 알고리즘으로 암호화를 진행하면, 일반적으로 암호문의 길이는 블록의 배수가 됨.

- 스트림 암호화(Stream Cipher)
난수 발생기를 통해 생성된 키 스트림을 암호화 연산에 참여시켜 암호화 패턴에 변화를 주면서 1비트씩 암호화를 진행하는 방식.
주로 실시간 음성, 영상 통신 암호화에 많이 사용됨.

다음에 블록암호화에 대해 이어집니다.



Posted by 개발자 용이~
2009/06/14 22:51
오랜만에 글을 쓰게되는군요..
예전 I/O공부하던 것에 이어서 자바 I/O에 관련된 내용들을 계속해서 공부해 보겠습니다. 참고서적은 자바I/O & NIO 네트워크 프로그래밍(한빛미디어)입니다.

이 책에나오는 IO클래스를 사용할 때 반드시 지켜야 할 내용은
- try문에서 사용할 IO클래스를 선언한다. 보통 null값을 할당한다. (그러니까 IO클래스의 레퍼런스를 선언할 때 에러처리를 하는 try구문위에 선언을 한다는 말입니다.)
- try블록안에서 IO클래스 객체를 생성한다. (new 키워드는 try블록에서!!)
- finally블록안에서 IO클래스의 close()메소드를 호출한다. 

파일의 내용을 읽어오는 예제입니다. Stream형식(바이트 단위)으로 읽어오기

package ch04;


import java.io.*;


public class FileView2 {

  public static void main(String[] args) {

    if (args.length != 1) {

      System.out.println("사용법 : java FileView2 파일명");

      System.exit(0);

    }

    

    FileInputStream fis = null;

    try {


      fis = new FileInputStream(args[0]);


      int readcount = 0;

      byte[] buffer = new byte[512];

      while ( (readcount = fis.read(buffer)) != -1 ) {

        System.out.write(buffer, 0, readcount);

      }

      

    } catch (Exception e) {

      e.printStackTrace();

    } finally {

      try {

        fis.close();

      } catch (IOException e) {

        e.printStackTrace();

      }

    }

  }

}


중간쯔음의 굵게 표시된부분을

int i = 0;

while ((i = fis.read()) != -1) {

  System.out.write(i);

}

이렇게 바꾸어도 되지만... 자바프로그래밍으로 1바이트를 읽어오라고 실행하면, 운영체제는 실제로 1바이트를 읽어오지않고 256바이트나 512바이트를 읽어온다고 합니다. 굵게표시된부분말고 밑에처럼 프로그래밍하게되면 1000바이트 파일이라고 할 때, 내부적으로는 512바이트씩 1000번을 읽어온다네요. 이게 파일의 크기가 작으면 상관이 없지만 커질경우에는 문제가 있겠죠. 그러므로 운영체제가 읽어올수있는 크기로 버퍼의 크기를 정해주면 빠르게~ 낭비도 없이 짜여진 프로그램이 되겠죠^^


다음은 파일복사의 예제입니다. Stream형식(바이트 단위)

package ch04;


import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;


public class FileStreamCopy {

  public static void main(String[] args) {

    if (args.length != 2) {

      System.out.println("사용법 : java FileStreamCopy 파일1 파일2");

      System.exit(0);

    }

    

    FileInputStream fis = null;

    FileOutputStream fos = null;

    

    try {

      fis = new FileInputStream(args[0]);

      fos = new FileOutputStream(args[1]);

      byte[] buffer = new byte[512];

      int readCount = 0;

      while ( (readCount = fis.read(buffer)) != -1 ) {

        fos.write(buffer, 0, readCount);

      }

      System.out.println("복시가 완료되었습니다.");

      

    } catch (Exception e) {

      e.printStackTrace();

    } finally {


      try {

        fis.close();

      } catch (IOException e) {

        e.printStackTrace();

      }

      try {

        fos.close();

      } catch (IOException e) {

        e.printStackTrace();

      }

      

    }

  }

}

Posted by 개발자 용이~
2009/06/14 22:26
다음에 나오는 글은 자바I/O & NIO 네트워크 프로그래밍(한빛미디어)에 나오는 내용입니다.
저도 잘 모르고 쓰고 있었군요...

다음 소스의 실행 결과를 맞춰봅시다.

package ch03;


public class InheritanceTest {

  public static void main(String[] args) {

    

    FirstChild fc = new FirstChild();

    System.out.println(fc.read());

    

    SecondChild sc = new SecondChild();

    System.out.println(sc.read());


    ThirdChild tc1 = new ThirdChild(fc);

    System.out.println(tc1.read());


    ThirdChild tc2 = new ThirdChild(sc);

    System.out.println(tc2.read());

  }

}



class Parent {

  public String read() {

    return "Parent 입니다.";

  }

}


class FirstChild extends Parent {

  @Override

  public String read() {

    return super.read() + ": FirstChild";

  }

}


class SecondChild extends Parent {

  @Override

  public String read() {

    return super.read() + ": SecondChild";

  }

}


class ThirdChild extends Parent {

  Parent p;

  

  public ThirdChild(Parent p) {

    this.p = p;

  }

  

  @Override

  public String read() {

    return p.read() + ": ThirdChild";

  }

  

}


결과는!!

더보기



다음문제입니다.

package ch03;


class Parent2 {

  int i = 7;

  public int get() {

    return i;

  }

}


class Child2 extends Parent2 {

  int i = 5;

  @Override

  public int get() {

    return i;

  }

}


public class ChildTest {

  public static void print(Parent2 p) {

    System.out.println(p.i);

    System.out.println(p.get());

  }

  

  public static void main(String[] args) {

    Parent2 p = new Parent2();

    System.out.println("----- 1 -----");

    System.out.println(p.i);

    System.out.println(p.get());

    

    Child2 c = new Child2();

    System.out.println("----- 2 -----");

    System.out.println(c.i);

    System.out.println(c.get());

    

    

    Parent2 p2 = new Child2();

    System.out.println("----- 3 -----");

    System.out.println(p2.i);

    System.out.println(p2.get());

    

    System.out.println("----- 4 -----");

    print(c);

    print(p2);

  }

}


결과는

더보기


다 맞추셨나요??
이 문제들은 상속과 오버라이에 관한 문제입니다.

여기서 오버라이드란(override) 직역을 한다면 "올라타다"라는 뜻이라고 하네요.
----- 3 -----, ----- 4 ----- 부분이 중요한부분이죠.

여기서 살펴보변 Child2객체가 메모리에 올라가게 되면, Child2에 있는 필드i와 Parent2에 있는 i가 모두 메모리에 올라가게됩니다. 이 경우에 객체를 가리키는 참조변수가 Parent2라면 필드는 Parent2의 것을 사용하게 됩니다. 
하지만 메소드가 오버라이딩 되는 경우, 부모의 메소드는 사라지고 자식에서 선언된 메소드가 사용된다고 합니다.

여기서 정리1
- 부모는 자식을 가리킬 수 있다. 조상은 자손을 가리킬수 없다.
- 만약, 자식이나 자손이 메소드를 오버라이딩 하고 있으면, 메소드의 기능은 자식이나 자손이 구현한 것을 따른다.

다음으로 public static void print(Parent2 p) 메소드의 정의를 살펴봅시다.
이것을 초보들은 "메소드 print는 인자로 Parent2를 받아들인다." 라고 해석한다고 하네요; 이 말은 반은 맞고 반은틀린데 
"메소드 print는 인자로 Parent2와 Parent2의 자손을 받아들인다." 라고 해석되어야 맞는 말이랍니다. 

Posted by 개발자 용이~