[JAVA]package와 import

2012. 4. 29. 22:35NOTE/IT

java-package와 import 


원문
http://blog.naver.com/gml81/40022184076 



package와 import 
package의 사전적 의미는 "다발", "꾸러미", "묶음"의 뜻이다. 
자바에서 패키지의 의미는 "클래스 꾸러미", "클래스 묶음" 이라는 뜻이다. 
말 그대로 클래스들을 묶어 놓았다. 
자바에서 지원하는 클래스는 그 수가 상당히 많아서 기능별로 클래스들을 구분하여 묶어 놓았는데 그것이 바로 패키지이다. 
패키지의 개념은 디렉토리(directory)의 개념과 비슷하다. 
SRC문서가 있는 디렉토리를 열어보자. 
여러 디렉토리가 보일 것이다. 그 중에서 java 디렉토리를 열어보자. 
java 디렉토리 안에 있는 lang 디렉토리를 열어보자. 두 개의 디렉토리와 수많은 파일들이 보일 것이다. 
이 파일들은 확장자가 "*.java"인데, 자바에서 지원하는 클래스들의 소스파일이다. 
독자가 이미 알고 있는 자바 클래스는 String클래스와 System클래스인데, 이 두 클래스의 소스파일이 이 디렉토리에 존재한다. 
이들 파일은 자바 소스 파일이므로 메모장이나 다른 텍스트 에디터로 불러올 수 있다. 
"System.java" 파일의 경로는 SRC문서 디렉토리로부터 "javalangSystem.java"이다. 
이를 패키지 표기로 바꾸면 "java.lang.System"이 된다. ""대신에 "."을 사용하는 것으로 이를 도메인(Domain)식 표기라고 한다. 
여기서 java와 lang이 패키지이다. 
나중에 배울 애플릿(Applet) 클래스의 주소는 아래와 같다. 
지금 SRC문서 디렉토리를 열어 확인하기 바란다. 

java.applet.Applet 

아래의 예제는 사용자가 패키지를 만들고 만들어진 패키지 안에 클래스를 생성하는 예제이다. 

Class16.java 

package Mypack.pack1; // x1 

public class Class16{ 
public void hi(){ // x2 
System.out.println("하이여~~~~"); 



x1행에서 보자. 
package Mypack.pack1; 

위와 같이 하고 컴파일 하면 Mypack 디렉토리가 만들어지고 그 안에 pack1 디렉토리가 만들어진다. 컴 
파일 할 때는 -d옵션을 사용해야한다. 
javac -d . Class16.java 

-d옵션은 package의 위치를 지정하는 것으로 -d에 도트(.)를 삽입하면 현재 디렉토리에 패키지를 만든다. 
현재 디렉토리란 소스파일(Class16.java)이 있는 위치를 말한다. 
컴파일이 완료되면 현재 디렉토리 안에 "Mypack.pack1.Class16"이 생겨있을 것이다. 
Class16 클래스는 main 메소드가 없으므로 혼자서 실행될 수 없는 클래스이다. 
그러나 다른 클래스에서 Class16 클래스의 객체를 만들어 사용할 수 있다. 
x2행에서 "void hi()"앞에 있는 public과 같은 것을 접근 지정자(Access Modifier)라고 하는데 public은 다른 패키지에 있는 
클래스에서 hi메소드를 사용할 수 있게 하는 것이다. 접근 지정자는 조금 후에 자세히 알아보자. 
다른 패키지에 있는 클래스를 사용하기 위하여 import 키워드를 이용한다. import의 사전적 의미는 "수입하다"이다. 
import Mypack.pack1.Class16; 

위의 코드는 Mypack 안의 pack1 안에 있는 Class16 클래스를 수입하라는 명령이다. 
다른 패키지에 있는 클래스를 사용하려면 위와 같은 방법으로 해당 클래스를 import해와야 한다. 
아래 예제는 다른 패키지에 있는 클래스를 import하여 사용하는 방법을 보여준다. 
Class17.java 

import Mypack.pack1.Class16; // Class16 클래스를 import한다. 

public class Class17{ 
public static void main(String[] args){ 
Class16 ob=new Class16(); 
ob.hi(); 



출력 결과 

하이여~~~~ 

패키지를 만드는 이유는 자기만의 Library를 만들어 클래스들을 효율적으로 관리하기 위해서이다. 
또는 대형 프로젝트를 작성할 때 클래스가 아주 많이 생기므로 클래스들을 묶어서 효율적으로 관리할 수 있다. 
초보자는 많아야 대여섯 개 정도의 클래스를 만들 것이고, 대부분은 한 두 개의 클래스로 연습하기 때문에 패키지의 필요성을 못 느낀다. 
따라서 어느 정도의 실력이 쌓이면 그 때 패키지 작성 방법을 공부해도 괜찮을 듯 싶다. 

Date 클래스는 "java.util" 패키지에 있는 날짜와 관련된 클래스이다. 이 클래스를 사용하려면 "java.util.Date"를 import한다. 
Class18.java 

import java.util.Date; 

public class Class18{ 
public static void main(String[] args){ 
Date d=new Date(); 
System.out.println(d); 



출력 결과 

Thu Feb 21 13:42:26 JST 2002 

String 클래스와 System 클래스는 "java.lang" 패키지에 있는 클래스이다. 
자바는 기본적으로 "java.lang"에 있는 모든 클래스를 import한다. 
import java.lang.*; 

"*"는 모든 클래스를 의미한다. 우리가 "java.lang.*"을 import하지 않더라도 자동적으로 "java.lang.*"을 import하기 때문에 
System클래스나 String클래스를 사용할 수 있는 것이다. 
lang은 language의 약자로 자바 언어를 하기 위한 기본적인 클래스들이 있는 패키지이다. 
Class18.java 

import java.util.Date; 
import java.lang.*; // 이 행은 삭제해도 된다. 자동으로 import한다. 

public class Class18{ 
public static void main(String[] args){ 
Date d=new Date(); 
System.out.println(d); 



자바에서 제공하는 클래스는 그 양이 상당하므로 클래스를 모두 설명하고자 한다면 책으로 수십 권내지 수백 권될 것이다. 
따라서 이 책에 없는 클래스나 메소드를 공부하려면 SRC문서나 API문서를 잘 활용해야 한다. 
아쉬운 것은 이 문서들이 영어로 되어있다는 것이다. 
자바도 공부하고 영어도 공부할 수 있는 절호의 기회라고 생각하고 열심히 번역하길 바란다. 
일거양득(一擧兩得)이라면 좀 위안이 될라나?. 
인터넷에 한글로 번역된 API문서가 유통되고 있으므로 영어가 딸린다면 한글 API문서를 보는 것도 좋다. 

접근 지정자(Access Modifier) 
접근 지정자의 종류는 아래와 같다. 

멤버 변수나 멤버 메소드 앞에 올 수 있는 접근 지정자 
private 
public 
default(friendly) 
protected 

클래스 앞에 올 수 있는 접근 지정자 
public 
default(friendly) 

그렇다면 이런 접근 지정자의 역할은 무엇일까? 
private 접근을 가진 멤버는 클래스 내부에서만 사용(접근)될 수 있다. 즉 다른 클래스에서는 이 멤버를 사용할 수 없다. 
말 그대로 사적(私的)인 용도로 사용한다. 

Class19.java 

class Class19_A{ 
private int num; 
private void hi(){ 
System.out.println("안녕~~~"); 


public class Class19{ 
public static void main(String[] args){ 
Class19_A ob=new Class19_A(); 
ob.num=10; // x1 
ob.hi(); // x2 



출력 결과 

C:...Class19.java:11: num has private access in Class19_A 
ob.num=10; 

C:...Class19.java:12: hi() has private access in Class19_A 
ob.hi(); 

2 errors 

위 에러는 "num과 hi()는 Class19_A에서 private 접근을 가지고 있어서 다른 클래스에서는 접근할 수 없다"는 내용이다. 
x1행과 x2행을 보면 num과 hi()를 Class19에서 사용하고 있으므로 에러이다. num과 hi()는 
private이므로 Class19_A 클래스의 내부에서만 사용 가능하다. 
일반적으로 멤버 변수는 private 접근을 가지게 하여 다른 클래스(객체)에서 
멤버 변수에 직접적으로 접근하는 것을 막는다. 이것을 은닉화, 또는 캡슐화(Encapsulation)라고 한다. 
객체는 자신의 데이터와 내부에서 일어나는 일은 외부로부터 숨기고, 
단지 외부에는 객체 내부와 통신할 수 있는 인터페이스들을 제공한다. 
따라서 외부에서는 객체의 인터페이스만을 통해 그 객체를 사용할 수 있게 하는 것이다. 
예를 들면, 자동차와 자동차를 운전하는 기사가 있다. 
가고 있는 자동차를 세우려면 기사는 어떤 행동을 해야할까? 자동차의 브레이크를 밟을 것이다. 
그 다음은 자동차 내부에서 척척 알아서 처리한다(자동차를 세운다). 
기사는 자동차 내부에서 어떤 일이 일어나고 있는 지 알 필요가 없고, 
브레이크만 밟으면 된다. 자동차 객체는 내부에서 일어나는 일은 숨기고, 
단지 외부에 여러 가지 인터페이스를 제공한다. 따라서 사용자는 그 인터페이스를 통해서 자동차 객체를 사용할 수 있다. 
자동차의 동작 원리를 모르는 많은 사람들이 자동차를 자유자재로 운전할 수 있는 이유는 자동차를 완벽하게 캡슐화 했기 
때문이라고 말할 수 있을 것이다. 믿거나 말거나..., 
캡슐화 되지 않은 프로그램은 객체 지향 프로그램이라고 말할 수 없다. 
아래 예제는 객체의 데이터를 숨기고, 외부에 인터페이스를 제공하는 예이다. 

Class20.java 

class Class20_A{ 
private int num; 
void setNum(int a){ // x1, 인터페이스 
num=a; // 클래스(객체) 내부에서만 사용 가능하다 

int getNum(){ // x2, 인터페이스 
return num; 


public class Class20{ 
public static void main(String[] args){ 
Class20_A ob=new Class20_A(); 
ob.setNum(10);// num의 값을 바꾸지만 num은 보이지 않는다. 
System.out.println(ob.getNum()); 



출력 결과 

10 

위 예제를 해보면 의문점이 생길 것이다. x1행과 x2행의 setNum()과 getNum()의 접근 지정자가 생략되어있다. 
접근 지정자가 생략된 멤버를 default 또는 friendly 멤버라고 한다. 
default 멤버는 같은 패키지 안의 클래스에서 접근할 수 있다. 
같은 말로 다른 패키지의 클래스는 default 멤버에 접근할 수 없다. 
Class20_A와 Class20은 같은 패키지(디렉토리)에 있는 클래스이므로 Class20_A의 default 멤버를 Class20에서 사용할 수 있다. 
Class20_A와 Class20이 같은 패키지에 있다는 것을 어떻게 알 수 있을까? 
탐색기를 열어서 확인해보면 Class20_A.class와 Class20.class이 같은 디렉토리에 있음을 확인할 수 있을 것이다. 
즉 같은 패키지이다. 

public 멤버는 모든 클래스가 접근할 수 있다. 말 그대로 공적(公的)인 멤버이다. 
Class21.java 

class Class21_A{ 
public int num; // public 멤버 변수 
public void hi(){ // public 멤버 함수 
System.out.println("안녕~~"); 



public class Class21{ 
public static void main(String[] args){ 
Class21_A ob=new Class21_A(); 
ob.num=10; // 모든 클래스가 num에 접근할 수 있다. 
ob.hi(); // 모든 클래스가 hi에 접근할 수 있다. 
System.out.println(ob.num); 



출력 결과 

안녕~~ 
10 

protected 멤버는 같은 패키지에 있는 클래스에서 접근 가능할 뿐만 아니라 다른 패키지에 있는 자식(child) 클래스에서도 접근 가능하다. 
상속(Inheritance)을 알아야 이해되므로 나중에 상속 부분에서 살펴보자. 
여기까지 배운 접근 지정자를 요약하면 아래와 같다. 

private: 클래스 내부에서만 사용할 수 있다. 
public: 모든 클래스가 접근할 수 있다. 
default(friendly): 같은 패키지 안의 클래스가 접근할 수 있다. 
protected: 같은 패키지 안의 클래스가 접근할 수 있고, 
다른 패키지에 있는 자식 클래스도 접근할 수 있다. 

클래스 앞에 올 수 있는 접근 지정자는 public과 default인데 public은 모든 클래스가 
해당 클래스를 사용할 수 있고 default는 같은 패키지 안의 클래스에서 해당 클래스를 사용할 수 있다. 

오버로드(Overload) 
오버로드란 같은 이름을 가지는 멤버 메소드를 정의하는 것을 말한다. 
void hi(){ 
System.out.println("안녕~~"); 


void hi(String name){ 
System.out.println(name+"씨 안녕~~"); 


void hi(String name1, String name2){ 
System.out.println(name1+"씨, "+name2+"씨 안녕~~"); 



위 세 메소드는 이름이 모두 hi이다. 그러나 매개 변수의 개수가 다르거나 자료형이 다르다. 
이것을 메소드 오버로드라고 한다. 리턴형은 같아도 되고 달라도 된다. 호출할 때는 아래와 같이 한다. 
ob.hi(); // 첫 번째 hi호출 
ob.hi("철수"); // 두 번째 hi호출 
ob.hi("철수","영희"); // 세 번째 hi호출 

Class22.java 

public class Class22{ 
void hi(){ 
System.out.println("안녕~~"); 

void hi(String name){ 
System.out.println(name+"씨 안녕~~"); 

void hi(String name1, String name2){ 
System.out.println(name1+"씨, "+name2+"씨 안녕~~"); 

public static void main(String[] args){ 
Class22 ob=new Class22(); 
ob.hi(); 
ob.hi("철수"); 
ob.hi("철수","영희"); 



출력 결과 

안녕~~ 
철수씨 안녕~~ 
철수씨, 영희씨 안녕~~ 

다음 예제를 검토하자. 
Class23.java 

public class Class23{ 
void hi(){ 
System.out.println("안녕~~"); 

int hi(){ 
System.out.println("씨 안녕~~"); 
return 1; 

public static void main(String[] args){ 
Class23 ob=new Class23(); 
ob.hi(); 



출력 결과 

C:...Class23.java:5: hi() is already defined in Class23 
int hi(){ 

1 error 

오버로드할 때는 반드시 매개 변수의 개수가 다르거나 매개변수의 자료형이 달라야 한다. 
Class24.java 

public class Class24{ 
static boolean isSame(int a, int b){ 
return a==b; 

static boolean isSame(double a, double b){ 
return a==b; 

public static void main(String[] args){ 
System.out.println(isSame(1, 2)); // 첫 번째 
System.out.println(isSame(1.2, 1.2)); // 두 번째 



출력 결과 

false 
true 

짚어두기 

Static 
Static 변수나 메소드는 객체 없이도 호출될 수 있다. 


생성자(Constructor) 
멤버 변수를 초기화하지 않으면 기본 자료형은 0을, 레퍼런스는 null을 기억하게 된다고 앞에서 배웠다. 
Class25.java 

public class Class25{ 
int a; 
String b; 
public static void main(String[] args){ 
Class25 ob1=new Class25(); 
Class25 ob2=new Class25(); 
Class25 ob3=new Class25(); 
System.out.println(ob1.a+" "+ob1.b); 
System.out.println(ob2.a+" "+ob2.b); 
System.out.println(ob3.a+" "+ob3.b); 



출력 결과 
0 null 
0 null 
0 null 

ob1과 ob2, 그리고 ob3은 모두 같은 값을 가지고 생성된다. 그러나 ob1, ob2 그리고 ob3는 엄연히 서로 다른 객체가 분명하다. 
그런데 같은 값을 가지고 있으므로 쌍둥이라고 불러야할 것이다. 
여자가 아기를 낳을 때마다 같은 모습을 가진 아기를 낳을 수 없듯이 객체도 서로 다르게 태어나도록 해야함이 옳다. 
객체 지향 프로그래밍은 실세계를 반영하는 프로그래밍이다. 아기를 낳기 위해서는 난자와 정자가 만나서 수정하고, 
여자가 힘을 주는 등의 일련의 동작이 필요하다. 즉 객체를 생성하려면 동작이 필요하다. 이 필요한 동작을 생성자라고 한다. 

Class25의 객체를 만드는 방법은 아래와 같다. 
Class25 ob1=new Class25(); 

여기서 Class25()는 메소드를 호출하는 것처럼 보인다. 사실은 이것이 바로 생성자이다. 
생성자는 객체를 만드는 순간에 호출되어 실행되는 특수한 메소드이다. 
생성자를 만들어 주지도 않았는데 어떻게 생성자가 호출된다는 것일까? 
사용자가 생성자를 만들지 않으면 컴파일러가 알아서 생성자를 만들어 주기 때문이다. 
컴파일러가 만들어 주는 생성자는 어떤 모습일까? 다음은 컴파일러가 만들어 주는 Class25의 생성자이다. 
Class25(){} 

생성자의 이름은 클래스의 이름과 동일하고 리턴형이 없다. 위와 같이 컴파일러가 만들어 주는 생성자를 default 생성자라고 한다. 
디폴트 생성자는 매개변수가 없고 몸체가 비어있다. 즉 아무 것도 실행하지 않는 생성자이다. 
하는 일이 있다면 객체를 만들어 주는 것이다. 

이제 직접 생성자를 만들어보자. 
Class26.java 

public class Class26{ 
int a; 
public Class26(){ //x1 
a=10; 

public static void main(String[] args){ 
Class26 ob=new Class26(); // x2 
System.out.println(ob.a); 



출력 결과 

10 

x1행에 있는 메소드가 생성자이다. x2행에서 ob객체가 만들어 질 때 x1행의 생성자가 실행된다. 따라서 "ob.a=10"된다. 
일반적으로 생성자는 다른 클래스에서 호출되므로 접근 지정자를 보통 public으로 지정한다. 
그러나 목적에 따라 다른 접근 지정자가 사용되기도 한다. 생성자는 리턴형이 없고 클래스의 이름과 동일하다는 것을 확인하자. 

위 예제에서 객체가 생성되면 멤버 변수 a에 10이 대입된다. 다른 객체를 만들더라도 a에 10이 대입될 것이다. 
한마디로 쌍둥이이다. 생성자를 오버로드해서 이 문제를 해결할 수 있다. 
Class27.java 

public class Class27{ 
int a; 
public Class27(){ // x1 
a=10; 

public Class27(int a){ // x2 
this.a=a; 

public static void main(String[] args){ 
Class27 ob1=new Class27(); // x3 
Class27 ob2=new Class27(20); // x4 
Class27 ob3=new Class27(30); // x5 
System.out.println(ob1.a); 
System.out.println(ob2.a); 
System.out.println(ob3.a); 



출력 결과 

10 
20 
30 

x3행은 x1행의 생성자를 호출하고, x4행과 x5행은 x2행의 생성자를 호출한다. 

아래 예제를 유심히 보자. 
Class28.java 

public class Class28{ 
int a; 
public voidClass28(){ // x1, 생성자?????? 
a=10; 

public static void main(String[] args){ 
Class28 ob=new Class28(); 
System.out.println(ob.a); 



출력 결과 



x1행의 void Class28()은 생성자가 아니라 멤버 메소드이다. 왜냐하면 생성자는 리턴형이 없기 때문이다. 
따라서 ob.a=0이 된다. Class28에는 디폴트 생성자만 존재한다. 왜냐하면 사용자가 생성자를 만들어주지 않았기 때문이다. 

아래 예제도 유심히 보자. 
Class29.java 

public class Class29{ 
int a; 
public Class29(int a){ 
this.a=a; 

public static void main(String[] args){ 
Class29 ob=new Class29(); // x1 
System.out.println(ob.a); 



출력 결과 

C:...Class29.java:7: cannot resolve symbol 
symbol : constructor Class29 () 
location: class Class29 
Class29 ob=new Class29(); 

1 error 

x1행에서 매개 변수가 없는 생성자를 호출하고 있다. 디폴트 생성자가 존재하면 문제가 없지만 
이미 생성자를 만들었으므로 컴파일러는 디폴트 생성자를 만들어 주지 않는다. 
따라서 매개 변수가 없는 생성자가 없으므로 에러가 뜬다. 

this(...) 
생성자에서 오버라이드된 다른 생성자를 호출할 수도 있다. 다른 생성자를 호출하고자 할 때는 this(...)를 사용한다. 
this(), this(a), this(a,b), ... ; -> 생성자 호출 

Class30.java 

public class Class30{ 
public Class30(){ // x1 
System.out.println("안녕~~"); // x2 

public Class30(String s){ // x3 
this(); // x4, Class30()호출, x1행으로 이동 
System.out.println(s); // x5 

public Class30(int a){ // x6 
this("반가워~~"); // x7, Class30(String s) 호출, x2행으로 이동 
System.out.println(a); // x8 

public static void main(String[] args){ 
Class30 ob=new Class30(20); // x9 
} // x10 


출력 결과 

안녕~~ 
반가워~~ 
20 

실행 순서는 다음과 같다. 
x9 → x6 -> x7 -> x3 → x4 → x1 → x2 → x5 → x8 → x10 

메소드의 실행이 끝나면 그 메소드를 호출한 부분으로 돌아간다는 것을 상기하면 실행 순서가 이해될 것이다. 
알아두기 

this(...) 호출의 제한 
◈ 생성자의 실행은 다른 처리보다 우선적이므로 this(...)는 블록({})안에서 맨 위에 있어야한다. 

public Class30(String s){ 
System.out.println(s); 
this(...); // 에러, 생성자의 실행은 다른 처리보다 우선적이다. 


◈ 일반 메소드는 객체를 생성한 후에 사용하는 메소드이므로 this(...)를 일반 메소드에서 호출할 수 없다. 
생성자는 객체를 생성하기 위해서만 사용되기 때문이다. 

void method(){ 
this(...); // 에러 

[출처] java-package와 import |작성자 영희 

'NOTE > IT' 카테고리의 다른 글

[JAVA]JDBC를 이용한 DB연동 확인  (0) 2012.04.29
[ORACLE] 함수 정리  (0) 2012.04.29
[ORACLE]오라클 Alter table  (0) 2012.04.29
[포토샾] 간락 팁  (0) 2012.04.29
[ASP]파일 다루기  (0) 2012.04.25