(1) 패키지 (package) : 폴더(디렉토리)와 비슷

> 클래스를 기능별로 묶은 것

> os(operating system 운영체제)의 folder (구분 - win : \ , linux mac : /)

> java의 package 구분 : .

> 클래스 이름의 일부

전체 클래스 이름 = 상위패키지.하위패키지.클래스

* 클래스명이 같아도 패키지명이 다르면 다른 클래스!!

> 클래스를 선언할 때 패키지가 결정된다.

클래스 파일은(~.class) 선언된 패키지와 동일한 폴더 안에서만 동작 (다른 폴더에서는 동작 x)

 

선언)

클래스 선언 첫 줄에 해야 한다.

package 상위패키지.하위패키지;

public class ClassName{ }

 

package pn.pn.pn;

접근제어자 [modifier] class ClassName [extends ClassName implements x1,x2,x3....] {

        variable
        - instance var
        - class var (static)

            constructor
            - ClassName()

            method
            - method(){}
            [ - abstract method();]

}

 

* 패키지 이름 규칙, 관례

1. 전부 알파벳 소문자로 작성

2. 숫자로 시작 x

3. _,$ 를 제외한 특수 문자 사용 x

4. 회사 도메인의 역순으로 보통 패키지 이름을 작성 (ex) com.samsung.projectname)

 

- 자바에서 제공하는 system package ****** (숙달 필요!!!!)

 

-java.lang : 가장 기본 package (별도의 import 없이 사용 가능)

-java.util : 없어도 되지만, 있으면 편한 것

-- util class

-- JCF(Java Collection Framework)

-java.io : input/output(입출력)

-java.text : 형식

-java.awt : 추상윈도우 만드는 것 (abstract window toolkit)

-java.awt.event : event처리

-java.net : network

-java.sql : JDBC (Java DataBase Connectivity)

.

.

.

 

(2) import문

> 같은 패키지 내에 포함된 클래스간에는 자유롭게 사용이 가능하다.

> 다른 패키지에 있는 클래스를 사용할 수 있는 방법 2가지

(패키지가 달라지면 import 필요, 패키지의 모든 class는 import로 사용 가능)

 

① 패키지명이 포함된 전체 클래스 이름을 사용 (전체를 다 입력해줘야 하기 때문에 귀찮다....)

 

package com.mycompany;

public class Car{
     com.hankook.Tire tire = new com.hankook.Tire();
}

② import문으로 패키지를 지정하고 사용 (주로 사용되는 방법)

package com.mycompany;

import com.hankook.Tire;

public class Car{
  Tire tire = new Tire();
}

 

* 컴파일 에러(~ cannot be resolved to a type) 가 난 상태에서 이클립스 단축키 (Ctrl + Shift + O) 누르면?

자동으로 import문 생성

 

Q. import com.hankook. * 같은 패키지 내에 있는 여러 개의 클래스를 모두 사용하고자 한다면?

이클립스에서 설정방법) 1. window>preference>java>code style>organize imports 선택

2. number of imports needed for.*의 99를 1로 변경한 후 [OK] 버튼 클릭

3. 다시 Ctrl + Shift + O 클릭

 

(3) cmd 이용하기

 

** cmd에서 class가 저장되어 있는 폴더로 이동

 

Q. cmd창에서 클래스 파일을 자동으로 javac로 compile 하는 법

javac -d .*.java (현재폴더)

javac -d d:\ .*.java (d드라이브 특정위치)

 

Q. jar 압축 파일 생성하는 법

jar 입력해서 사용법 보기

jar -cvf tire.jar com (저장하고자 하는 파일 이름)

c: create

v: 추가하는 중 : ~% 저장함

f : 폴더

 

Q. 외부에서 클래스파일을 가져오게 된다면? jar 압축 파일 활용하는 2가지 방법 (폴더까지 달라지면)

1.C:\Program Files\Java\jdk1.8.0_231\jre\lib\ext (java가 기본으로 참조한다.)

여기에 잘라내기 해서 붙여넣기

 

2.내PC>속성>환경변수 : CLASSPATH 원래 .만 있던 곳에 .;D:\javadata (java.jar 파일이 있는 곳) 설정하기

 

 

 

(1) 열거 타입 : 한정된 값만을 갖는 데이터 타입 (요일, 계절, 로그인 성공? 실패?.....)

: 한정된 값은 열거 상수(요일 中 월, 화, 수, 목, 금, 토, 일)

** JDK5에서 추가 (이전에는 상수를 열거형 대신 사용)

Q. 열거 대신 상수를 사용했을 때의 문제점??

> String 으로 선언된 변수에 한정된 값만을 대입하고 싶은데, String 타입이기 때문에 아무 문자열이나 올 수 있게 된다.... 해결 방법으로 열거형이 나옴!!

 

선언) 파일 이름과 동일한 이름으로 할 것!!!

public enum 열거타입이름 {열거상수1,열거상수2....} // 열거 상수는 모두 대문자,' _ ' 사용!!

 

열거 타입 변수 선언)

Week today;

Week reservationDay;

 

열거 상수값 저장)

열거타입 변수 = 열거타입.열거상수;

Week today = Week.MONDAY;

* 열거 타입 변수는 참조 타입이므로 null값으로 초기화 가능~

 

- 열거 객체는 열거 상수의 문자열을 내부 데이터로 가지고 있다.

그렇기 때문에, 열거 상수값을 저장할 때 열거타입.열거상수로만 해야 됨!!

 

- 열거 타입은 컴파일시 java.lang.Enum 클래스를 자동 상속한다.

 

- values() 메소드 / 향상된 for문 이용

Week[] days = Week.values();

for(Week day : days) {

System.out.println(day);

}

> days[0] ~days[6] : MONDAY~SUNDAY 까지 출력됨.

 

(2) 싱글톤(Singleton) : 어떠한 클래스는 단 하나의 객체만 생성되야 하는 클래스가 존재한다.

만드는 방법)

1. 클래스 자신의 타입으로 정적 필드를 선언하고, 자신의 객체를 생성해 초기화한다.

 

2. private 접근 제한자를 생성자 앞에 붙인다. (외부에서 여러 개의 생성자 생성하는 것을 막는다.)

 

3. 외부에서 호출할 수 있는 정적 메소드인 getInstance()를 선언한다.

(정적 필드에서 참조하고 있는 자신의 단 하나의 객체만 리턴하도록!!!)

public class 클래스이름 {
//정적 필드
private static 클래스이름 singleton = new 클래스이름();

//생성자
private 클래스() {}

//정적 메소드
public static 클래스이름 getInstance() {
	return singleton;

	}
}

 

public class Singleton {
	
		private static Singleton singleton = new Singleton(); //객체 생성

		private Singleton(){ //생성자 생성
			
		}

		static Singleton getInstance(){
			return singleton;
		}
}
public class SingletonExample {
	public static void main(String[] args) {
		//Singleton obj = new Singleton(); private으로 생성자 생성을 막아놓았기 때문에 error

		//유일한 singleton 메소드 호출 방법
		Singleton obj1 = Singleton.getInstance();
		Singleton obj2 = Singleton.getInstance();

		if (obj1 == obj2){
			System.out.println("같은 Singleton 객체입니다.");
		} else {
			System.out.println("다른 Singleton 객체입니다.");
		}
	}
}

 

---------- run ----------
같은 Singleton 객체입니다.

 


 

package test06;

public class SingletonClass {

	//static이니까 SINGLETON_CLASS_INSTANCE 데이터영역에 존재, SingletonClass()는 heap영역에 존재
	private static SingletonClass SINGLETON_CLASS_INSTANCE = new SingletonClass();
	public int i = 10;
	
	//외부에서 생성자 생성 막기 위해서 private
	private SingletonClass() {}
	
	//객체를 못 만드니까 static으로 객체가 만들어지기 전부터 데이터 영역(클래스 영역)에서 사용 가능
	//자신의 클래스에서 객체생성을 하고 있다.
	public static SingletonClass getSingletonClass() {
		if(SINGLETON_CLASS_INSTANCE==null) { //FirstClass
			SINGLETON_CLASS_INSTANCE = new SingletonClass();
		}
		return SINGLETON_CLASS_INSTANCE; //SecondClass
	}
	
	public int getI() {
		return i;
	}
	
	public void setI(int i) {
		this.i = i;
	}
}
package test06;

public class FirstClass {

	public FirstClass() {

		SingletonClass singletonClass = SingletonClass.getSingletonClass();
		System.out.println("FirstClass 입니다.");
		System.out.println("i=" + singletonClass.getI());
		singletonClass.setI(200);
		System.out.println("i=" + singletonClass.getI());
	}
}
package test06;

public class SecondClass {

	public SecondClass() {

		SingletonClass singletonClass = SingletonClass.getSingletonClass();
		System.out.println("SecondClass 입니다.");
		System.out.println("i=" + singletonClass.getI());
	}
}
package test06;

public class MainClass {

	public static void main(String[] args) {

		FirstClass firstClass = new FirstClass();
		SecondClass secondClass = new SecondClass();
	}
}
FirstClass 입니다.
i=10
i=200
SecondClass 입니다.
i=200

 

(1) 수정자 (modifier)

 

1.abstract : 추상 (class, method)

 

2.final : 변수, 메소드, 클래스에 모두 사용

variable : 변수에 final을 붙이게 되면 상수화(변수 변경 불가)가 된다.

public class FinalVarTest {
	private final int x; //error : final을 붙였기 때문에 상수화

	public void changeX() {
		x=10;
	}
}
---------- compile ----------
FinalVarTest.java:5: error: cannot assign a value to final variable x
		x=10;

 method : 메소드에 final을 붙이게 되면 상속후에도 override가 불가능하다.

public class FinalMethodTest {
	
	public final void x() {} //final method 
}
public class FinalMethodExt extends FinalMethodTest {
	
	public final void x(){} //final method는 override 불가
}
---------- compile ----------
FinalMethodExt.java:3: error: x() in FinalMethodExt cannot override x() in FinalMethodTest
	public final void x(){} //final method는 override 불가

 

class : 클래스에 final을 붙이게 되면 상속이 불가능하다.

public final class FinalClassTest {
	
}
//final class는 상속 불가능!!

public class FinalClassExt extends FinalClassTest {
	public static void main(String[] args) {
		System.out.println();
	}
}
---------- compile ----------
FinalClassExt.java:3: error: cannot inherit from final FinalClassTest
public class FinalClassExt extends FinalClassTest {

 

3.static : 공유 (객체 생성하지 않아도 클래스의 이름으로 접근 가능), class 변수라고 한다.

> 클래스 변수 : static한 변수, 값을 저장할 수 있는 공간이 하나밖에 없어서 값을 공유한다.

> 인스턴스가 여러개 생성되어도 static 변수는 딱 하나이다.

 

공용적인 데이터, 동일한 값, 고정 값 등

사용 ) 클래스의 이름.변수이름

VS

instance 변수 : 각자의 객체를 참조해야 접근 할 수 있는 변수, 객체 생성 필요

객체마다 가지고 있어야 할 데이터, 변화 가능한 객체들의 특징

사용) 객체의 이름. 변수이름

 

variable : static을 붙일 수 있다.

method : static을 붙일 수 있다.

class : static을 붙일 수 없다. (단, inner class에서는 가능)

class A {

	class B {

	}

}

 

Q. static 블록과 메소드에서 instance 필드나 메소드를 사용하고 싶다면??

> 객체를 생성해서 사용 가능하다!! or 필드나 메소드에 static 붙이기

 

* static이 선언되지 않은 변수와 메소드는 static 블록내(main method)에서 사용 불가능

(but, static 블록이 아닌 다른 블록 내에서는 static 변수와 메소드가 사용 가능!!!)

Static(공유)

y

class 변수

A

Heap

(동적할당)

 

x=10

y

----------

x

y=20

 

instance 변수

Stack

a1 a2

 

 

a1.x = 10;

S.o.p(a2.x); //0

a2.y = 20; -----------A.y = 20;

S.o.p(a1.y); //0 ------S.o.p(A.y); //20

 

* static과 객체와의 관계

> static은 클래스 변수다.

> 객체는 클래스에서 생성(복사) 되어진다.

> 클래스 하나에서 무한대로 객체를 생성할 수 있지만, 독립적인 전혀 다른 덩어리들이다.

> static이 붙은 변수는 클래스 변수로써 객체가 생성되기 전에 이미 존재한다.

 

클래스들이 모여 있는 데이터 영역 (new로 객체 생성하기 전)

객체들이 모여 있는 Heap 영역(new로 객체 생성) ----> 가비지 콜렉터는 Heap 영역만 메모리를 관리한다.

 

*설명

 

variable

method

class

abstract

x

o

o

final

o

o

o

static

o

O

X

(but,

inner class o)

 

4. 상수 : 상수이기 때문에 초기화 필요 (한 번 값을 초기화하면 변경 불가), 대문자로 작성하는 것이 관례

초기화 방법 )

1. 처음 선언에서 초기화 하기

static final DataType CONSTANCE_NAME = 값;

2. static 블록에서 초기화 하기 (복잡한 초기화 식이 있을 때)

static final DataType CONSTANCE_NAME;

static{

상수 = 초기값;

final 필드

static final (상수)

instance 필드

정적 필드

생성자에서 초기화 될 수 있다.

생성자에서 초기화 될 수 x

* 생성자를 생성하는 것 자체가 객체를 생성하는 것이기 때문에 상수는 객체를 생성하기 전에

이미 완성이 되어 있어야 한다!!

(선언할 때 or 정적 블록에서 초기화 되야 함)

 

대문자로 작성, 합성어인 경우 _로 구분

 

객체 생성없이 클래스를 통해 사용

초기값이 저장되면 값을 변경할 수 없다.


- 포인트 적립 ex) 객체 따로따로 counting...

public class PointCard {
	String name;
	int count; 

	public PointCard(String name){
		this.name = name;
	}

	public void buy(){
		count++;
	}
}
public class PointStore {
	public static void main(String[] args) {
		PointCard pc1 = new PointCard("홍길동");
		PointCard pc2 = new PointCard("임꺽정");
		System.out.println(pc1.name + "님 구매!!!");
		pc1.buy();
		System.out.println("스탬프 : " + pc1.count + "개");

		System.out.println(pc2.name + "님 구매!!!");
		pc2.buy();
		System.out.println("스탬프 : " + pc2.count + "개");

		System.out.println(pc1.name + "님 구매!!!");
		pc1.buy();
		System.out.println("스탬프 : " + pc1.count + "개");

		System.out.println(pc2.name + " 스탬프 확인 : " + pc2.count + "개");
	}
}
---------- run ----------
홍길동님 구매!!!
스탬프 : 1개
임꺽정님 구매!!!
스탬프 : 1개
홍길동님 구매!!!
스탬프 : 2개
임꺽정 스탬프 확인 : 1개

 

- 위의 코딩에 static만 추가해 본다면?? '누적' 방문객 수를 출력할 수 있다!! (공유), 객체 생성하지 않고!!

> 하나의 변수이기 때문에 값이 계속 누적!!

public class Guest {
	String name;
	static int count; //방문횟수

	public Guest(String name){
		this.name = name;
	}

	public static void visit(){
		count++;
	}
}
public class Store {
	public static void main(String[] args) {
		
		System.out.println("손님 방문!!!"); 
		Guest.visit();
		System.out.println("방문자수 : " + Guest.count + "명");

		System.out.println("손님 방문!!!");
		Guest.visit();
		System.out.println("방문자수 : " + Guest.count + "명");

		System.out.println("손님 방문!!!");
		Guest.visit();
		System.out.println("방문자수 : " + Guest.count + "명");
	}
}
---------- run ----------
손님 방문!!!
방문자수 : 1명
손님 방문!!!
방문자수 : 2명
손님 방문!!!
방문자수 : 3명

 

ex) 객체 생성하지 않고 호출하기

public class Printer{
	
	static void printin(int a){
		System.out.println(a);
	}

	static void println(boolean a){
		System.out.println(a);
	}

	static void println(double a){
		System.out.println(a);
	}

	static void println(String a){
		System.out.println(a);
	}	
}
public class PrinterExample {
	public static void main(String[] args) {
		
		Printer.println(10);
		Printer.println(true);
		Printer.println(5.7);
		Printer.println("홍길동");
	}
}

 

(2) 배열 (Array) -- 반복문과 단짝!!!!

 

장점 : 서로 연관된 데이터를 정리정돈 !!

(* 변수가 많을수록 오류 or 혼동 가능성이 있기 때문에 서로 연관된 데이터는 하나의 배열 변수로 만들어 주는 것이 좋다!!!!)

 

1.같은 DataType 여러 개 을 연속적으로 저장.

 

2.배열은 생성시 크기를 반드시 지정 >> 한 번 정해진 배열의 크기는 변할 수 없다..

>> 배열의 크기 : int size = 배열명.length;

 

3.기본DataType을 저장하는 reference 배열의 사용

a. 선언

형식) 접근제어자 기본DT[ ] 배열명;

                       or

        접근제어자 기본DT 배열명[ ]; (둘 다 똑같지만, 이 형식을 더 많이 사용)

 

ex)

public int x[ ];

private boolean b[ ];

 

b.생성

형식) 배열명 = new 기DT[크기];

ex)

x = new int[3]

b = new boolean[2];

 

>> a, b를 동시에 가능!!

접근제어자 기DT 배열명[ ] = NEW 기DT[크기];

public int x[ ] = new int[3];

private boolean b [ ]= new boolean[2];

 

c. 사용 : 값 할당

형식)

get : 배열명[index];

set : 배열명[index] = 값;

ex)

int x1 = 10;

int x2 = 30;

int x3 = 30;

>>> 배열

x[0] = 10;

x[1] = 20;

x[2] = 30;

S.o.p(x[0]);//10

S.o.p(x[1]);//20

S.o.p(x[2]);//30

       or

int len = x.length;

for(int i=0;i<len;i++) {

x[i] = (i+1) * 10;

S.o.p(x[i]);

}

 

>> a,b,c를 동시에..

ex)

public int x[] = {10,20,30};

public class ArrayTest1 {
	public static void main(String[] args) {
		int x1 = 10;
		int x2 = 20;
		int x3 = 30;
		System.out.println("x1 : " + x1 + "  x2 : " + x2 + "  x3 : " + x3);

		int x[] = new int[3];
		x[0] = 10;
		x[1] = 20;
		x[2] = 30;
		System.out.println("x[0] : " + x[0] + "  x[1] : " + x[1] + "  x[2] : " + x[2] );

		int y[] = new int[3];
		int len = y.length;
		for (int i=0;i<len ;i++ ){ //규칙이 있다면 for문 사용
			y[i] = (i+1)*10;
			System.out.print("  y[" + i + "] : " + y[i]);
		}
		System.out.println();

		int z[] = {10,20,30,40};
		len = z.length;
		for (int i=0;i<len ;i++ ){
			System.out.print("  z[" + i + "] : " + z[i]);
		}
	}
}
---------- run ----------
x1 : 10  x2 : 20  x3 : 30
x[0] : 10  x[1] : 20  x[2] : 30
  y[0] : 10  y[1] : 20  y[2] : 30
  z[0] : 10  z[1] : 20  z[2] : 30  z[3] : 40
/*
정수형의 5개의 배열을 만드시오.
1-10까지의 수 중 짝수만 저장.
출력.
*/

public class ArrayTest2 {
	public static void main(String[] args) {
		int x[] = new int[5];
		int idx = 0;
			for (int i=1;i<=10 ;i++ ){
				if (i%2==0){
					x[idx++] = i; //x[]에 i를 대입해라
				}
			}
		int len = x.length;
		for (int i=0;i<len ;i++ ){
			System.out.println(x[i]);
		}
	}
}
/*백준 알고리즘 배열 문제 (음계)
int x[] = {1,2,3,4,5,6,7,8}; -- ascending
int x[] = {8,7,6,5,4,3,2,1}; -- descending
int x[] = {8,1,7,2,6,3,5,4}; -- mixed
*/

public class ArrayTest3 {
	public static void main(String[] args) {
		int x[] = {1,2,3,4,5,6,7,8};
		//int x[] = {8,7,6,5,4,3,2,1};
		//int x[] = {8,1,7,2,6,3,5,4};
		
			/*int len = x.length;
			int idx = 0;
			for (int i=1;i<len ;i++ ){
				if (x[0]<x[1]){
					x[idx++] = i;
					System.out.println("ascending");
			}

				if (x[0]>x[1]){
					x[idx++] = i;
					System.out.println("descending");
				} else {
					System.out.println("mixed");
				}
			}*/

		int len = x.length;
		int a = 0;
		int d = 0;
		String str = "mixed";  
		for(int i=1;i<len;i++) { //배열의 길이는 8, 서로 비교해야 하니까 0이 아닌 1부터 시작!!
			if(x[i-1] < x[i])    
				a++;
			if(x[i-1] > x[i])
				d++;
		}
		
		if(a == 7)
			str = "ascending";
		else if(d == 7)
			str = "descending";
		System.out.println(str);

	}
}

 

4. for each문 : 값을 꺼내서 알아서 대입해 준다. for문 보다 훨씬 간결해진다.

for(타입 값을 받아줄 변수명 : 출력하고 싶은 자료구조)

//for each문을 이용해서 iarr의 값을 한 줄씩 출력하라.

public class Array1 {
	public static void main(String[] args) {
		int[] iarr = {10,20,30,40,50};

		
		for (int i=0;i<iarr.length ;i++ ){
			int value = iarr[i];
			System.out.println(value);
			
		}
		//System.out.println(value); //반복된 후 마지막 값인 50만 출력됨.

		for (int value : iarr){
			System.out.println(value);
		}
	}
}

 

 

 

cf) 오라클에서 날짜 구하는 방법

select to_char(sysdate, 'd') : 'ddd'는 365일, 'dd'는 '한달', 'd'는 한주

 

cf) cmd창에서 경로 이동할 때,

cd \ : 최상위

cd .. : 하나위

cd . : 현재폴더

 

(1) API 문서에서 check할 것

1. 제일 먼저 추상클래스(abstract) 인지 아닌지 확인하기!!

2. 생성자 확인 ()

3. 추상클래스라면 하위클래스가 있는지 확인 Direct Known Subclasses: 바로 아래 하위클래스

Q. final이라면? 하위클래스 자체가 없는 것!! final클래스는 상속불가이기 때문에

4. 상속구조 확인

 

API(Application Programming Interface : 응용 프로그래밍 인터페이스)문서 --> Packages의 java.util(어디에 있는지 명시해줘야 함) --> class의 Calendar로 확인

 

(2) 추상클래스의 객체 생성 방법

① 하위 클래스를 참조 (가장 일반적 방법 50%정도 사용)

ex) Calendar cal = new Calendar(); >> x

Calendar cal = new GregorianCalendar(); >> o

 

Q. 하위 클래스가 없다면?

② 자신의 객체를 return하는 static method 이용

static은 객체 생성없이 메소드 호출 가능

ex) Calendar cal = Calendar.getInstance(); //

* getInstance() 는 자신의 컴퓨터의 현재 날짜를 Calendar 객체로 만들어서 값을 리턴해주는 메소드

 

Q. a,b도 없다면?

java.lang(아무것도 안해도 내꺼처럼 사용할 수 있다.) --> Process 영어 설명 읽어보기

③ 외부클래스를 참조

ex) Runtime이 먼저 필요

Runtime r = Runtime.getRuntime(); //Runtime의 객체 리턴

Process p = r.exec("command");

 

④ 자신의 생성자 이용 (경우에 따라서 가능한 경우) - dynamic 동적 객체 생성 >> 자바만의 특징

import java.util.Calendar; //어디에 있는지 위치 명시해 줘야 함
import java.util.GregorianCalendar;

public class CalenderTest {
	public static void main(String[] args) {
		//Calendar cal = new Calendar(); //error : 추상클래스라서 
		//1.하위 클래스 참조
		//Calendar cal = new GregorianCalendar(); //하위클래스 참조
		
		//2.static method
		Calendar cal = Calendar.getInstance();
		int y = cal.get(Calendar.YEAR);
		int m = cal.get(Calendar.MONTH) + 1; //MONTH는 반드시 +1 해주기.. index에서 1월은 0이다..
		int d = cal.get(Calendar.DAY_OF_MONTH);
		int apm = cal.get(Calendar.AM_PM);
		int h = cal.get(Calendar.HOUR_OF_DAY);
		int mi = cal.get(Calendar.MINUTE);
		int s = cal.get(Calendar.SECOND);
		System.out.println("지금은 " + y + "년 " + m + "월 " + d + "일 " + (apm == 0? "오전 " : "오후") + h + "시 " + mi + "분 " + s + "초입니다.");
	}		
}
---------- run ----------
지금은 2019년 11월 1일 오전 0시 6분 48초입니다.
public class ProcessTest {
	public static void main(String[] args) throws Exception{
	
	//3.외부클래스 참조
	Runtime r = Runtime.getRuntime(); 
	Process process = r.exec("calc.exe"); //계산기 띄우기
	Thread.sleep(3000); //3000/1000 = 3초안에 계산기 꺼진다.
	process.destroy();
	}
}
import java.awt.*;
import java.awt.event.*;


public class WindowTest extends Frame {
	
	Button b = new Button("눌러");

	public WindowTest(){
		super("추상클래스 생성 테스트");
		setLayout(new FlowLayout());
		add(b);

		Toolkit tk = Toolkit.getDefaultToolkit();
		Dimension ds = tk.getScreenSize();
		int width = ds.width;
		int height = ds.height;

		setLocation(width/2-200,height/2-150);
		setSize(400,300);
		setVisible(true);
		
		//4. 동적 객체 생성 
		WindowAdapter wa = new WindowAdapter(){
			public void windowClosing(WindowEvent e){
				System.out.println("프로그램을 종료합니다.");
				System.exit(0);
			}

			public void windowIconified(WindowEvent e){
				System.out.println("최소화합니다.");
			}
		}
		addWindowListener(wa);
	}

	public static void main(String[] args){
		new WindowTest();
	}
}

 

(3) 인터페이스(Interface) : 껍데기, 작업지시서, 명세서, 약속(전부 다 추상메소드로 되어 있다>> 모든 메소드는 override해야 함)

 

***추상클래스와 비교***

추상클래스는 ???

> 내가 필요한 것들은 구현해놓고, 못하는 것들은 구현을 해라

 

인터페이스는??

> 모든 것을 구현해라

 

Q. 왜 만들어졌을까?

>반드시 구현해야 하는 클래스가 여러개 있을 경우 사용

>추상클래스는 추상메소드를 모두 override 했어야 했다.

>클래스는 다중 상속이 불가능하고 일대일 관계만 성립하지만, interface는 다중 implements가 가능하기 때문에 자주 사용된다.

 

- 개발 코드는 객체의 내부 구조를 알 필요가 없기 때문에 인터페이스의 메소드만 알고 있으면 ok~

역할)

개발 코드가 객체에 종속되지 않게 하여 객체를 교체할 수 있도록 하는 역할

개발 코드 변경 없이 리턴값 or 실행 내용이 다양해 질 수 있다.(다형성)

 

ex) 클래스인 도형을 상속받아 사각형의 넓이, 원의 넓이와 둘레를 구한다고 가정해보자.

(둘레 클래스와 넓이 클래가 따로 존재한다고 가정)

>> 사각형의 넓이는 부모 클래스인 도형의 메소드를 상속받아 사용할 수 있지만,

원은 넓이만 상속받고 둘레는 다중 상속받을 수가 없기 때문에, 따로 구현해야만 하는 문제가 발생한다.

 

1.변수 or 구현메소드 or 생성자가 존재하지 x

상수 or 추상메소드는 존재 o

>> 상수와 추상메소드만 갖는 클래스의 일종

 

2.형식)

접근제어자 interface InterfaceName {

// 상수;

[public static final] 타입 상수명 = 값; // 상수는 모두 대문자!! 초기값을 반드시 줘야 한다.!!

 

// 추상 메소드(매개변수); {실행블록 x}

[public abstract] 리턴타입 메소드명(매개변수);

 

// 디폴트 메소드() {...}; // 자바 8부터 추가됨.

[public] default 리턴타입 메소드명(매개변수);

 

// 정적 메소드() {...}; // 자바 8부터 추가됨.

[public] static 리턴타입 메소드명(매개변수);

}

 

3.스스로 객체 생성 불가능...

>> 클래스에 implements(구현) 후 사용가능 (구현한 클래스를 참조해서 객체 생성)

ex) class Television implements RemoteControl{....}

RemaoteControl rc = new Television();

rc.turnOn(); -------> Television의 turnOn() 실행

 

4.implements keyword 사용

형식)

접근제어자 class ClassName [extends ClassName] implements In1, In2, In3....

 

interface가 가진 모든 추상 메소드를 override

}

 

5.interface는 다중 implements가 가능

 

6. 인터페이스 변수와 구현 객체

ex) class Television implements RemoteControl{....}

RemoteControl rc;

rc = new Television();

 

7. 익명 구현 객체 : 이름이 없는 구현 클래스 선언과 동시에 객체 생성 -- 중첩클래스에서 다시 나옴

사용)

인터페이스 변수 = new 인터페이스(){

//인터페이스에 선언된 추상 메소드를 모두 재정의하는 실체 메소드 선언

}

 

> 언제 사용?

- UI 프로그래밍(Swing,Android,java FX)에서 이벤트를 처리하기 위해 주로 사용

- 임시 작업 스레드를 만들기 위해 사용

 

8.

상위

class

class

interface

interface

 

extends

x

implements

extends

하위

class

interface

class

interface

 

*Interface : 상수와 추상메소드만 갖는 클래스의 일종이기 때문에 구지 abstract를 붙일 필요가 없다.

public interface DohyungRound { 

	//double round = 10; //상수가 되서 다른 곳에서 변경 or 사용할 수 없기 때문에!! 
                         //인터페이스는 변수를 가질 수 없다는 것이 증명!
	public double calcRound();
}
public interface DohyungArea { 
	
	public double calcArea(); 

}
public class Rect implements DohyungArea{
	int width;
	int height;

	public Rect(){
		this(4,3);
	}

	public Rect(int width, int height){
		this.width = width;
		this.height = height;
	}

	public double calcArea(){
		return width * height;
	}

	void info(){
		System.out.println("사각형입니다.");
	}
}
public class Circle implements DohyungArea, DohyungRound { //클래스의 다중 상속은 불가능하지만, 다중 implements는 가능

	int radius;

	public Circle(){ 
		radius = 4;
	}

	public Circle(int radius){ 
		this.radius = radius;
	}

	public double calcArea(){
		return Math.pow(radius,2)*Math.PI;
	}
	
	public double calcRound(){
		return 2*Math.PI*radius;
	}
}
public class MatheMatics {

	static void printDohyung(Rect rect) {
		double area = rect.calcArea();
		System.out.println("가로가 " + rect.width + "이고 세로가 " + rect.height + "인 사각형의 넓이는 " + area + "입니다.");
	}

	static void printDohyung(Circle circle) {
		double area = circle.calcArea();
		double round = circle.calcRound();
		System.out.println("반지름이 " + circle.radius + "인 원의 넓이는 " + area + "이고 둘레는 " + round + "입니다.");
	}

	public static void main(String[] args) {
		
		Rect r1 = new Rect();

		printDohyung(r1);

		Rect r2 = new Rect(7, 5);

		printDohyung(r2);

		Circle c1 = new Circle();
		printDohyung(c1);

		Circle c2 = new Circle(6);
		printDohyung(c2);	
	}	
}
---------- run ----------
가로가 4이고 세로가 3인 사각형의 넓이는 12.0입니다.
가로가 7이고 세로가 5인 사각형의 넓이는 35.0입니다.
반지름이 4인 원의 넓이는 50.26548245743669이고 둘레는 25.132741228718345입니다.
반지름이 6인 원의 넓이는 113.09733552923255이고 둘레는 37.69911184307752입니다.
import java.awt.*;
import java.awt.event.*;

public class WindowListenerTest extends Frame implements WindowListener {
	
	Button b = new Button("눌러");

	public WindowListenerTest(){
		super("interface 생성 테스트");
		setLayout(new FlowLayout());
		add(b);

		Toolkit tk = Toolkit.getDefaultToolkit();
		Dimension ds = tk.getScreenSize();
		int width = ds.width;
		int height = ds.height;

		setLocation(width/2-200,height/2-150); //중앙에 오게 하기
		setSize(400,300);
		setVisible(true);
		
		//WindowListener w1 = new WindowListenerTest();
		//WindowListener w1 = this;
		addWindowListener(this);
	}

	//모든 메소드를 override 해야함!!!
	public void	windowActivated(WindowEvent e){}

	public void	windowClosed(WindowEvent e){}

	public void	windowClosing(WindowEvent e){
		System.exit(0);
	}

	public void	windowDeactivated(WindowEvent e){}

	public void	windowDeiconified(WindowEvent e){}

	public void	windowIconified(WindowEvent e){}

	public void	windowOpened(WindowEvent e){}

	public static void main(String[] args) {
		new WindowListenerTest();
	}
}

 

(4) 인터페이스의 default method --> java 8부터 생김..

(기존 인터페이스는 추상메소드와 상수만 가질 수 있었다...)

① default 키워드를 이용하여 추상메소드가 아닌 default 메소드가 구현 가능하다.

사용) 하위클래스 참조하여 객체 생성

② static 키워드를 이용하여 메소드 구현 가능하다.

사용) 인터페이스명.메소드명();

Q. 왜 추가 되었나?

> 인터페이스 내에서는 추상클래스만 올 수 있었기 때문에 인터페이스 내에서 구현이 불가능했다.

하지만, default나 static 키워드를 사용한 메소드가 인터페이스 내에서 구현가능하게 됨으로써, 인터페이스 내는 물론이고, 이를 구현하고자 하는 클래스에서도 default 메소드를 오버라이드하여 사용할 수 있게 되었다.

 

cf) 인터페이스를 사용하는 목적은 ?

>> 디자인의 측면에서, Client 입장에서는 자신이 사용하는 구체적인 클래스를 몰라도, 인터페이스에 정의된 메서드를 사용하는 객체라는 것이 보장되어 있기 때문에 구체적인 클래스의 변경이 일어나더라도 Client의 코드수정은 불필요!!! 구현 객체의 같은 동작을 보장하기 위한 목적이 있다.

 

(5) 추상클래스 vs 인터페이스

<공통점>

1. 추상메소드를 가지고 있다. ---> 하위클래스에서 구현해야 한다.

2. 데이터 타입이 목적이다. 객체생성이 목적이 아니라 데이터 타입을 정의하는 것이 목적이다.

3. 객체 생성은 'anonymose'를 이용해야 한다.

<차이점>

1. 상속, 구현 - 추상메소드는 상속을 통한 사용이고, 인터페이스는 구현을 통한 사용이다.

2. 구성요소 차이 - 추상클래스는 일반 클래스와 동일하게 변수와 메소드의 모든 기능을 사용할 수 있지만,

인터페이스는 상수와 추상메소드만 존재한다.

3. 단일상속, 다중구현 - 추상클래스는 상속이므로 단일 상속만 지원하고, 인터페이스는 다중구현이 가능하다.

 

 

(1) 추상 클래스 (Abstract Class) : 공통된 특성을 추출해서 만든 클래스

 

Q. 왜 추상클래스를 만들까?

> ex) 본사에서 메뉴만 정해주고 가격은 정해주지 x --> 각 매장에서 가격을 정해서 사용해라

---> 즉, 추상적으로 정의할 테니, 사용자가 꼭 '강제적'으로 overriding(재정의) 하라는 의미!!

ex) 어떤 메소드는 override하고, 어떤 메소드는 override를 하지 않을 경우, 본사에서 가격을 정하지 않았기 때문에 0원이 발생하는 경우가 존재한다. 따라서 모든 추상메소드를 override 해야 함!!!!

> 추상클래스를 상속 받은 실체 클래스의 공통된 필드와 메소드 이름을 통일할 목적으로 생성

= 여러 사람이 실체 클래스를 설계할 경우, 제각기 필드와 메소드 이름을 가질 수 있기 때문에 통일

> 실체 클래스 작성시 시간 절약

> 하위클래스에서 상위클래스의 메소드를 재정의 할 필요가 없을 때는 일반메소드 주로 사용

(ex) 식당에서 모든 사람들이 먹는 메뉴들)

> 하위클래스에서 상위클래스의 메소드를 각 상황에 맞게 재정의 할 필요가 있을 때 추상메소드 주로 사용

(ex) 식당에서 각각의 사람들이 먹는 메뉴들)

 

(2) 추상 메소드(abstract method)를 하나 이상 가진 클래스

* 추상 메소드란?

> method의 body(구현부,{중괄호})가 없는 method

--> 상속받는 자식 클래스에 기능을 위임하는 개념

> abstract keyword(modifier) 사용

> 추상 클래스 내부에는 일반 메소드 구현도 가능하다.

 

형식)

접근제어자 abstract ReturnType methodName ([args]); - 매개변수 생략 가능

 

ex)

public void a(); >> o - a라는 추상 메소드를 만들 것이다.

public void b() {} >> x - 아무 일도 하지 않는 일반 메소드

 

추상클래스 형식)

접근제어자 abstract class ClassName {

 

field

 

constructor

 

method

- 구현 method(){}

- abstract 추상 method();

}

 

**2. 추상클래스는 하위 클래스를 제어하기 위해 사용한다. (2,3번 함께 생각)

**3. 추상클래스는 자신의 생성자로 객체 생성이 불가능하고, 부모 클래스로만 사용된다.

>> 2+3 : 추상클래스는 하위클래스에 상속 후 사용 가능 --> 추상클래스를 상속받는 클래스는 '반.드.시' 추상메소드를 override해야 한다. (강제적으로!!!)

ex)

>> 다형성 : 하위 클래스를 참조하여 상위 클래스의 객체를 생성한다.

 

4. 추상클래스의 객체 생성 방법

a. 하위 클래스를 참조 (가장 일반적 방법 50%정도 사용)

b. 자신의 객체를 return하는 static method 이용

c. 외부클래스를 참조

d. 자신의 생성자 이용 (경우에 따라서 가능한 경우)

 

(3) 클래스 형변환

 

** 부모 타입으로 자식을 가리킬 수 있다. 이 경우 부모가 가지고 있는 필드 or 메소드만 사용이 가능하다.

Dohyung d1 = new Rect();

d1.calcArea();

d1.calcRound();

Q. 부모가 자식의 필드나 메소드를 사용하고 싶다면?? 클래스 형변환을 하면 OK~~~

Rect rect = (Rect) d1;

 

- Animal 추상클래스 만들기

 

public abstract class Animal {
	public String kind;

	public void breathe(){
		System.out.println("숨을 쉰다");
	}

	public abstract void sound();//추상 메소드는 추상 클래스에서만 사용 가능
	                             //동물들의 울음소리는 다 다르기 때문에 추상 메소드로 만들어주기
}
public class Dog extends Animal {
	public Dog(){
		this.kind = "포유류";
	}
	
	@Override
	public void sound(){
		System.out.println("멍멍");
	};
}
public class Cat extends Animal {
	public Cat(){
		this.kind = "포유류";
	}
	
	@Override
	public void sound(){
		System.out.println("야옹");
	};
}
public class AnimalExample {
	public static void main(String[] args) {
		Dog dog = new Dog();
		Cat cat = new Cat();

		dog.sound();
		cat.sound();
		System.out.println("----------------");

		Animal animal = null; // animal이라는 변수 생성
		animal = new Dog(); //자식객체를 만들어서 부모 변수에 대입 (자동타입변환)
		animal.sound(); // override한 자식 메소드 실행 : 멍멍

		animal = new Cat();
		animal.sound(); //  override한 자식 메소드 실행 : 야옹
	}
}

 

- Dohyung 추상클래스 만들기

public abstract class Dohyung { //Dohyung.java:1: error: Dohyung is not abstract and does not override abstract method calcRound() in Dohyung
								//추상클래스로 만들기(강제성)
	
	public abstract double calcArea(); //추상메소드로 만들기

	public abstract double calcRound();
}
public class Rect extends Dohyung{
	int width;
	int height;

	public Rect(){
		this(4,3);
	}

	public Rect(int width, int height){
		this.width = width;
		this.height = height;
	}

	public double calcArea(){
		return width * height;
	}

	public double calcRound(){
		return (width + height) * 2;
	}

	void info(){
		System.out.println("사각형입니다.");
	}
}
public class Circle extends Dohyung {

	int radius;

	public Circle(){ //반지름 = 4
		radius = 4;
	}

	public Circle(int radius){ //외부 값 입력
		this.radius = radius;
	}

	public double calcArea(){
		return Math.pow(radius,2)*Math.PI;//Math.pow(radius,2) : 제곱근, Math.PI : 파이값
	}
	
	
	public double calcRound(){
		return 2*Math.PI*radius;
	}
}

 

- 실행클래스

public class MatheMatics {

	static void printDohyung(Rect rect) {
		double area = rect.calcArea();
		double round = rect.calcRound();
		System.out.println("가로가 " + rect.width + "이고 세로가 " + rect.height + "인 사각형의 넓이는 " + area + "이고 둘레는 " + round + "입니다.");
	}

	static void printDohyung(Circle circle) {
		double area = circle.calcArea();
		double round = circle.calcRound();
		System.out.println("반지름이 " + circle.radius + "인 원의 넓이는 " + area + "이고 둘레는 " + round + "입니다.");
	}

	public static void main(String[] args) {
		//int area = 0;
		//int round = 0;
		//default 생성자를 이용한 넓이와 둘레를 구하시오.
		Rect r1 = new Rect();

		//가로가 4이고 세로가 3인 사각형의 넓이는 12이고 둘레는 14입니다.
		/*
		area = r1.calcArea();
		round = r1.calcRound();
		System.out.println("가로가 " + r1.width + "이고 세로가 " + r1.height + 
			"인 사각형의 넓이는 " + area + "이고 둘레는 " + round + "입니다.");
		*/
		printDohyung(r1);

		//가로 7, 세로 5인 사각형의 넓이와 둘레를 구하시오. 
		Rect r2 = new Rect(7, 5);

		//가로가 7이고 세로가 5인 사각형의 넓이는 35이고 둘레는 24입니다.
		/*
		area = r2.calcArea();
		round = r2.calcRound();
		System.out.println("가로가 " + r2.width + "이고 세로가 " + r2.height + 
			"인 사각형의 넓이는 " + area + "이고 둘레는 " + round + "입니다.");
		*/
		printDohyung(r2);

		Circle c1 = new Circle();
		printDohyung(c1);

		Circle c2 = new Circle(6);
		printDohyung(c2);

		//Dohyung d1 = new Dohyung(); error 추상클래스는 자신의 생성자로 객체 생성 할 수 x
		Dohyung d1 = new Rect(); // 추상클래스는 하위클래스를 참조해서 객체를 생성한다.
		//d1.info();
		//System.out.println("가로가 " + d1.width + "이고 세로가 " + 
		//	d1.height + "인 사각형의 넓이는 " + d1.calcArea());
		System.out.println("도형의 넓이는 " + d1.calcArea());

		Rect r = (Rect) d1;
		System.out.println("가로가 " + r.width + "이고 세로가 " + r.height + "인 사각형의 넓이는 " + r.calcArea());

		Circle c = (Circle) d1;
		System.out.println("반지름이 " + c.radius + "인 사각형의 넓이는 " + r.calcArea());
	}
}
---------- run ----------
가로가 4이고 세로가 3인 사각형의 넓이는 12.0이고 둘레는 14.0입니다.
가로가 7이고 세로가 5인 사각형의 넓이는 35.0이고 둘레는 24.0입니다.
반지름이 4인 원의 넓이는 50.26548245743669이고 둘레는 25.132741228718345입니다.
반지름이 6인 원의 넓이는 113.09733552923255이고 둘레는 37.69911184307752입니다.
도형의 넓이는 12.0
가로가 4이고 세로가 3인 사각형의 넓이는 12.0
Exception in thread "main" java.lang.ClassCastException: Rect cannot be cast to Circle
	at MatheMatics.main(MatheMatics.java:58)

 

                                                      1번            ------------>    2번 ----------------> 3번 순으로 생성

 

Heap

Object

(최상위클래스)

Dohyung

calcArea()

calcRound()

Rect

info()

Stack

 

d1

r

 

****

-Dohyung d1 = new Dohyung();

error? 추상클래스는 자신의 생성자로 객체 생성 할 수 x

 

-Dohyung d1 = new Rect(); // 추상클래스는 하위클래스를 참조해서 객체를 생성한다.

d1.info(); // error : 도형클래스에는 info가 없기 때문에 에러

 

-Rect r = (Rect) d1; //d1을 Rect로 변환하면 대입 가능하다.

 

-Circle c = (Circle) d1;

error ? Circle은 객체가 만들어지지 않았기 때문

 

 

 

(1) 상속(Inheritance)

 

효과)

- 부모 클래스를 재사용해서 자식 클래스를 빨리 개발할 수 있다.

- 반복된 코드의 중복을 줄여준다.

- 유지 보수의 편리성을 제공해 준다.

- 객체의 다형성을 구현할 수 있다.

 

제한)

- 부모 클래스의 private 접근을 갖는 필드와 메소드는 제외된다.

- 부모 클래스가 다른 패키지에 있을 경우, default 접근을 갖는 필드와 메소드는 제한된다.

- 자식 클래스는 부모 클래스의 필드와 메소드를 사용 or 자신의 필드와 메소드를 추가하여 사용할 수 있지만, 부모 클래스는 자식 클래스의 필드와 메소드를 사용할 수 x (only 자신의 필드와 메소드만 사용 가능)

 

1.상위클래스의 변수, 메소드를 하위클래스에서 사용 가능

 

2.형식) extends keyword 사용 : 자식 클래스가 부모 클래스를 선택해서 물려받음

하위 sub 상위 super

자식 child 클래스 부모 parent 클래스

접근제어자 class ClassName extends ClassName {

 

}

 

3.클래스는 단일 상속만 가능 (다중 상속 불가능, 계층적 상속 구조 가능)

 

4.모든 클래스의 최상위 클래스는 Object이다.

--------> Object의 메소드는 모든 클래스에서 사용 가능하다.

 

5.상위 클래스의 field, method는 상속된다.

( but, 생성자, private field & method는 상속되지 x)

 

6.method의 overriding (재정의) vs overloading (다중정의) ***************************

: 상위 클래스가 가진 메소드를 하위 클래스에 적합하게 변경 (재정의하는 작업)

: 상위 클래스의 메소드와 반드시 형식 일치 (단, 접근제어자는 넓은 의미로 변경 가능)

> public을 default나 private으로 수정할 수 없다.

> 반대로 default는 public으로 수정할 수 있다.

> 하위 클래스가 상위 클래스의 메소드를 '올라타다' (override)

(but, 상위 클래스의 메소드가 사라지는 것은 아님!!!!!)

 

* @Override 어노테이션 -- 다형성에서 많이 사용**

(개발자가 메소드 이름의 철자를 잘못 입력한 경우, 매개변수에 엉뚱한 값을 넣은 경우, 리턴타입에 잘못된 타입을 입력한 경우... 올바르게 부모 메소드를 재정의 하도록 도와주는 용도 )

> 컴파일러에게 부모 클래스의 메소드 선언부와 동일한지 검사하도록 지시한다.

- 잘못된 경우가 있다면, 컴파일 오류를 출력한다.

> 정확한 메소드 재정의를 위해 @Override를 붙여주는 것이 좋다.

 

효과)

> 부모 메소드는 숨겨지는 효과 > 재정의된 자식 메소드가 실행되기 때문에

 

7. this, super : 자기 객체 안에서만 사용가능, 객체 밖에서는 사용 x

super() : 자식 생성자의 첫줄에서만 가능

: 상위클래스(부모 클래스)의 생성자 호출 (하위 클래스의 생성자에 생략되어 있음)

: 부모 클래스에 기본 생성자(default)가 없다면 필수적으로 자식 클래스의 생성자에서 부모 생성자 super(매개변수)를 호출하여 작성해야 한다!!!!

**this(), super() 같이 못 씀!!!!!

 

Q. 자식 객체를 생성하면 부모 객체도 생성되는가?

> 자식 객체를 생성할 때, 부모 객체부터 생성되고 -> 자식 객체가 생성된다.

> 부모 생성자가 호출 완료되고, 자식 생성자가 나중에 호출 완료된다. --> 부모 객체를 초기화하는 역할

 

* eclipse에서 사용 : Source에서 Override/implement Methods...클릭

or

ctrl+space바 (현재 상속받고 있는 메소드들이 나온다.)

 

8.

- is a : 상속 관계 (~이다/ 자동차 - 트럭, 택시....)

import java.awt.*;

public class IsATest extends Frame { 
	
	//Frame은 창이 출력되기 때문에 상속관계
	Button b = new Button("눌러주세요!!"); //처음부터 글자 출력 (버튼은 포함관계)

	public IsATest(){
		super("Is A Test!!!!");
		//setTitle("Is A Test!!!!");//제목표시줄에 입력하기
		setLayout(new FlowLayout());
		//b.setLabel("눌러주세요");
		add(b);
		setBackground(Color.cyan);
		setSize(400,300);
		setLocation(300,200);
		setVisible(true);
	}
	public static void main(String[] args) {
		new IsATest();
	}
}

- has a : 포함 관계 (~포함된다/ 엔진,핸들....)

import java.awt.*;

public class HasATest {

	Frame f = new Frame("Has A Test!!!!"); //처음부터 제목표시줄에 타이틀 출력
	Button b = new Button("눌러주세요"); //처음부터 글자 출력

	public HasATest(){
		//f.setTitle("Has A Test!!!!");//제목표시줄에 입력하기
		f.setLayout(new FlowLayout());
		//b.setLabel("눌러주세요");
		f.add(b);
		f.setBackground(Color.orange);
		f.setSize(400,300);
		f.setLocation(300,200);
		f.setVisible(true);
	}
	public static void main(String[] args) {
		new HasATest();
	}
}

 

******9.다형성 : 하위 클래스를 참조하여 상위 클래스의 객체를 생성할 수 있다.(추상클래스, 인터페이스에서 엄청 중요!!!!)

Car car = new Car();

Car car = new Taxi();

> 인터페이스 클래스 자체가 데이터 타입이 될 수 있다!!!!!

 

- 주석 : 컴파일 할 때 빼고 실행된다는 의미,

 

- 어노테이션(Annotation) : 프로그램에게 추가적인 정보를 제공해주는 주석의 일종,

*자바5부터 나옴* : 상황에 따라 다양한 의미가 있다.(자바에서는 @Override 정도만 알기!!)

용도)

① 컴파일러에게 코드 작성 문법 에러를 체크하도록 정보를 제공한다.

ex) 메소드가 재정의 되었는지 확인, 내가 지금 작성한 코드가 부모클래스에 있는 메소드인지 확인 (@Override)

② 소프트웨어 개발 툴이 빌드나 배치시 코드를 자동으로 생성할 수 있도록 정보를 제공

ex) XML 설정 파일을 자동 생성하거나 배포를 위한 JAR 압축 파일을 자동 생성

③ 실행시 특정 기능을 실행하도록 정보를 제공

ex) 객체가 어플리케이션 내부에서 해야 할 역할을 정의(서블릿, 컨트롤러....)

public class Car{
	
	String carName; 
	String carColor;
	String maker;
	int speed;

	public Car() { 
		this ("아반떼", "흰색", "현대");
	}
	

	public Car(String carName) {  
		this (carName, "흰색", "현대");
	}

	
	public Car(String carName, String carColor) { 
		this(carName,carColor,"현대");
	}
	
	
	public Car(String carName, String carColor, String maker) { 
		this.carName = carName;
		this.carColor = carColor;
		this.maker = maker;
	}

	void speedUp() { 
		speed += 10;
	}

	int speedUp(int speed) { 
		this.speed += speed;
		return this.speed;
	}

	void speedDown() {
		speed -= 10;
		if(speed < 0)	
			stop(); 
	}

	void stop() {
		speed = 0;
	}

	@Override  //annotation : 자바에서는 override만 기억하면 된다. 상황에 따라 다름, @Override는 오타 잡을 때 등에 사용됨
	public boolean equals(Object obj){ //반드시 public을 붙여줘야 한다.
		boolean flag = false; //초기화
		Car car = (Car) obj; //Car타입으로 형변환
		if (carName == car.carName){
			flag = true;
		}
		return flag;
	}

	@Override
	public String toString(){ //객체의 문자열 표현을 반환한다.
		return maker + "에서 만든 " + carColor + " " + carName;
	}
}
public class Taxi extends Car{ //Taxi는 Car라는 클래스를 상속 받겠다라는 의미
	
	int price;

	public Taxi(){ //기본요금
		price = 3800;
	}

	public Taxi(String carName, String carColor, String maker) { 
		super(carName, carColor, maker);

	}
	
	int calculatePrice(int km){ //km당 300원
		return price + (km * 300);
	}

	@Override
	public int speedUp(int speed){
		speed = super.speedUp(speed);
		if (speed > 200){
			this.speed = 200;
		}
		return this.speed;
	}

	@Override
	public String toString(){ 
		return super.toString() + "택시   속도 : " + speed; //상위가 가진 toString을 호출해라
	}
}
public class TaxiUser {
	public static void main(String[] args) {
		Taxi t1 = new Taxi();
		//t1.carName = "K7"; 
		//System.out.println(t1.info()); //결과 : 현대에서 만든 흰색 아반떼 > 인자값이 없는 Car 기본 생성자 호출하기 때문에
		System.out.println(t1.toString()); //Taxi@15db9742 > Taxi 타입 @ 주소값 -- but,실제로는 별로 필요 없는 메소드..따라서 overriding으로 재정의 해주기
		t1.speedUp(300);
		System.out.println(t1);

		Taxi t2 = new Taxi("K5", "감홍색", "기아"); // 생성자는 상속이 안되기 때문에 새로 생성자 만들어 줘야 함.
		//System.out.println(t2.info());
		System.out.println(t2);// toString은 t2만 입력해도 ok

		Taxi t3 = new Taxi("K5", "감홍색", "기아");
		
		//Object의 override하기 전 equals method는 주소값을 비교한다(결과 : 다른 택시다.)
		//override 후(Car 클래스에) 차이름이 같으면 true
		if (t2.equals(t3)){ //t2랑 t3랑 같나?
			System.out.println("t2와 t3는 같은 택시다.");
		} else {
			System.out.println("t2와 t3는 다른 택시다.");
		}
	}
}

ex)

        자동차 (이름, 색상, 제조사, 속도, 가속(), 감속(), 정지())

 

          택시 버스 트럭

필드    요금 승객수 중량

               정원수(45)

 

메소드 요금계산 승차() 상차()

하차() 하차()

public class Bus extends Car{
	
	private int passenger; //승객수
	int totalPassenger = 45; //정원수(45) - 처음 만들어질 때부터 정원 고정


	public Bus(String carName, String carColor, String maker) { //외부에서 값 입력되도록
		super(carName, carColor, maker); 
		}

	int getOn(int passenger){
		this.passenger += passenger;
		if (this.passenger > 45){ //= if(this.passenger > totalPassenger)
			this.passenger = 45; // = this.passenger = totalPassenger
		}
		
		return this.passenger;
	}

	int getOff(int passenger){
		this.passenger -= passenger; 
		if(this.passenger<0) //빼먹음..
			this.passenger = 0;//빼먹음..
		return this.passenger;
	}
	
	//void info(){
		@Override
		public String toString(){ 
		//System.out.println("현재 탑승인원 : " + passenger + "명, 가능인원 : " + (totalPassenger-passenger) + "명");
		return "현재 탑승인원 :"  + passenger + "명, 가능인원 : " + (totalPassenger-passenger) + "명";
		}
	
	@Override
	public int speedUp(int speed){ //상위 클래스 메소드 선언부 그대로 복사(동일해야 함)
		speed = super.speedUp(speed); //this.speed = speed;(x) 
		if (speed > 110){
			this.speed = 110;
		}
		return this.speed;
	}
}
public class BusUser {
	public static void main(String[] args) {
		Bus bus1 = new Bus("기아","알록달록","에어로");
		
		//기아에서 만든 알록달록 에어로버스
		System.out.println(bus1.carName + "에서 만든 " + bus1.carColor + " " + bus1.maker + "버스");
		
		//현재 탑승인원 : 0명, 가능인원 : 45명
		System.out.println(bus1);
		
		//첫번째 정류장에서 8명 탑승
		bus1.getOn(8);
		
		//현재 탑승인원 : 8명, 가능인원 : 37명
		System.out.println(bus1);

		//두번째 정류장에서 10명 탑승, 3명 하차
		bus1.getOff(3); //하차를 먼저 해야 가능인원을 계산할 수 있다.
		bus1.getOn(10);

		//현재 탑승인원 : 15명, 가능인원 : 30명
		System.out.println(bus1);

		//세번째 정류장에서 30명 탑승, 8명 하차
		bus1.getOff(8);
		bus1.getOn(30);
	

		//현재 탑승인원 : 37명, 가능인원 : 8명
		System.out.println(bus1);

		//네번째 정류장에서 20명 탑승, 10명 하차
		bus1.getOff(10);
		bus1.getOn(20);
		

		//현재 탑승인원 : 45명, 가능인원 : 0명 // 내리고 타야 됨!!! 순서 중요~~
		System.out.println(bus1);

		//버스가 120으로 진행
		//버스 속도는 110입니다. 제한속도
		bus1.speedUp(120);
		System.out.println("버스속도 : " + bus1.speed);
	}
}
---------- run ----------
기아에서 만든 알록달록 에어로버스
현재 탑승인원 :0명, 가능인원 : 45명
현재 탑승인원 :8명, 가능인원 : 37명
현재 탑승인원 :15명, 가능인원 : 30명
현재 탑승인원 :37명, 가능인원 : 8명
현재 탑승인원 :45명, 가능인원 : 0명
버스속도 : 110

(1) TV프로그램

/*
TV의 최대 채널이 999이고, 볼륨은 99입니다.
class : TV
field : 
	-power
	-channel 0으로 시작
	-volume  0으로 시작
	-maker
	-inch
constructor
	-args가 2개(maker랑 inch)
method :
	-powerOn
	-PowerOff
	--------------volume은 +1, -1씩 증감
	-volumeUp
	-volumeDown
	--------------channel은 +1, -1씩
	-channelUp
	-channelDown
	--------------channel은 x로 변경 (한방에 이동)
	-changeChannel
*/

public class TV{
	boolean power;
	int channel;
	int volume;
	String maker;
	int inch;
	
	
	
	TV(String maker,int inch){ //명확히 밝혀주는 것이 좋다.
		power = false;
		channel = 0;
		volume = 0;
		this.maker = maker;
		this.inch = inch;
	}

	void powerOn() {  //전원만 켜면 그만이기 때문에 리턴값이 없다.
		power = true;
		//System.out.println("TV 전원을 켜세요!!");
	}
	
	void powerOff() {
		power = false;
		//System.out.println("TV 전원을 끄세요!!");
	}

	/*void volumeUp(int volume) { //여기서 for문을 쓰면 비효율적! 사람이 리모컨을 누를 때마다, 변경되는 것이기 때문에 고유값으로 만드는 것보다 실행 클래스에서 만드는 것이 좋다.
		this.volume = volume;
			if (power){
			for (int i=0;i<100 ;i++ )
			volume ++;
			} else {
				System.out.println("TV 전원을 켜세요!!");
			}
	}

	void volumeDown(int volume) {
		this.volume = volume;
			for (int i=0;i<100 ;i++ )
			volume --;
			if (volume<0){
			volume = 0;
			}
		}	
		
	void channelUp(int channel) {
		this.channel = channel;
			if (power){
			for (int i=0;i<1000 ;i++ )
			channel ++;
			} else {
				System.out.println("TV 전원을 켜세요!!");
			}
	}

	void channelDown(int channel) {
			this.channel = channel;
			for (int i=0;i<1000 ;i++ )
			channel -= 1;
			if (channel<0){
				channel = 0;
			}
	}*/

	void volumeUp(){
		if (checkPower())
			volume ++;
	}
	
	void volumeDown(){
		if (checkPower()){
			if (volume <0){
				volume = 0;
			} else {
				volume --;
			}
		}
	}

	void channelUp(){
		if (checkPower()){
			if (channel > 999){
				channel = 1;
				
			}
			channel ++; 
		}
	}
	
	void channelDown(){
		if (checkPower()){
			if (channel < 1){
				channel = 999;
				channel --;
			}
			
		}
	}

	int changeChannel(int channel) { //현재 채널을 갖고 오고 싶다면 int로 리턴타입 잡기
		if (!checkPower()){//false라면
			return -1; //말도 안되는 더미값(없는 채널)로 리턴하기 , break는 반복문일 때만 사용~~
		}
		if (channel > 999){
			return this.channel; //현재 자신의 채널로 남아 있기
		}
		this.channel = channel;
		return this.channel;
	}

	boolean checkPower() {
		if (!power){
			System.out.println("TV 전원을 켜세요!!!");
			return false; 
		}
		return true;
	}

	void tvInfo(){ //중복을 줄이기 위해서..
		if (power)
		System.out.println("tv1의 채널 : " + channel + "번이고 볼륨은 " + volume + "입니다.");
	}
}
public class TvWatcher {  
	public static void main(String[] args) {
	//tv1의 객체 생성.
	TV tv1 = new TV("LG",75); //기본생성자가 생성되지 않았다는 오류가 나오니까 ()안에 값 넣어주기!

	//print : LG에서 만든 75인치 TV
	System.out.println(tv1.maker + "에서 만든 " + tv1.inch + "인치 TV");
	
		System.out.println("channel을 11번으로 변경!!!"); 
		int ch = 11; // 변수를 잡는 것이 좋다.
        int channel = tv1.changeChannel(ch); //리턴값이 있는 메소드 호출
		// print : TV전원을 켜세요!! ----TV의 고유속성이기 때문에 class에 만들기
        System.out.println("channel을 " + ch + "번으로 변경!!!");		

		
		System.out.println("channel을 3회 증가");
		int cnt = 3;
		for (int i=0;i<cnt ;i++ ){
			tv1.channelUp();
		}
		
		// print : TV전원을 켜세요!!

		System.out.println("volume을 10회 증가!!");
		cnt = 10;
		for (int i=0;i<cnt ;i++ ){
			tv1.volumeUp();
		}
		// 전원 on
		tv1.powerOn();

		System.out.println("channel을 11번으로 변경!!!");
			ch = 11;
			channel = tv1.changeChannel(ch);
		// print : 현재 tv의 채널은 11번이고 볼륨은 0입니다.
		tv1.tvInfo();

		
		System.out.println("volume을 15회 증가!!!");
		cnt = 15;
		for (int i=0;i<cnt ;i++ ){
			tv1.volumeUp();
		}
		// print : 현재 tv의 채널은 11번이고 볼륨은 15입니다.
		tv1.tvInfo();

		System.out.println("channel을 1001번으로 변경!!!");
			ch = 1001;
			channel = tv1.changeChannel(ch);
			tv1.tvInfo();
		// print : 현재 tv의 채널은 11번이고 볼륨은 15입니다.
		
		System.out.println("volume을 25회 감소!!!");
		cnt = 25;
		for (int i=0;i<cnt ;i++ ){
			tv1.volumeDown();
		}
		tv1.tvInfo();
		// print : 현재 tv의 채널은 11번이고 볼륨은 0입니다.
		

		System.out.println("channel을 999번으로 변경!!!");
			ch = 999;
			channel = tv1.changeChannel(ch);
		// print : 현재 tv의 채널은 999번이고 볼륨은 0입니다.
		tv1.tvInfo();

		System.out.println("channel을 3회 증가!!!");
		cnt = 3;
		for (int i=0;i<cnt ;i++ ){
			tv1.channelUp();
		}
		// print : 현재 tv의 채널은 3번이고 볼륨은 0입니다.
		tv1.tvInfo();

		// 전원 : off
		tv1.powerOff();
		
		System.out.println("channel을 7번으로 변경!!!");
		ch = 7;
		channel = tv1.changeChannel(ch);
		
		// print : TV전원을 켜세요!!
		tv1.tvInfo();

	}
}
---------- run ----------
LG에서 만든 75인치 TV
channel을 11번으로 변경!!!
channel을 11번으로 변경!!!
TV 전원을 켜세요!!!
channel을 3회 증가
TV 전원을 켜세요!!!
TV 전원을 켜세요!!!
TV 전원을 켜세요!!!
volume을 10회 증가!!
TV 전원을 켜세요!!!
TV 전원을 켜세요!!!
TV 전원을 켜세요!!!
TV 전원을 켜세요!!!
TV 전원을 켜세요!!!
TV 전원을 켜세요!!!
TV 전원을 켜세요!!!
TV 전원을 켜세요!!!
TV 전원을 켜세요!!!
TV 전원을 켜세요!!!
channel을 11번으로 변경!!!
tv1의 채널 : 11번이고 볼륨은 0입니다.
volume을 15회 증가!!!
tv1의 채널 : 11번이고 볼륨은 15입니다.
channel을 1001번으로 변경!!!
tv1의 채널 : 11번이고 볼륨은 15입니다.
volume을 25회 감소!!!
tv1의 채널 : 11번이고 볼륨은 0입니다.
channel을 999번으로 변경!!!
tv1의 채널 : 999번이고 볼륨은 0입니다.
channel을 3회 증가!!!
tv1의 채널 : 3번이고 볼륨은 0입니다.
channel을 7번으로 변경!!!
TV 전원을 켜세요!!!

(2) 스타크래프트 소스

/*
class : Marine
field 
	-hp (100)
	-power (10) //한 번 때리면 hp가 10 감소
	-mode (0:일반모드, 1:흥분모드)
method
	-attack : 적 체력 감소
	-changeMode 
	 -- 흥분모드 변경시 : power25 증가, 내 체력 : 35감소
	 -- 내 체력이 50미만이면 흥분모드변경 불가 

*/

public class Marine {
	int hp;
	int power;
	int mode;

	Marine (){
		hp = 100;
		power = 10;
		mode = 0;
	}

	void attack(Marine enemy){ //call by references라고 한다.
		enemy.hp -= power; // 적의 hp를 감소시키기 위해서
	}
	
	void changeMode(){
		if (hp < 50){
			System.out.println("체력이 50미만이므로 모드 변경 불가능!!");
			return;
		}
		mode = 1;
		hp -= 35;
		power = 25; //power += 25;아닌가????????
		
	}
	/*void info() {
		 System.out.println(");
	} */ //hp 필드명이 똑같기 때문에 나와 컴을 둘 다 표현할 수 있는 방법이 없다. 따라서, 여기에 사용 x

	String status() {//die를 찍기 위해서
		return hp <= 0 ? "die" : hp + ""; //(숫자+문자열 = 문자열), 삼항연산자 사용
	}
}
public class StarCraft{
	public static void main(String[] args) {
		//내마린(my), 컴마린(com) 생성
		Marine my = new Marine();
		Marine com = new Marine();

		//1. 체력 >> 나 : 100, 컴 : 100
		System.out.println("체력 >> 나 : " + my.status() + ", 컴 : " + com.status());
		
		System.out.println("내가 컴을 2회 공격!!!!!!"); 
		// 2. 체력 >> 나 : 100, 컴 : 80
		int cnt = 2;
		for (int i=0;i<cnt ;i++ )
			my.attack(com); //my.attack()만 썼을 경우 내 체력을 감소시키고 있다... com을 공격하라
		System.out.println("체력 >> 나 : " + my.status() + ", 컴 : " + com.status());
		

		System.out.println("컴이 나를 3회 공격!!!!!!");
		//3. 체력 >> 나 : 70, 컴 : 80
		cnt = 3;
		for (int i=0;i<cnt ;i++ )
			com.attack(my); //컴이 나를 공격한다. 
		System.out.println("체력 >> 나 : " + my.status() + ", 컴 : " + com.status());

		System.out.println("내마린을 흥분모드로 변경!!!!!!");
		// 4. 체력 >> 나 : 35, 컴 : 80
		my.changeMode();
		System.out.println("체력 >> 나 : " + my.status() + ", 컴 : " + com.status()); //changeMode 완성시키러 gogo~

		System.out.println("내가 컴을 2회 공격!!!!!!");
		// 5. 체력 >> 나 : 35, 컴 : 30
		cnt = 2;
		for (int i=0;i<cnt ;i++ )
			my.attack(com);
		System.out.println("체력 >> 나 : " + my.status() + ", 컴 : " + com.status());


		System.out.println("컴이 나를 3회 공격!!!!!!");
		// 6. 체력 >> 나 : 5, 컴 : 30
		cnt = 3;
		for (int i=0;i<cnt ;i++ )
			com.attack(my); 
		System.out.println("체력 >> 나 : " + my.status() + ", 컴 : " + com.status());

		System.out.println("내마린을 흥분모드로 변경!!!!!!");
		// 7. 체력이 50미만이므로 모드 변경 불가능!!
		my.changeMode();
		System.out.println("체력 >> 나 : " + my.status() + ", 컴 : " + com.status());

		System.out.println("내가 컴을 2회 공격!!!!!!");
		// 8. 체력 >> 나 : 5, 컴 : die
		cnt = 2;
		for (int i=0;i<cnt ;i++ )
			my.attack(com);
		System.out.println("체력 >> 나 : " + my.status() + ", 컴 : " + com.status());
	}
}

/* 사용하기
Call by value
Call by Reference
*/
---------- run ----------
체력 >> 나 : 100, 컴 : 100
내가 컴을 2회 공격!!!!!!
체력 >> 나 : 100, 컴 : 80
컴이 나를 3회 공격!!!!!!
체력 >> 나 : 70, 컴 : 80
내마린을 흥분모드로 변경!!!!!!
체력 >> 나 : 35, 컴 : 80
내가 컴을 2회 공격!!!!!!
체력 >> 나 : 35, 컴 : 30
컴이 나를 3회 공격!!!!!!
체력 >> 나 : 5, 컴 : 30
내마린을 흥분모드로 변경!!!!!!
체력이 50미만이므로 모드 변경 불가능!!
체력 >> 나 : 5, 컴 : 30
내가 컴을 2회 공격!!!!!!
체력 >> 나 : 5, 컴 : die

 

(3) call by value : primitive type일때, 메소드의 인자값으로 전달되면 값이 전달

call by reference : reference type일때, 메소드의 인자값으로 전달되면 주소가 전달, 서로 관계가 있다.

 

public class RefValue {
	int x;

	void changeX(int x) {
		x = 100;
	}

	void changeRv(RefValue rv) {
		rv.x = 777;
	}
}
public class ValueTest {
	public static void main(String[] args) {
		RefValue rv = new RefValue();

		int x = 25; //RefValue 클래스의 x와는 전혀 다른 객체
		System.out.println("1. x : " + x); // 25
		//call by value : primitive type일때, 메소드의 인자값으로 전달되면 값이 전달
		rv.changeX(x);
		System.out.println("2. x : " + x); // 25
		
		System.out.println("3. rv.x : " + rv.x);
		//call by reference : reference type일때, 메소드의 인자값으로 전달되면 주소가 전달, 서로 관계가 있다.
		rv.changeRv(rv);
		System.out.println("4. rv.x : " + rv.x);
	}
}
---------- run ----------
1. x : 25
2. x : 25
3. rv.x : 0
4. rv.x : 777

 

(4) getter, setter : 클래스를 선언할 때 필드는 일반적으로 private 접근 제한을 한다. (public 사용)

- getter의 필요성 : 때에 따라서 외부에서 필드를 읽을 수 있도록 하기 위해서 필요로 한다.(읽기전용)

public 리턴타입 getFieldName(), boolean일 때는public boolean isFieldName()

- setter의 필요성 : 외부에서 엉뚱한 값으로 변경할 수 없도록 한다.(올바른 값만 저장 - 유효성 검사)

public void setFieldName(매개변수) : 매개변수의 타입은 필드타입과 동일 (void : 값만 변경하고 끝나면 되니까)

 

Q. getter와 setter 모두 사용하면 private 필드를 잡은 의미가 없다. 따라서 필드를 읽기 전용만 나타내고 싶다면?

>> getter만 사용!!

Q. setter가 꼭 필요한 경우는?

>> 유효성 검사가 필요한 경우!! ex) speed 등을 음수(-) 값이 올 수 없도록, 0으로 설정하는 경우

 

-- eclipse에서 private 필드를 선언한 후, Source에서 Generate Getter and Setters...클릭

 

/*
id
name
pass
age
*/


public class Member {

	private String id;
	private String name;
	private String pass;
	private int age;
	private boolean check;

	//getter : 가져와라 /setter : 지정 (항상 public)
	public String getId() { //String : 리턴타입
		return id; //id를 리턴해라
	}

	public void setId(String id) { 
		this.id = id;
	}

	public String getName() { 
		return name;
	}

	public void setName(String name) { 
		this.name = name;
	}

	public String getPass() { 
		return pass;
	}

	public void setPass(String pass) { 
		this.pass = pass;
	}

	public int getAge() { 
		return age;
	}

	public void setAge(int age) { 
		this.age = age;
	}

	public boolean isCheck() { //리턴타입이 boolean일때는, get이 아닌 is로 붙인다.
		return check;
	}

	public void setCheck(boolean check) { 
		this.check = check;
	}
}
public class Site {
	
	int register(Member member) { //method호출
		//db랑 연동해서 insert...
		System.out.println(member.getId());
		System.out.println(member.getName());
		System.out.println(member.getPass());
		System.out.println(member.getAge());
		System.out.println(member.isCheck());
		return 1;
	}

	public static void main(String[] args) {
		//java2, 홍길동, 1234, 25
		Site site = new Site();//객체 생성
		Member member = new Member(); //call by reference
		//member.id = "java2"; 
		member.setId("java2");
		member.setName("홍길동");
		member.setPass("1234");
		member.setAge(25);
		member.setCheck(true);
		int cnt = site.register(member);
	}

 

(1) 배열의 길이 : 직접 입력하지 않고 코드에서 배열의 길이를 얻을 수 있다.

>> int num = intArray.length; (주로 for문의 조건식에서 사용)

 

public class ArrayLengthExample {
	public static void main(String[] args) {
		int[] scores = {83,90,87};

		int sum = 0;
		for (int i=0;i<scores.length ;i++ ){ //i는 인덱스번호로 주로 사용
			sum += scores[i];
		}
		System.out.println("총합 : " + sum);

		double avg = (double) sum/scores.length;
		System.out.println("평균 : " + avg);
	}
}
---------- run ----------
총합 : 260
평균 : 86.66666666666667

- 최댓값을 구하라 (for문 이용)

public class Exercise07 {
	public static void main(String[] args){
		int max = 0;
		int[] array = {1,5,3,8,2};
		for (int i=0;i<array.length ;i++){
			if (max<array[i]){
				max = array[i];//0과1를 비교해서 큰 값인 1을 max에 대입,1과 5를 비교해서 5를 대입...
			}
		}
		System.out.println("max: " + max);
	}
}
---------- run ----------
max: 8

 

(2) 다차원 배열 : 1차원 배열을 이용해서 2차열 배열을 구현한다.

>> int[][] scores = new int [행의 수][열의 수] // 새로운 int 배열을 만들어라

scores[0][0] = 3; // 0행 0열에 3을 대입해라

>> int[][]scores = {{95,80},{92,96}};

int score = scores[0][0]; //결과 : 95

int score = scroes[1][1]; // 96

>> String[][] names = {{"김빛나","홍길동"},{"가나다","고구마"}};

String name = names[0][1]; //홍길동

 

public class ArrayExample{
	public static void main(String[] args) {
		int[][] mathScores = new int[2][3];
		for (int i=0;i<mathScores.length ;i++ ){ //0,1
			for (int k=0;k<mathScores[i].length ;k++ ){ //0,1,2
				System.out.println("mathScores[" + i + "][" + k + "] = " + mathScores[i][k] );
			}
		}
		System.out.println();

		int[][] englishScores = new int[2][]; 
		englishScores[0] = new int[2];
		englishScores[1] = new int[3];
		for (int i=0;i<englishScores.length ;i++ ){
			for (int k=0;k<englishScores[i].length ;k++ ){ 
				System.out.println("englishScores[" + i + "][" + k + "] = " + englishScores[i][k] );
			}
		}
		System.out.println();

		int[][] javaScores = {{95,80},{92,96,80}};
		for (int i=0;i<javaScores.length ;i++ ){
			for (int k=0;k<javaScores[i].length ;k++ ){ 
				System.out.println("javaScores [" + i + "][" + k + "] = " + javaScores[i][k] );
			}
		}
	}
}
---------- run ----------
mathScores[0][0] = 0
mathScores[0][1] = 0
mathScores[0][2] = 0
mathScores[1][0] = 0
mathScores[1][1] = 0
mathScores[1][2] = 0

englishScores[0][0] = 0
englishScores[0][1] = 0
englishScores[1][0] = 0
englishScores[1][1] = 0
englishScores[1][2] = 0

javaScores [0][0] = 95
javaScores [0][1] = 80
javaScores [1][0] = 92
javaScores [1][1] = 96
javaScores [1][2] = 80

- 전체 합과 평균값을 구하라 (중첩 for문 이용)

public class Exercise08 {
	public static void main(String[] args) {
		int[][] array = {{95,86},{83,92,96},{78,83,93,87,88}};

		int sum = 0;
		double avg = 0.0;

		int count = 0; //**
		for (int i=0;i<array.length ;i++ ){
			for (int k=0;k<array[i].length ;k++ ){//0일떄,1일때,2일때
				sum += array[i][k]; //i와 k 모두 입력해줘야 함
				count ++; //for문이 다 돌면 10번 카운팅
			}
		}

		avg = (double)sum / count;

		System.out.println("sum : " + sum);
		System.out.println("avg : " + avg);
	}
}
---------- run ----------
sum : 881
avg : 88.1

(3) 객체를 참조하는 배열

public class ArrayExample0 {
	public static void main(String[] args) {
		String[] strArray = new String[3];
		strArray[0] = "Java";
		strArray[1] = "Java";
		strArray[2] = new String("Java"); // 동일 문자열이지만, 새로운 객체를 생성하면 같은 객체 참조 x

		System.out.println(strArray[0] == strArray[1]); //같은 객체를 참조?
		System.out.println(strArray[0] == strArray[2]); 
		System.out.println(strArray[0].equals(strArray[2]));//.equals() 동일 문자열?
	}
}
---------- run ----------
true
false
true

 

(4) 배열 복사

>> 배열은 한 번 생성되면 크기를 변경할 수 없다!!!

>> 프로그램 도중 더 많은 저장이 필요하다고 한다면? 큰 배열을 새로 만들고, 이전 배열을 복사해야 한다.

 

*3가지 방법*

1. for문을 이용하여 복사

public class ArrayCopyExample1 {
	public static void main(String[] args) {
		int[] oldIntArray = {1,2,3};
		int[] newIntArray = new int[5];

		for (int i=0;i<oldIntArray.length ;i++ ){
			newIntArray[i] = oldIntArray[i];//새로운 배열에 이전 배열을 복사하여 대입
		}

		for (int i=0;i<newIntArray.length ;i++ ){
			System.out.print(newIntArray[i] + ",");
		}
	}
}
---------- run ----------
1,2,3,0,0, //이전 배열 값 1,2,3이 복사되고 0은 default값이 출력

 

2. System.arrayCopy() 메소드를 이용하여 복사

>>System.arrayCopy(이전배열,이전배열의 복사시작 위치,새로운배열,새로운배열의붙여넣기할위치,몇개복사)

 

public class ArrayCopyExample {
	public static void main(String[] args) {
		String[] oldStrArray = {"java","array","copy"};
		String[] newStrArray = new String[5];

		System.arraycopy(oldStrArray,0,newStrArray,0,oldStrArray.length);

		for (int i=0;i<newStrArray.length ;i++ ){
			System.out.print(newStrArray[i] + ",");
		}
	}
}
---------- run ----------
java,array,copy,null,null,

 

3. Arrays 클래스를 이용하여 복사 >> 추후에 공부....

 

(5) 향상된 for문 (자바 5부터 추가됨~)

>> 매번 for문을 작성하기 귀찮기 때문에 사용

>> 배열의 전체 값을 순차적으로 처리하고자 할 때 사용

 

public class AdvancedForExample {
	public static void main(String[] args) {
		int[] scores = {95,71,84,93,87};

		int sum = 0;
		for (int score : scores){ //항목의 개수만큼 반복
			sum += score;
		} 
		System.out.println("점수 총함 = " + sum);

		double avg = (double)sum/scores.length;
		System.out.println("점수 평균 = " + avg);

	}
}
---------- run ----------
점수 총함 = 430
점수 평균 = 86.0

+ Recent posts