▶ ArrayList
: 자료 저장 구조, 모든 java 객체 저장 가능
: 모든 java 객체는 Object의 후손
: 별도의 상속 선언 없이도 자동으로 모든 객체의 최상위
: Object 후손을 저장할 수 있는 Heterogeneous collection
▶ instanceof
: Object Data type Casting을 할 경우, instanceof 연산으로 확인
: 수정 불가
▶ 변수
: 변경 불가능 변수 = 상수
: final type name = 대입값;
→ 선언할 때만 대입 연산 가능 / 선언과 대입 분리 X
→ 일반적으로 public static으로 사용
→ 상수 이름은 모두 대문자로 작성, 단어가 이어질 때는 '_' 사용 (ex. MAX_INT)
package ch05_2;
public class Ch05_2Ex01 {
public static final int TMP_INT_TEST = 777;
// error, final 변수는 선언 이후 값 변경 불가능
// TMP_INT_TEST = 888;
// error, final 변수는 선언과 동시에 값 입력
// public final int TMP_INT_TEST2;
// TMP_INT_TEST2 = 888;
public static void main(String[] args) {
System.out.println(Ch05_2Ex01.TMP_INT_TEST);
}
}
출력 결과
777
▶ 메소드
: 변경 불가능 메소드
: override 불가
package ch05_2;
class Ch05_2Parent1 {
public final void finalMethod() {
System.out.println("finalMethod()");
}
}
class Ch05_2Child1 extends Ch05_2Parent1 {
// error, final method는 override 불가
// public final void finalMethod() {
// System.out.println("child - finalMethod()");
// }
}
public class Ch05_2Ex02 {
public static void main(String[] args) {
Ch05_2Parent1 p = new Ch05_2Parent1();
p.finalMethod();
}
}
출력 결과
finalMethod()
▶ 클래스
: 변경 불가능 클래스
: 상속 불가
final class Ch05_2Parent2 { }
// error, final class는 상속 불가
//class Ch05_2Child2 extends Ch05_2Parent2 { }
: 즉시 메모리에 load 할 것을 JRE에 전달하는 명령어
: static으로 선언된 변수와 메소드는 new 없이 메모리(static area)에 load
: JRE가 class 파일을 읽는 시점에 최초 1번 생성하므로 static 선언된 변수, 메소드는 1개만 존재
: 변수 없이 클래스 이름을 통해 접근 (클래스.변수이름 으로 static area에 load)
→ 공유 데이터로 사용
: 단, main method는 예외
▶ static area (stack)
: static으로 선언된 변수, 메소드가 생성되는 메모리 공간
: 일반 객체가 instance가 되는 공간(heap area)과 다름
: 언제든지 실행 가능한 영역
package ch05_2;
public class Ch05_2Ex04 {
public int nonStaticInt = 777;
public static int staticInt = 888;
public static void main(String[] args) {
// System.out.println(nonStaticInt); // error, 메모리에 load X
System.out.println("staticInt : " + staticInt);
System.out.println("Ch05_2Ex04.staticInt : " + Ch05_2Ex04.staticInt);
}
}
출력 결과
staticInt : 888
Ch05_2Ex04.staticInt : 888
package ch05_2;
class Ch05_2StaticTest {
public int intVar;
public static int staticIntVar;
public Ch05_2StaticTest() {
intVar++;
staticIntVar++;
} // constructor
}
public class Ch05_2Ex05 {
public static void main(String[] args) {
Ch05_2StaticTest test1 = new Ch05_2StaticTest();
System.out.println("test1.intVar : " + test1.intVar);
System.out.println("test1.staticIntVar : " + test1.staticIntVar);
Ch05_2StaticTest test2 = new Ch05_2StaticTest();
System.out.println("test2.intVar : " + test2.intVar);
System.out.println("test2.staticIntVar : " + test2.staticIntVar);
// static 변수 : 공유 데이터로 사용
test2.staticIntVar = 210000;
System.out.println("test1.staticIntVar : " + test1.staticIntVar);
}
}
출력 결과
test1.intVar : 1
test1.staticIntVar : 1
test2.intVar : 1
test2.staticIntVar : 2
test1.staticIntVar : 210000
▶ static method
: class load 할 때, static area(stack)에 최소 1번 생성
: override 불가
→ final의 override는 문법적 오류
→ static의 override는 문법적 오류가 아님 / 부모의 static 메소드와 자식의 static 메소드가 독립적으로 존재
→ 부모 타입의 변수로 자식 타입의 객체 생성 시, 해당 변수로 호출되는 static 메소드는 부모의 메소드
package ch05_2;
class Ch05_2Parent3 {
public static void staticMethod() {
System.out.println("Ch05_2Parent3 : staticMethod()");
}
}
class Ch05_2Child3 extends Ch05_2Parent3 {
public static void staticMethod() {
System.out.println(" ▷Ch05_2Child3 : staticMethod()");
}
}
public class Ch05_2Ex06 {
public static void main(String[] args) {
Ch05_2Parent3 p1 = new Ch05_2Child3();
// override 불가
p1.staticMethod();
Ch05_2Parent3.staticMethod();
Ch05_2Child3 c1 = new Ch05_2Child3();
c1.staticMethod();
Ch05_2Child3.staticMethod();
}
}
출력 결과
Ch05_2Parent3 : staticMethod()
Ch05_2Parent3 : staticMethod()
▷Ch05_2Child3 : staticMethod()
▷Ch05_2Child3 : staticMethod()
▶ static initializer
: static은 class load 할 때, 최초의 1번만 실행
: class load 시, 최초 1번만 실행하고자 하는 부분이 있을 때 사용
◎ 주의 사항
: 서버 프로그램에서 static의 존재는 서버가 종료되기 전까지 존재
package ch05_2;
public class Ch05_2Ex07 {
public static int staticInt1;
public static int staticInt2;
static {
staticInt1 = 777;
System.out.println("Ch05_2Ex07의 class가 load 중");
}
public static void main(String[] args) {
System.out.println("staticInt1 : " + staticInt1);
System.out.println("staticInt2 : " + staticInt2);
}
}
출력 결과
Ch05_2Ex07의 class가 load 중
staticInt1 : 777
staticInt2 : 0
: 미완성
▶ abstract method (추상 메소드)
: 구현부의 {수행 코드} X
: 메소드를 ;으로 종결
▶ abstract class (추상 클래스)
: 하나 이상의 abstract(추상) 메소드를 가진 클래스
: new를 통한 객체 생성 불가
: Inheritance 적용 가능
→ 상속 받는 class에 추상 메소드 구현 강제
→ 상속 받는 class는 추상 메소드 반드시 구현
→ 추상 메소드 구현이 안됐을 경우, instance 생성 불가
: Polymorphism 적용 가능
→ Heterogeneous Collection, Polymorphic Arguments, Object Data Type Casting, instanceof 등 적용 가능
▶ 사용 목적
: abstract 메소드를 상속받는 쪽에 구체적인 구현을 강요하기 위해
: 반드시 override 해야 하는 메소드의 구현 누락 가능성 배제를 위해
package ch05_2;
abstract class AbstractA {
abstract void abstractMethod();
}
abstract class AbstractB extends AbstractA {
// abstract도 상속
}
class AbstractChild1 extends AbstractB {
String hello = "안녕하세요.";
void abstractMethod() {
System.out.println(hello);
}
}
class AbstractChild2 extends AbstractB {
String hello = "반갑습니다.";
void abstractMethod() {
System.out.println(hello);
}
}
// abstract도 Polymorphism 적용 가능
public class Ch05_2Ex10 {
// Heterogeneous Collection
static AbstractA [] arr = new AbstractA[2];
public static void main(String[] args) {
arr[0] = new AbstractChild1();
arr[1] = new AbstractChild2();
printAbstract(arr[0]);
printAbstract(arr[1]);
}
// Polymorphic Arguments 적용
public static void printAbstract(AbstractA abs) {
abs.abstractMethod();
// Object Data Type Casting & instanceof 가능
if (abs instanceof AbstractChild1) {
AbstractChild1 one = (AbstractChild1) abs;
} else if (abs instanceof AbstractChild2) {
AbstractChild2 two = (AbstractChild2) abs;
}
}
}
출력 결과
안녕하세요.
반갑습니다.
FlowLayout
: 컴포넌트를 좌에서 우, 위에서 아래로 물 흐르듯 배치
package ch09;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.TextField;
public class AWT7Flow {
Frame frm;
FlowLayout flow;
TextField tf1, tf2, tf3;
public AWT7Flow() {
frm = new Frame("창 제목 입력하는 곳");
flow = new FlowLayout();
tf1 = new TextField("TextField1에 처음 보여지는 값");
tf2 = new TextField("TextField2");
tf3 = new TextField("TextField3");
}
public void makeGUI() {
frm.setSize(200, 200);
frm.setBackground(Color.GRAY);
frm.setVisible(true);
frm.setLayout(flow);
frm.add(tf1); frm.add(tf2); frm.add(tf3);
}
public static void main(String[] args) {
AWT7Flow awt = new AWT7Flow();
awt.makeGUI();
}
}
출력 결과
▷ 첫 출력 화면
▷ 가로 확장시 출력 화면
NullLayout
: 기존 Layout을 없애고 자유롭게 배치
: Frame의 기본 Layout이 BorderLayout이므로, 이를 제거
: Frame 위의 모든 컴포넌트의 위치 및 크기 지정 필요
package ch09;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.TextField;
public class AWT8Null {
Frame frm;
TextField tf1, tf2, tf3;
public AWT8Null() {
frm = new Frame("창 제목 입력하는 곳");
tf1 = new TextField("TextField1에 처음 보여지는 값");
tf2 = new TextField("TextField2");
tf3 = new TextField("TextField3");
}
public void makeGUI() {
frm.setSize(500, 500);
frm.setBackground(Color.GRAY);
frm.setVisible(true);
frm.setLayout(null);
frm.add(tf1); frm.add(tf2); frm.add(tf3);
// 앞의 두 개가 시작 x, y 좌표, 뒤의 두 개가 좌우, 상하 크기
tf1.setBounds(10, 30, 475, 20);
tf2.setBounds(10, 55, 235, 20);
tf3.setBounds(250, 55, 235, 20);
}
public static void main(String[] args) {
AWT8Null awt = new AWT8Null();
awt.makeGUI();
}
}
출력 결과
▶ WindowAdapter
: 윈도우 창에서 일어나는 유저의 모든 활동을 담당
▶ Window Event
: 컴퓨터의 그래픽 환경에서 유저의 모든 활동
▶ frm.addWindowListener()
: frm에 윈도우 이벤트를 감지하는 센서 추가
: 감지한 이벤트는 ()안에 위치
→ JRE는 frm을 감시하다 이벤트가 발생하면 ()안의 명령 수행
: 이벤트 발생시 수행 절차만 정의
▶ btn.addActionListener()
: btn에 이벤트 감지 센서 추가
: 감지한 이벤트는 ()안에 위치
→ JRE는 addActionListener가 적용된 컴포넌트를 감시하다 이벤트가 발생하면 () 안의 명령 수행
◆ WindowAdapterObject.java
package ch10;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class WindowAdapterObject extends WindowAdapter{
@
Override
public void windowClosing(WindowEvent e) {
System.out.println("Window Closing");
System.exit(0);
}
}
◆ ActionListenerObject.java
package ch10;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ActionListenerObject implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.getActionCommand());
String command = e.getActionCommand();
if (command.equals("C")) {
System.out.println("화면 클리어");
} else if (command.equals("=")) {
System.out.println("두 번째 입력 수를 sNum 저장, 기호에 따라 계산을 수행");
} else if (command.equals("/") || command.equals("x") ||
command.equals("-") || command.equals("+")) {
System.out.println("첫 번째 입력 수를 fNum에 저장, 기호는 giho에 저장");
}
}
}
◆ Event2ButtonAction.java
package ch10;
import java.awt.Button;
import java.awt.Frame;
public class Event2ButtonAction {
Frame frm;
Button btnPlus, btnMinus, btnMulti, btnDivide, btnEqual, btnClear;
ActionListenerObject obj;
WindowAdapterObject closeobj;
public Event2ButtonAction() {
frm = new Frame();
btnPlus = new Button("+");
btnMinus = new Button("-");
btnMulti= new Button("x");
btnDivide = new Button("/");
btnEqual = new Button("=");
btnClear = new Button("C");
obj = new ActionListenerObject();
closeobj = new WindowAdapterObject();
}
public void makeGUI() {
frm.setSize(500, 500);
frm.setVisible(true);
frm.setLayout(null);
frm.addWindowListener(closeobj);
frm.add(btnPlus); frm.add(btnMinus); frm.add(btnMulti);
frm.add(btnDivide); frm.add(btnEqual); frm.add(btnClear);
btnPlus.setBounds(20, 35, 150, 150);
btnMinus.setBounds(175, 35, 150, 150);
btnMulti.setBounds(330, 35, 150, 150);
btnDivide.setBounds(20, 190, 150, 150);
btnEqual.setBounds(175, 190, 150, 150);
btnClear.setBounds(330, 190, 150, 150);
// 액션 발생 시 obj 메소드 실행
btnPlus.addActionListener(obj);
btnMinus.addActionListener(obj);
btnMulti.addActionListener(obj);
btnDivide.addActionListener(obj);
btnEqual.addActionListener(obj);
btnClear.addActionListener(obj);
}
public static void main(String[] args) {
Event2ButtonAction window = new Event2ButtonAction();
window.makeGUI();
}
}
출력 결과