- 클래스를 사용할 때 패키지이름을 생략할 수 있다.
- 컴파일러에게 클래스가 속한 패키지를 알려준다.
- java.lang패키지의 클래스는 핵심패키지여서 import하지 않고도 사용할 수 있다.
String, Object, System, Tread ...- import문은 패키지문과 클래스선언 사이에 선언한다.
class ImportTest {
java.util.Date today = new java.util.Date();
}
---- 위처럼 전부 써야하지만 import를 쓰면 -------
import java.util.Date;
class ImportTest {
Date today = new Date();
}
혹시나 코드를 작성할때 패키지가 어디에 있는지 찾을 수 없어 오류가 뜰때 이클립스에서
ctrl + shift + o
를 누르면 찾아준다.
- static멤버를 사용할 때 클래스 이름을 생략할 수 있게 해준다.
import static java.lang.Integer.*; // Integer클래스의 모든 static메서드 import static java.lang.Math.random; // Math.random()만. 괄호 안붙임. import static java.lang.System.out; // System.out을 out만으로 참조가능 System.out.println(Math.random()); ---> out.println(random());
클래스와 클래스의 멤버(멤버 변수, 메서드)에 부가적인 의미 부여
접근 제어자 - public, protected, (default), private
그 외 - static, final, abstract, native, transient, synchronized, volatile, strictfp하나의 대상에 여러 제어자를 같이 사용가능(접근 제어자는 하나만)
public class ModifierTest { public static final int WIDTH = 200; public static void main(String[] args) { System.out.println("WIDTH=" + WIDTH); } }
class StaticTest {
------- 간단 초기화 ---------
static int width = 200; // 클래스 변수(static 변수)
static int height = 120; // 클래스 변수(static 변수)
------ 복잡한 초기화 ---------
static { // 클래스 초기화 블럭
// static변수의 복잡한 초기화
}
static int max(int a, int b) { // 클래스 메서드(static 메서드)
return a > b ? a : b;
}
}
------ 조상이 될 수 없는 클래스 -----
final class FinalTest {
-------- 상수(멤버변수) -----------
final int MAX_SIZE = 10;
----- 오버라이딩할 수 없는 메서드 -----
final void getMaxSize() {
-------- 상수(지역변수) ------------
final int LV = MAX_SIZE;
return MAX_SIZE;
}
}
--------- 미완성 설계도 ----------
abstract class AbstractTest { // 추상 클래스(추상 메서드를 포함한 클래스)
abstract void move(); // 추상 메서드(구현부가 없는 메서드)
미완성 메서드
}
--------- 제품 생성불가 ----------
AbstractTest a = new AbstractTest(); // 에러. 추상 클래스의 인스턴스 생성불가
private
- 같은 클래스 접근 가능
(default)
- 같은 패키지 접근 가능
protected
- 같은 패키지 + 다른 패키지의 자손 접근 가능
public
- 제한x
class MyParent {
private int prv; // 같은 클래스
int dft; // 같은 패키지
protected int prt; // 같은 패키지 + 자손(다른 패키지)
public int pub; // 접근제한 없음.
public void printMembers() {
System.out.println(prv); // OK
System.out.println(dft); // OK
System.out.println(prt); // OK
System.out.println(pub); // OK
}
}
public class MyParentTest {
public static void main(String[] args) {
MyParent p = new MyParent();
System.out.println(p.prv); // 에러.
System.out.println(p.dft); // OK
System.out.println(p.prt); // OK
System.out.println(p.pub); // OK
}
}
접근 제어자를 사용하는 이유
- 외부로부터 데이터를 보호하기 위해서
- 외부에는 불필요한, 내부적으로만 사용되는 부분을 감추기 위해서
public class Time {
----------- 캡슐화 -----------
private int hour;
private int minute;
private int second;
-------- 메서드는 public ------
public int getHour() {return hour;}
public void setHour(int hour) {
if (hour < 0 || hour > 23) return;
this.hour = hour;
}
}
- 여러가지 형태를 가질 수 있는 능력
- 조상 타입 참조 변수로 자손 타입 객체를 다루는 것
Tv t = new SmartTv(); // 타입 불일치
class Tv{
boolean power;
int channel;
void power() {power = !power;}
void channelUp() {++channel;}
void channelDown() {--channel;}
}
class SmartTv extends Tv {
String text;
void caption() {}
}
SmartTv s = new SmartTv(); // 참조 변수와 인스턴스의 타입이 일치
Tv t = new SmartTv(); // 조상 타입 참조변수로 자손 타입 인스턴스 참조
실제 멤버가 7개라고 해도 5개밖에 사용하지 못한다.
자손 타입의 참조변수로 조상 타입의 객체를 가리킬 수 없다.
Tv t = new SmartTv(); // 허용 SmartTv s = new Tv(); // 에러
자손의 멤버 개수가 부모보다 많기 때문에 부모기준으로 할당이 되었을 때, 자손에서 가리키려는 멤버가 없기 때문에 에러가 나온다.
- 사용할 수 있는 멤버의 갯수를 조절하는 것
- 조상 자손 관계의 참조변수는 서로 형변환 가능
class Car {
String color;
int door;
void drive() { // 운전하는 기능
System.out.println("drive, Brrr~");
}
void stop() { // 멈추는 기능
System.out.println("stop!!");
}
}
class FireEngine extends Car { // 소방차
void water() { // 물을 뿌리는 기능
System.out.println("water!!!");
}
}
public class Drive {
public static void main(String[] args) {
FireEngine f = new FireEngine();
Car c = (Car)f; // Ok. 조상으로 형변환
FireEngine f2 = (FireEngine)c; // OK. 자손으로 형변환
Ambulance a = (Ambulance)f; // 에러. 상속관계가 아니면 형변환 불가
}
}
또, 형변환을 할때 변환 전에 있던 값들은 남아있다.
이렇게 했을때, f2.a에 값을 주고 형변환을 두번한 후에 다시 출력해보면 값이 남아있다. 또, 처음 할당이 자손으로 되었는지 조상으로 되었는지도 중요하다.
Car는 조상이다. 조상에는 멤버가 4개 자손은 5개있다. 여기서 처음 할당할때 4개의 멤버가 만들어지고 그 형변환을 자손이 받는다 이때 조상에 없는 자손의 메소드를 실행하면, 컴파일은 성공했다고 착각을 하지만 실제로 실행했을때, 오류가 나온다. 조상에 자손의 메소드가 없기 때문이다.
- 참조변수의 형변환 가능여부 확인에 사용. 가능하면 true 반환
- 형변환 전에 반드시 instanceof로 확인해야 함
void doWork(Car c) { if (c instanceof FireEngine) { // 1. 형변환이 가능한지 확인 FireEngine fe = (FireEngine)c; // 2. 형변환 fe.water(); ...
- 참조형 매개변수는 메서드 호출시,
자신과 같은 타입 또는 자손타입
의 인스턴스를 넘겨줄 수 있다.
class Product {
int price; // 제품가격
int bonusPoint; // 보너스점수
}
class Tv extends Product {}
class Computer extends Product {}
class Audio extends Product {}
class Buyer { // 물건사는 사람
int money = 1000; // 소유금액
int bonusPoint = 0; // 보너스점수
// void buy(Tv t)
// void buy(Computer t)
// void buy(Audio t)
void buy(Product p) {
money -= p.price;
bonusPoint += p.bonusPoint;
}
}
public class Buyman {
public static void main(String[] args) {
Buyer b = new Buyer();
Tv tv = new Tv();
Computer com = new Computer();
b.buy(tv);
b.buy(com);
}
}
- 조상타입의 배열에 자손들의 객체를 담을 수 있다.
Product p1 = new Tv(); Product p2 = new Computer(); Product p3 = new Audio(); ------------------------------ Product p[] = new Product[3]; p[0] = new Tv(); p[1] = new Computer(); p[2] = new Audio();
class Product {
int price; // 제품가격
int bonusPoint; // 보너스점수
}
class Tv extends Product {}
class Computer extends Product {}
class Audio extends Product {}
class Buyer { // 물건사는 사람
int money = 1000; // 소유금액
int bonusPoint = 0; // 보너스점수
Product[] cart = new Product[10]; // 구입한 물건을 담을 배열
int i = 0;
void buy(Product p) {
if(money < p.price) {
System.out.println("잔액부족");
return ;
}
money -= p.price;
bonusPoint += p.bonusPoint;
cart[i++] = p;
}
}
배열은 Vector클래스가 최고다. 배열의 단점중의 하나가 한번 크기를 정하면 바꿀수가 없다라는 것인데 벡터는 그 단점을 보안해줄 수 있다.