사진을 정리할 때 어떤 종류의 사진이냐에 따라 가족사진, 풍경사진 등 폴더별로 정리를 해놓으면 분류가 용이해진다. 사진을 정리해 놓은 나뿐만 아니라 어느 다른 사람이 원하는 사진을 찾고 싶을 때에도 찾기 수월하다. 패키지는 종류별로 나뉜 사진 폴더와 같다. 패키지는 비슷한 성격의 클래스들을 분류해 놓은 자바의 디렉토리이다. 자바 코드를 작성하다 보면 다른 사람의 자바 클래스나 라이브러리를 사용해야 하는 경우가 있는데 이 때 혹시 자바 클래스 명이 내가 만든 클래스명과 이름이 겹치거나 하더라도 패키지가 다르면 서로 충돌할 일이 없다.
package family;
class parents {}
class sibling {}
package friends;
class highSchool {}
class college {}
package foods;
class parents {}
// 부모님과 외식할 때 찍은 사진이라고 치자.
// family 패키지에서도 parents 클래스가 있지만 패키지가 달라 문제없다.
class koreanFood {}
패키지 내에 또 다른 패키지를 만들 수 있는데 이를 서브패키지라고 한다. 서브패키지 명은 패키지명.서브패키지명 으로 짓는다.
package family.fatherSide;
...
package family.matherSide;
...
접근제어자란 변수, 메소드, 클래스 등의 사용권한을 설정할 수 있는 기능이다. private -> default -> protected -> public 순으로 보다 많은 접근을 허용한다. 이와 같이 접근의 허용 범위를 지정하는 이유는 정보 은닉(Data Hiding)을 위해서이다. 프로그램을 사용할 사용자가 알 필요 없는 많은 정보를 숨겨 최소한의 정보만 가지고도 프로그램을 사용할 수 있도록 하게 하기 위함이다.
private 접근제어자는 메소드, 변수 등을 해당 클래스 내에서만 사용할 수 있게 하는 기능이다.
package family;
class parents {
private int fatherAge = 63;
}
class siblings {
// fatherAge 변수 사용 못함
}
default 접근제어자는 동일 패키지 내에서만 접근이 가능하다. 따로 접근제어자를 지정하지 않으면 자동적으로 자바가 default 접근제어자로 설정한다.
package friends;
class highSchool {
default String class1 = "Avengers";
}
class college {
String getGroupName { // default가 생략된 메소드
return "Five Guys";
}
}
default가 붙은 변수,메소드 모두 friends 패키지 내에서만 이용가능하다.
protected 접근제어자는 동일 패키지뿐만 아니라 접근제어자가 붙은 변수 혹은 메소드를 포함한 클래스를 임포트한 다른 패키지에서만 사용가능하다.
package family;
class parents {
protected String lastName = "Kang";
}
package family.fatherSide;
import family.parents;
public class KangFamily extends parents {
public static void main(String[] args) {
KangFamily kang = new KangFamily();
System.out.println(kang.lastName); // Kang 출력
}
}
lastName 변수의 접근제어자가 protected였기 때문에 다른 패키지에서도 parents 클래스를 임포트해서 lastName 변수를 사용할 수 있었다. default나 private이였다면 컴파일 에러가 났을 것이다.
public 접근제어자는 어디서든 사용할 수 있게 해주는 기능이다.
접근제어자를 모두 public으로 사용해도 프로그램은 잘 동작하겠지만 접근제어자를 잘 이용하면 코딩 실수를 방지할 수 있고, 기타 위험요소를 제거할 수 있다.
자바에서 객체는 각각 독립적으로 존재한다. 만약 프로그램 전역적으로 자주 재사용되는 변수나 메소드가 있다면 굳이 독립적으로 존재할 필요가 있을까? 이럴 때 쓰는 키워드가 staic이다.
class HouseLee {
String lastName = "Lee";
}
public class Sample {
public static void main(String[] args) {
HouseLee lee1 = new HouseLee();
HouseLee lee2 = new HouseLee();
}
}
static String lastName = "Lee";
final static String lastName = "Lee";
class Counter {
int count = 0;
Counter() {
this.count++;
System.out.println(this.count);
}
}
public class Sample {
public static void main(String[] args) {
Counter c1 = new Counter();
Counter c2 = new Counter();
}
}
1
1
class Counter{
static int count = 0;
...
1
2
class Counter {
static int count = 0;
String line = "테스트용 변수";
Counter() {
count++;
System.out.println(count);
}
public static int getCount() {
return count;
}
}
public class Sample {
public static void main(String[] args) {
Counter c1 = new Counter();
Counter c2 = new Counter();
System.out.println(Counter.getCount());
System.out.println(c1.getCount());
}
}
1
2
2
2
getCount라는 static method를 생성해서 count를 리턴하게끔 했다. static method 역시 값을 공유하기 때문에 2를 출력한다.
static 메소드의 또 다른 특징은 객체를 생성하지 않고도 클래스를 통해 메소드를 호출할 수가 있다.
static 메소드에서는 객체변수가 접근하지 못하는 특징도 가지고 있다. line 객체 변수를 static 메소드인 getCount에서 사용하려고 하면 컴파일 에러가 난다.
싱글톤 패턴이란 객체를 단 한개만 생성할 수 있게끔 강제하는 것이다. 싱글톤 패턴을 이용하면 클래스를 통해 단 하나의 객체만을 생성할 수 있다. 어떤 경우에 싱글톤을 이용하는지는 아직까지는 잘 모르겠다.
class SingleTon {
private SingleTon() {
}
}
public class Sample {
public static void main(String[] args) {
SingleTon singleton = new SingleTon();
}
}
class SingleTon {
private SingleTon() {
}
public static SingleTon getInstance() {
return new SingleTon();
}
}
public class Sample {
public static void main(String[] args) {
SingleTon singleton = SingleTon.getInstance();
}
}
class SingleTon {
private static one;
private SingleTon() {
}
public static SingleTon getInstance() {
if (one==null) {
one = new SingleTon();
}
return one;
}
}
public class Sample {
public static void main(String[] args) {
SingleTon singleton1 = SingleTon.getInstance();
SingleTon singleton2 = SingleTon.getInstance();
}
}