1. 정의하는 방법

package annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Hello {
}

2. Annotation의 종류

- @Override

> 메소드가 override 되었는지 알려주는 역할을 한다. 생략이 가능하지만, 실수를 방지하기 위해서 생략하지 않는 것이 좋다.

 

- @Target 

> annotation이 적용 가능한 대상을 지정하는데 사용된다.

> METHOD, TYPE, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, LOCAL_VARIABLE, MODULE, PACKAGE, PARAMETHER, TYPE_PARAMETER, TYPE_USE에 사용할 수 있다고 한다.

 

- @Retention(RetentionPolicy.RUNTIME)

>  annotation이 유지되는 범위를 지정하는데 사용된다.

 

 3개의 레벨 순서 : SOURCE -> CLASS -> RUNTIME 

 

1. SOURCE : 소스코드에만 유지하겠다. 컴파일 하고 나면, 애너테이션이 없어진다.

(바이트 코드에 남아있지 않음!! 즉, 주석으로만 사용하겠다.)

ex) @Override

 

2. CLASS : 바이트 코드에 남겨두겠다. 컴파일시까지 유지됨

 

3. RUNTIME : reflection이 가능해진다.

Q. reflection이란?? 

- 객체를 통해 클래스에 대한 정보를 분석해 내는 프로그램 기법

 

package annotation;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@Hello
@RestController
public class HelloController{

    private static final String hello = "hello";

    @GetMapping(hello)
    public String hello(){
        return "hello";
    }
}

getAnnotatiions 메소드로 해당 클래스에 쓰인 annotation 정보들을 알아볼 수 있다.

package annotation;

import java.lang.annotation.Annotation;

public class HelloMain {

    public static void main(String[] args) {

        Annotation[] annotations = HelloController.class.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
    }
}
@annotation.Hello()
@org.springframework.web.bind.annotation.RestController(value=)

- @Inherited

> 상속받은 클래스에도 annotation이 유지된다는 뜻

 

- @Id

>

 

- @GeneratedValue

>

 

 

3. ServiceLoader

> interface 클래스를 만들어 놓고, 구현체는 누군지 모르는 상황에서.. jar 파일만 바꿔서 동작하게끔 하는 것!!

'STUDY' 카테고리의 다른 글

lambda  (0) 2021.03.07
JVM / Compile / run / javac / bite code / binary code / JIT / JDK / JRE  (0) 2021.01.18

 

1. JVM이란 무엇인가?

A Java virtual machine (JVM) is a virtual machine that enables a computer to run Java programs as well as programs written in other languages that are also compiled to Java bytecode. - wikipedia

자바 가상 머신은 컴퓨터가 자바 프로그램을 실행할 수 있도록 도와준다.

 

Q. JVM은 왜 필요한 것 일까?

A. 기계어는 하나의 언어가 아니기 때문이다.

컴퓨터, 정확히 말하자면 CPU가 이해할 수 있는 언어 기계어는 하나의 언어가 아니다.

CPU 제조사마다 다르기에 특정 프로그램 A를 X, Y, Z라는 각각 다른 컴퓨터 환경에서 실행하려면 각각의 제조사에 맞는 기계어를 알고 있어야 한다.

 

Q. 그렇다면 개발자는 모든 종류의 CPU에 맞는 기계어 패턴을 알고 있어야 할까?

하드웨어 엔지니어가 아닌 이상 일반적인 소프트웨어 엔지니어의 목표는 요구 사항을 충족하는 프로그램을 개발하는 것이다.

CPU 제조사마다 다른 기계어 패턴을 알 필요 없이 요구 사항을 충족하는 프로그램을 하나의 고급 언어로 작성하는 것이 이상적일 것이다.

 

자바 가상 머신이란 컴퓨터가 자바 프로그램을 실행할 수 있도록 도와준다.

결국 JVM은 자바 프로그램(바이트 코드)을 다양한 CPU 환경에서 이식성 문제없이 실행할 수 있도록 도와주는 가상 머신

 

2. 컴파일 하는 방법

자바 소스를 컴파일 및 실행하기 위해서는 기본적으로 아래의 두 프로그램이 필요하다.

javac.exe

java.exe

javac.exe는 자바 소스코드를 컴파일할 때 사용하는 프로그램이며 컴파일된 바이트 코드를 실행할 때 java.exe 사용

 

또한 javac.exe는 JDK, java.exe는 JRE에 포함되어 있기에 JDK과 JRE를 설치해야 하지만 과거와 다르게 요즘은 JDK에 JRE가 포함된 형태로 배포되고 있기에 JDK만 설치해도 무관

 

3. 실행하는 방법

java.exe 파일을 사용하여 바이트코드로 컴파일 된 .class 실행

단, 실행 시에는 소스 파일명의 확장자는 붙이지 않음

 

Q. java compile option

 

 

4. 바이트코드란 무엇인가

바이너리 코드

바이트코드

0과 1로 구성되어 있는 코드

C언어로 작성 된 .c 파일을 컴파일한 .obj 파일이 바이너리 코드

하지만 .obj 파일만으로는 실제 컴퓨터가 이해하여 실행할 수 없다. 이때 필요한 것이 링커로 링커는 여러 개의 코드와 데이터를 모아서 연결하여 메모리에서 실행 가능 한 파일로 만드는 역할을 한다.

위 과정이 모두 진행된 후 생성되는 실행 파일이 컴퓨터가 이해 할 수 있는 기계어로 구성

0과 1로 구성되어 있는 이진 코드이지만 바이너리 코드와 다르게 가상 머신이 이해할 수 있는 코드

사람에게 더 친숙한 고급언어보다는 덜 추상적이지만 기계어보다는 추상적이다.

컴퓨터가 이해 할 수 있는 기계어로 만들기 위해서는 인터프리터의 도움이 필요하다.

 

5. JIT(짓) 컴파일러란 무엇이며 어떻게 동작하는지

 

일반적으로 인터프리터 언어(python)보다는 정적 컴파일 언어(C)가 실행 속도가 더 빠르다고들 한다.

 

Q. why??

 

그 이유는 JIT 컴파일러의 목적을 보면 알 수 있다.

정적 컴파일 언어의 경우 컴파일에 시간이 오래 걸리는 반면 컴파일 후 결과물(.exe)은 CPU가 이해할 수 있는 '기계어'이기 때문에 실시간으로 번역하여 실행하는 인터프리터 언어보다 빠를 수 밖에 없다.

Java는 컴파일 언어이지만 동적 컴파일 언어이다.

CPU가 이해할 수 있는 기계언어가 아닌 JVM이 이해 할 수 있는 바이트 언어로 컴파일한 뒤 인터프리터에 의해 실시간으로 번역되어 실행된다.

JIT 컴파일러는 반복되어 사용되는 코드나 기계어로 변환 시 많은 리소스가 필요한 부분을 코드가 실행되는 과정(Just-In-Time)에 실시간으로 변환(기계어)하여 캐싱한다.

 

Java는 이러한 최적화 과정이 존재하기에 인터프리터 언어(Python) 보다 좋은 실행 성능을 낼 수 있다.

 

6. JVM 구성 요소

- JVM은 크게 클래스 로더 시스템(Class Loader),실행 엔진(Execution Engine), Runtime Data Area 나뉘어져 있다.

 

(1) 클래스 로더 시스템 : JRE의 일부로, 바이트코드를 실행할 때 class 객체를 메모리에 load하는 요소

자바 소스 프로그램이 컴파일되어 실행되기까지의 순서를 간략하게 확인

개발자가 자바 언어를 사용하여 프로그램 작성 .java

작성 한 프로그램을 컴파일 .class

프로그램 실행에 필요한 .class 파일들을 모두 읽어 연결

프로그램 실행 전 메모리 초기화 작업 진행

바이트 코드로 작성된 프로그램을 인터프리터가 기계어로 번역하여 실행

 

클래스 로더 시스템은 컴파일된 바이트코드들을 읽어 연결한 뒤 메모리에 저장하는 역할을 수행

내부적으로는 로딩, 링크, 초기화의 단계가 존재

클래스 로더 시스템 초기화 단계에서 전역 변수를 메모리에 할당하기 때문에 필요 이상으로 전역 변수를 남용할 경우 메모리 이슈를 겪을 수 있음

 

(2) 실행 엔진 : 메모리에 load된 바이트코드를 실행하는 역할

클래스 로더 시스템에 의하여 실행에 필요한 준비 과정이 완료되었다면 이제 인터프리터를 사용하여 바이트 코드를 번역하여 실행할 차례이다.

실행 엔진 내부적으로는 인터프리터, JIT 컴파일러, GC가 있다.

< 인터프리터 >

컴파일된 .class의 바이트코드를 실행하는 역할

< JIT 컴파일러 >

프로그램이 실행될 때 인터프리터가 바이트코드를 읽어 기계어로 번역하지만 프로그램에는 반복적으로 사용하는 코드가 존재한다.

반복적으로 사용되는 코드를 매 번 번역하는 것보다는 최초 1회만 번역하여 특정 저장소(캐시)에 저장 한 뒤 추가 참조가 필요할 때마다 불러온다면 성능 향상을 이끌어 낼 수 있을 것이다.

이 역할을 수행하는 것이 JIT 컴파일러이다.

< GC >

프로그램이 실행되면서 특정 데이터를 저장할 때 주로 메모리를 사용한다.

다양한 로직이 순차적으로 실행되다 보면 한정돼있는 메모리는 여러 데이터로 점령될 것이다.

더 이상 참조되지 않는 데이터를 정리하는 역할을 수행하는 것이 GC이다.

 

(3) Runtime Data Area : JVM의 메모리 영역

- 클래스 영역> 실행에 필요한 클래스들을 로드하여 저장> 내부에서 메소드 영역과 상수 영역으로 나뉘어 저장

 

- 가비지 컬렉션 힙 영역> GC에 의해 관리되는 영역> 동적 메모리 할당 영역> 소스상에서 new 연산자로 객체를 만들 때 할당되는 영역

 

- 런타임 스택 영역> 프로그램 실행 중 발생하는 메소드 호출과 복귀에 대한 정보를 저장

 

- 네이티브 메소드 스택 영역> 자바에서 하드웨어를 직접 제어하는 기능이 없기 때문에, 필요한 경우 c언어와 같은 다른 언어의 기능을 빌려 사용한다.. 이떄!!! 사용하는 기술이 JNI(Java Native Interface)이다.. 네이티브 메소드들이 바이트코드로 변환되면서 사용되고 기록되는 것

 

7. JDK와 JRE의 차이

JDK

JRE

Java Development Kit로 오라클 자바 9부터는 JRE 포함하고 있으며 개발에 필요한 여러 가지 툴을 제공

Java Runtime Environment로 바이트 코드로 컴파일된 자바 프로그램을 실행할 때 사용

>> 자바 언어로 프로그램을 '개발'하기 위해서는 ?? JDK 설치 필요

>> 자바 언어로 작성된 프로그램을 '실행'하기 위해서는 ?? JRE 설치 필요 

 

Q. javac는 어디에 들어있을까???

> 개발할 때 필요한 것이기 때문에 JDK에 들어있다!!!

'STUDY' 카테고리의 다른 글

lambda  (0) 2021.03.07
Annotation  (0) 2021.02.08

 

(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
public class Car{
	
	String carName; //전역변수 (class영역에서 선언했기 때문에 전체적으로 사용할 수 있는 변수)
	String carColor;
	String maker;
	int speed;

	public Car() { //기본 생성자 생성
		//carName = "아반떼";
		//carColor = "흰색";
		//maker = "현대";
		this ("아반떼", "흰색", "현대");
		//speed = 10;
		
	}
	
	// carName만 외부에서 받은 값으로 하고 싶다면?
	public Car(String carName) {  // 왜 cn이 아닌 carName으로 했을 때, null값이 나오는가? 전역변수의 carName은 class영역에 있고, 지역변수의 carName은 메소드 영역에 있기 때문에 같은 이름이 지정가능하다. 지역변수가 전역변수보다 먼저 적용되기 때문에 
		//this.carName = carName; //.을 찍어 새로운 객체가 형성되기 때문에 자기 자신을 참조하기 위해서는 this를 붙여야 한다. 지역변수와 전역변수가 같을 경우 반드시 this를 명시해주어야 한다.
		//carColor = "흰색"; //앞에 this가 생략되어 있음
		//maker = "현대";
		this (carName, "흰색", "현대");
	}

	// carName, carColor만 외부에서 받은 값으로 하고 싶다면?
	public Car(String carName, String carColor) { //타입이나 개수가 달라야 함!! 그냥 String cn하면 x 컴퓨터는 cn,cc를 인식하는 것이 아니라 같은 String으로 인식하기 때문!!
		//this.carName = carName;
		//this.carColor = carColor;
		//maker = "현대";
		this(carName,carColor,"현대");

	}
	
	// 초기화 내용(중복 코드)을 몰아서 작성한 생성자 this()
	public Car(String carName, String carColor, String maker) { //타입이나 개수가 달라야 함!! 그냥 String cn하면 x 컴퓨터는 cn,cc를 인식하는 것이 아니라 같은 String으로 인식하기 때문!!
		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)
			//speed = 0;
			stop(); //그냥 stop을 호출하면 됨
	}

	void stop() {
		speed = 0;
	}

}
public class CarUser{
	public static void main(String[] args) {
		Car car1 = new Car();
		System.out.println("1. " + car1.maker + "에서 만든 " + car1.carColor + " " + car1.carName + "입니다. ");
		
		car1.carName = "쏘나타";
		car1.carColor = "남색";
		car1.maker = "현대";
		System.out.println("2. " + car1.maker + "에서 만든 " + car1.carColor + " " + car1.carName + "입니다. ");

		System.out.println("속도를 5회증가!!!");
		for (int i=0;i<5;i++)
			car1.speedUp();
		System.out.println("car1의 속도 : " + car1.speed);

		System.out.println("속도를 150회증가!!!");
		int s = car1.speedUp(150);
		System.out.println("car1의 속도 : " + s);
		

		Car car2 = new Car("제네시스"); //내가 원하는 이름을 지정해서 넣을 수 있다
		System.out.println("3. " + car2.maker + "에서 만든 " + car2.carColor + " " + car2.carName + "입니다. ");

		Car car3 = new Car("그랜저", "검정색"); 
		System.out.println("4. " + car3.maker + "에서 만든 " + car3.carColor + " " + car3.carName + "입니다. ");

		//기아에서 만든 빨간색 K5입니다.

		Car car4 = new Car("K5", "빨간색", "기아"); 
		System.out.println("5. " + car4.maker + "에서 만든 " + car4.carColor + " " + car4.carName + "입니다. ");
	}
}
---------- run ----------
1. 현대에서 만든 흰색 아반떼입니다. 
2. 현대에서 만든 남색 쏘나타입니다. 
속도를 5회증가!!!
car1의 속도 : 50
속도를 150회증가!!!
car1의 속도 : 200
3. 현대에서 만든 흰색 제네시스입니다. 
4. 현대에서 만든 검정색 그랜저입니다. 
5. 기아에서 만든 빨간색 K5입니다. 

 

(1) Null : 변수(스택 영역)가 참조하는 객체(힙 영역)가 없을 경우 초기값으로 사용

: 참조 타입의 변수에만 저장 가능 (기본타입은 사용 x)

: 값이 없는 변수는 stack 영역에 생성되지 않지만, null로 초기화된 참조 변수는 stack 영역에 생성

String str = null;
char c = str.charAt(0); //NullPointerException

 

여기서 null이란 str이란 String 변수가 선언만 되어 있고, 참조하고 있는 주소값이 없다는 것

즉, 존재하지 않는 객체를 가리킬 때 발생한다.

null을 사용하는 이유는? 자원을 해제하기 위해서 주로 사용한다. 추후에 사용되지 않으면 자동 소멸됨.

 

(2) NullPointerException : 가장 자주 발생하는 에러, 가장 잡기 쉬우면서 어려운 에러

 

- 발생 원인 : 참조 변수가 null값을 가지고 있는데 객체의 필드나 메소드를 사용하려고 했을 때 발생

(에러가 발생된 곳에서 객체를 참조하지 않은 상태로 참조 타입 변수를 사용하고 있음)

- 해결법 : 변수 추적, 객체를 참조하도록 수정

 

(3) String : 문자열을 저장하는 클래스 타입

Q.동일한 문자열 리터럴을 String에 대입하고자 한다면? 힙 영역의 같은 String 객체를 공유 (객체 하나만 생성됨)

Q. 동일한 문자열 리터럴을 같은 String이 아닌 다른 String 객체에 대입하고자 한다면?

new 연산자를 이용한 String 객체 생성 : 힙 영역에 새로운 String 객체를 생성 >> 번지를 리턴

 

(4) 참조 변수의 ==, != 연산

- 동일한 객체를 참조하는지 서로 다른 객체를 참조하는지 조사하는 것

 

(5) 문자열 비교시 주의사항 ***

주로 Sring은 동일한 객체를 참조하는지를 비교하지 않고, 객체 안 문자열이 동일한지를 비교한다.

ex) String name1 = "홍길동";

String name2 = "홍길동";

String name3 = new String ("홍길동");

 

>> name1.equals(name3) //true (문자열 동일 o, 객체 동일x)

 

(6) 배열

- 같은 타입의 데이터를 연속된 공간에 저장하는 자료구조

- 각 데이터의 저장 위치는 인덱스(번호)를 부여해서 접근할 수 있다.

 

Q. 배열을 왜 사용하는가?

>> 변수의 수가 많을 경우, 연산을 하기 어렵기 때문에 쉽게 연산을 하기 위해서

>> 같은 타입의 변수들을 효율적으로 관리하기 위해서 (반복문 사용)

>> 코드 절감하기 위해서

 

index

85

0

96

1

74

2

76

3

.....

....

88

44

 

- 배열이름[인덱스번호] (*인덱스 번호는 0번부터 시작되고, 자동으로 생성된다.)

( 주로 배열은 for문과 함께 사용되어 최댓값, 최솟값, 평균, 총합 등을 구한다.)

ex) score[2] = 79; // index 2번인 74점을 79점으로 변경하여 대입.

ex) 0~44번까지의 총학점과 평균을 구하라.

int sum = 0;

for (i=0; i<45; ,i++) {

sum += score[i];

}

int avg = sum / 45;

 

선언) 타입[ ] 변수;

int[ ] intArray;

double[ ] doubleArray;

String[ ] strArray;

 

사용)

1. 변수 선언과 동시에 값 대입

데이터 타입[ ] 변수 = {값1,값2.........};

String[ ] names = {"홍길동", "임꺽정"};

public class ArrayCreateByValueListExample{
	public static void main(String[] args) {
		int[] scores = {95,80,99}; // scores 배열 변수는 stack 영역에 생성, {95,80,99} 배열 객체는 heap 영역에 생성

		System.out.println("scores[0]:" + scores[0] ); //index번호 0부터 자동 생성됨
		System.out.println("scores[1]:" + scores[1] );
		System.out.println("scores[2]:" + scores[2] );

		int sum = 0;
		for (int i=0;i<3 ;i++ ){ //0~2 
			sum += scores[i]; //배열에 저장되어 있는 값들을 더하라 
		}
		System.out.println("총합 :" + sum);

		double avg = (double) sum/ 3;
		System.out.println("평균 : " + avg);
	}
}
---------- run ----------
scores[0]:95
scores[1]:80
scores[2]:99
총합 :274
평균 : 91.33333333333333

2. 변수 선언 후 값 대입

데이터 타입 [ ] 변수;

변수 = new 타입 [ ] {값1, 값2.....};

String[ ] names = null;

names = new String [ ] {"홍길동","임꺽정"};

 

* 배열은 참조 변수이기 때문에 null로 초기화가 가능하다.

(but, null값을 가진 상태에서 항목에 접근하기 위해 "변수[인덱스]"를 하면 NullPointerException 발생)

 

Q. 이미 선언한 배열을 매개변수로 가지는 메소드를 호출하고 싶다면?

>> int add (int[] scores) {......} --- int 배열의 값을 모두 더해서 return하는 메소드

ex)

int result = add({95,80,99}); //컴파일 에러 발생

int result = add(new int[] {95,80,99} );

public class ArrayCreateByValueListExample2 {
	public static void main(String[] args) {
		int[] scores;
		//scores = {83,90,87}; //컴파일 에러 
		scores = new int[] {83,90,97};//배열변수 선언 후 값 대입을 할 떄는 new 붙이기
		
		int sum1 = 0;
		for (int i=0;i<3;i++){
			sum1 += scores[i];
		}
		System.out.println("총합 : " + sum1);

		int sum2 = add(new int[] {83,90,97});
		System.out.println("총합 : " + sum2);

	}

	public static int add(int[] scores) { //add라는 메소드 사용
		int sum = 0;
		for (int i=0;i<3;i++){
			sum += scores[i];
		}
		return sum;
	}
---------- run ----------
총합 : 270
총합 : 270

3. new 연산자로 배열 생성 : 배열 생성시 값을 대입하지 않고, 추후에 값들을 대입하고 싶을 경우

>> 타입[] 변수 = new 타입[길이];

int[] socres = new int[5]; //5개의 값

 

데이터 타입

초기값

기본타입(정수)

new byte[]

new char[]

new short[]

new int[]

new long[]

0

공백

0

0

0

기본타입(실수)

new float[]

new double[]

0.0

0.0

기본타입(논리)

new boolean[]

false

참조타입

클래스[]

인터페이스[]

null

null

public class ArrayCreateByNewExample {
	public static void main(String[] args) {
		int [] arr1 = new int[3]; //배열생성
		for (int i=0;i<3 ;i++ ){
			System.out.println("arr1[" + i + "] : " + arr1[i]);//초기값 알아보기 위해서
		}
		System.out.println(); // 한 줄 생성

		arr1[0] = 10; // 0번 인덱스에 10이라는 값 저장
		arr1[1] = 20;
		arr1[2] = 30;
		for (int i=0;i<3 ;i++ ){
			System.out.println("arr1[" + i + "] : " + arr1[i]);
		}
		System.out.println();

		double[] arr2 = new double[3];
		for (int i=0;i<3 ;i++ ){
			System.out.println("arr2[" + i + "] : " + arr2[i]);//초기값 알아보기 위해서
		}
		System.out.println();

		arr2[0] = 0.1;
		arr2[1] = 0.2;
		arr2[2] = 0.3;
		for (int i=0;i<3 ;i++ ){
			System.out.println("arr2[" + i + "] : " + arr2[i]);
		}
		System.out.println();

		String[] arr3 = new String[3];
		for (int i=0;i<3 ;i++ ){
			System.out.println("arr3[" + i + "] : " + arr3[i]);//초기값 알아보기 위해서
		}
		System.out.println();

		arr3[0] = "1월";
		arr3[1] = "2월";
		arr3[2] = "3월";
		for (int i=0;i<3 ;i++ ){
			System.out.println("arr3[" + i + "] : " + arr3[i]);
		}
	}
}
---------- run ----------
arr1[0] : 0
arr1[1] : 0
arr1[2] : 0

arr1[0] : 10
arr1[1] : 20
arr1[2] : 30

arr2[0] : 0.0
arr2[1] : 0.0
arr2[2] : 0.0

arr2[0] : 0.1
arr2[1] : 0.2
arr2[2] : 0.3

arr3[0] : null
arr3[1] : null
arr3[2] : null

arr3[0] : 1월
arr3[1] : 2월
arr3[2] : 3월

 

(7)

java : 객체 지향 프로그래밍

c : 절차 지향 프로그래밍

객체들은 서로 다른 객체들과 관계를 맺고 있다.

(위에서부터 순서대로 이루어짐)

- 관계 종류

1. 집합 관계 : 자동차 -- 엔진, 타이어, 핸들

2. 사용 관계 : 사람 --> 자동차

3. 상속 관계 : 자동차 --> 기계

 

 

 

** 붕어빵 생각하기

1. 붕어빵 틀 : 클래스

2. 팥, 초코, 딸기 붕어빵 : 각각의 객체

3. 클래스 (속성, 기능) 두개로 나뉜다.

 

** object (참조형(Reference) DataType)

- class (Object)

- array

 

* 메소드(동작)를 호출하고 결과를 리턴한다.

 

(1) class : 객체(object)를 생성하기 위한 틀, 설계도

: 속성(field), 기능(method)으로 이루어져 있음

=(특징,명사) =(동작,동사)

 

** 클래스 용도

1. 라이브러리 API : 자체적으로 실행X, 다른 클래스에서 이용할 목적으로 만든 클래스

2. 실행용 : main() 메소드를 가지고 있는 클래스로 실행할 목적으로 만든 클래스

(주로, 1개의 어플리케이션 = 1개의 실행클래스로 충분 + 여러개의 라이브러리 클래스)

 

형식)

public class ClassName {

 

//Field : 객체의 데이터가 저장되는 곳

int FieldName;

String FieldName;

int FieldName = 초기값;

1. 객체 내부 사용 : 생성자 or 메소드 영역에서 바로 필드이름으로 사용 ex) speed = 10;

2. 객체 외부 사용 : Car car1 = new Car(); 새로운 객체 생성 후 car1.speed = 10; 사용

 

//Constructor : 객체 생성시 초기화 역할

ClassName() {.............};

Car(String model, String color, int maxSpeed) {........}

사용:Car myCar = new Car("그랜저","검정",300);

 

//Method : 객체 동작에 해당하는 실행 블록

접근제어자 ReturnType methodName([args]) { //[ ]:생략가능,return값이 없을 때는

ReturnType에 void 입력

기능 구현

[return 값;] // return값이 있는 경우 반드시 return문을 사용해서 리턴값을 지정해야 한다.!!

}

void methodName() {..................}; * 메소드 안에 있는 변수는 접근제어자 생략 가능

}

(2) 메소드 (Method) : 서로 연관된 코드를 정리정돈해주는 역할!!!



> 리턴타입 : 메소드가 실행 후 리턴하는 값의 타입(ex) 메소드 실행 후 int값, String 문자열이 리턴해서 나옴)

: 리턴값이 있을 수도 있고, 없을 수도 있다.

: 메소드의 실행을 중지하고 리턴값을 지정하는 역할 (return문 뒤에 실행문이 올 수 x)

선언)

void powerOn() {} // void 리턴 값이 없을 때 사용, 실행만 하고 끝남

double divide (int x, int y) {} // double : 나눗셈 결과를 리턴해야 되기 때문에 리턴타입이 있고, 실행할 때 정수 x,y값이 필요하다는 뜻이다.

 

호출)

powerOn(); // 리턴 값이 없기 때문에 메소드 이름만 ~

double result = divide (10,20); // 리턴 타입이 double이기 때문에 double로 받고, x,y에 해당하는 값도 명시해야 함!!리턴값을 저장할 변수가 필요하기 때문에 double로 잡기!!

* 리턴 타입이 있다고 해서 반드시 리턴값을 변수에 저장할 필요는 없다. 리턴값이 중요하지 않고, 메소드 실행이 중요할 경우, 변수 선언 없이 divide(10,20); 메소드 호출하기

 

public class Calculator {
	void powerOn() {
		System.out.println("전원을 켭니다.");
	}

	int plus(int x, int y){ //int : 리턴타입, plus : 메소드
		int result = x+y; // 기능구현
		return result; // result값을 리턴하라는 뜻
	}

	double divide(int x, int y){
		double result = (double)x/(double)y;
		return result;
	}
}
public class CalculatorUser {
	public static void main(String[] args) {
		Calculator cal = new Calculator();
		cal.powerOn();

		int result1 = cal.plus(10,20);// x+y를 한 result값이 리턴되어 result1에 저장
		System.out.println("result1 : " + result1);

		byte x = 10;
		byte y = 4;
		double result2 = cal.divide(x,y); //리턴타입이 double이기 때문에 double로 받아야 함
		System.out.println("result2 : " + result2);

	}
}
---------- run ----------
전원을 켭니다.
result1 : 30
result2 : 2.5

 

> 매개변수 : 메소드가 실행할 때 필요한 데이터를 외부로부터 받기 위해 사용

매개 변수를 모를 경우?

(방법1) ---- 배열을 매개 변수로 할 경우 {} 중괄호 사용해야 함!!

int sum1(int[] values) {};

----------------------------

int[] values = {1,2,3};

int result = sum1(values);

or

int result = sum1(new int[] {1,2,3,4,5});

 

(방법2)

int sum2(int... values) {} --- 그냥 1,2,3 값을 대입해도 알아서 배열로 인식함!!

-----------------------------

int result = sum2(1,2,3);

or

int result = sum2(1,2,3,4,5);

public class Computer {
	int sum1(int[] values){
		int sum = 0;
		for (int i=0;i<values.length ;i++ ){
			sum += values[i];
		}
		return sum;
	}

	int sum2(int...values){
		int sum = 0;
		for (int i=0;i<values.length ;i++ ){
			sum += values[i];
		}
		return sum;
	}
}
public class ComputerUser {
	public static void main(String[] args) {
		Computer myCom = new Computer();

		int[] values1 = {1,2,3}; //미리 배열을 만들어 놓는 경우
		int result1 = myCom.sum1(values1);
		System.out.println("result1: " + result1);

		int result2 = myCom.sum1(new int[] {1,2,3}); //메소드 호출 시 직접 매개 값으로 주는 경우
		System.out.println("result2: " + result2);

		int result3 = myCom.sum2(1,2,3);
		System.out.println("result3: " + result3);

		int result4 = myCom.sum2(1,2,3,4,5);
		System.out.println("result4: " + result4);

	}
}

(3) 생성자(Constructor)

* 라이브러리 클래스에서 생성자를 생성하고, 실행 클래스에서 new연산자로 생성자를 호출해 객체를 생성

a. 객체 생성시 최초로 한번만 호출이 되는 메소드의 일종

반드시 new 연산자와 함께 사용!!!! (객체를 생성한 후, 객체 생성 번지를 리턴한다.)

b. 객체의 field값 초기화

c. Class의 이름과 같고 Return Type이 없다.

형식)

접근제어자 ClassName([args]) { // 접근제어자 public class에서 선언을 했다면, 접근제어자 생략 ok~

}

d. 사용자가 생성자를 생략할 경우, default 생성자가 생략되어 있다고 생각하면 ok~

public ClassName() { }

사용자가 생성자를 생성했을 경우, 라이브러리 클래스에서 매개변수를 입력하고, 실행클래스에서 값을 입력해야 함

사용자가 클래스 내부에 하나라도 생성자를 생성했을 경우, default 생성자는 생성되지 않는다.

 

e. 메소드의 overloading ************************

- 클래스 내에 같은 이름의 메소드를 여러 개 선언하는 것

- 외부의 값이 어떤 타입으로 몇 개가 입력될 지 모르기 때문에 메소드도 다양해질 필요가 있을 때

단, 인자값의 개수가 다르거나, 인자값의 타입, 인자값의 순서가 달라야 한다. (리턴타입,인자값의 이름은 상관x)

ex)

public void a() {} :기준

public void a() {} : x

public void a(int x) {} : O

public void a(Sting s) {} : O

public void a(int y) {} : x , int x와 int 타입이 같다

public int a() {} : x

private void a() {} : x

public void a(int x, String s) {} : o

public void a(String s, int x) {} : o //위에랑 순서가 바뀌었다고 보지 말고, 컴퓨터는 첫번째부터 인식한다.

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

 

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

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

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

	void println(String a){
		System.out.println(a);
	}	
}
public class PrinterExample {
	public static void main(String[] args) {
		Printer printer = new Printer();

		printer.println(10);
		printer.println(true);
		printer.println(5.7);
		printer.println("홍길동");
	}
}

f. ************

< this : 자기클래스 참조변수 >

-- 생성자의 매개변수와 필드명이 동일할 경우,,

> 관례적으로 매개변수의 값을 필드값으로 설정할 경우 매개변수와 필드명을 동일하게 한다.(n보다는 name으로!)

> 생성자 내부에서는 매개변수가 우선순위를 갖는다.

> 필드임을 명시하기 위해 this.필드명을 사용한다.

ex) public Korean(String name, String ssn) {

name = name; // 필드명 앞에 this.를 쓰지 않으면? 매개변수의 값을 매개변수에 저장하라는 뜻이 된다.

필드명 매개변수

this.name = name; // 따라서, this.의 의미는 외부에서 매개변수로 받은 값을 필드에 저장하라는 뜻이 된다.

}

 

< super : 상위클래스 참조변수>

 

< this() : 자기클래스 생성자 호출 > : 중복 코드 줄이기, 반드시 첫 줄에 와야 함!!

-- 생성자가 오버로딩되면 생성자 간의 중복된 코드가 발생될 수 있다.

-- 초기화 내용이 비슷한 생성자들에서 주로 발생

> 해결방법 : 초기화 내용을 한 생성자에 몰아서 작성한다. (주로 모든 생성자의 내용을 포함할 수 있는 생성자로 함)

: 다른 생성자는 초기화 내용을 작성한 생성자를 this()로 호출한다.

 

< super() : 상위클래스 생성자 호출 >

 

* Car.java:13: error: call to this must be first statement in constructor

-- this(), super()는 생성자의 첫줄에서만 호출이 가능하다.

 

(4) Reference DataType의 사용

a.선언

형식)

접근제어자 참조형DataType(ClassName) 객체명;

ex)

public String carName;

private Car car;

TV tv;

Radio r;

b.생성 : class를 메모리에 할당

형식)

객체명 = new ClassName;

ex)

carName = new String("쏘나타");

car = new Car();

tv = new TV();

r = new Radio();

 

>> a, b를 동시에

접근제어자 객체명 = new ClassName();

public String carName = new String("쏘나타");

private Car car = new Car();

 

c.사용

형식) 객체명.변수 = 값;

객체명.변수 // System.out.println( );에서 주로 사용

객체명.methodName( );

ex)

car.carName;

System.out.println(car.carName);

car.speedUp( );

 

(5) 메모리 사용 영역 *

JVM은 OS에서 할당받은 메모리 영역을 3 영역으로 구분한다.

Method

클래스 생성

Heap

(동적할당)

car1

carName

carColor

maker

speed

---------------

car2

carName

carColor

maker

speed

.

.

.

- class타입인 string("문자열") 등의 객체가 Heap 영역에 생성,

배열 생성

- 사용되지 않는 객체는 GC가 자동 제거

Stack

car1 car2 car3

변수 생성

기본타입 변수 : 값을 직접 저장

참조타입 변수 : Heap영역에 생성된 주소값이 Stack에 저장 (Heap 영역을 참조한다)

 

<순서>

1.Car라는 객체를 만들 것이다.

2.car1 = new Car;

3.Car생성

4.car1.carName : ' . ' 의 의미는 ' in ' (Heap에서 car1의 주소값을 가져온다.)

 

ex)

class : 자동차 Car

 

field : 차이름 carName

차색상 carColor

제조사 maker

속도 speed

 

method : 가속 speedUp >> 한 번 호출시 속도가 10씩 증가

감속 speedDown >> 감소

정지 stop >> 속도를 0으로

public class Car{
	
	String carName; //전역변수 (class영역에서 선언했기 때문에 전체적으로 사용할 수 있는 변수)
	String carColor;
	String maker;
	int speed;

     //생성자 default 값으로 생략되어 있음.

	void speedUp() { //접근제어자 생략 가능, ()안 인자값 생략 가능
		speed += 10; // 필드 내부에서 사용
	}

	void speedDown() {
		speed -= 10;
		if(speed < 0) //속도가 -는 없으므로, 
			//speed = 0;
			stop(); //그냥 stop을 호출하면 됨
	}

	void stop() {
		speed = 0;
	}
}
public class CarUser{
	public static void main(String[] args) {
		Car car1 = null;//Car라는 객체를 만듦, 참조형은 아무것도 생성하지 않은 상태를 null이라고 한다. 힙 영역의 객체를 참조하지 않는다. cf)오라클 아직 알 수 없는 값
		car1 = new Car(); //새로운 객체 생성 , Car클래스에 만든 적은 없지만 자동으로 Car클래스에 자동으로 생성됨
		
		System.out.println("car1의 이름 : " + car1.carName); 
// 초기화를 하지 않으면 자동으로 초기화 (참조형 : null) (기본형 : int는 0, boolean은 false, double은 0.0, char는 초기화x공백)
		car1.carName = "쏘나타";
		System.out.println("car1의 이름 : " + car1.carName);
		car1.carColor = "흰색";
		System.out.println("car1의 색상 : " + car1.carColor);
		car1.maker = "현대";
		System.out.println("car1의 제조사 : " + car1.maker);
		car1.speed = 30;
		System.out.println("car1의 속도 : " + car1.speed);

		int cnt = 3;
		System.out.println("car1의 속도를 " + cnt + "회 증가!!");
		for (int i=0;i<cnt;i++){
			car1.speedUp();
		}
		//car1.speedUp();
		//car1.speedUp();//speedUp 메소드 호출
		System.out.println("car1의 속도 : " + car1.speed);

		cnt = 10;
		System.out.println("car1의 속도를 " + cnt + "회 감속!!");
		for (int i=0;i<cnt;i++)
			car1.speedDown(); //조건문 밑에 한줄일 경우에는 { } 생략 가능
		
		System.out.println("car1의 속도 : " + car1.speed);


		Car car2 = new Car();
		System.out.println("car2의 이름 : " + car2.carName); //쏘나타? null?

		Car car3 = car1;
		car3.carName = "K5";
		System.out.println("car1의 이름 : " + car1.carName); //객체는 주소값을 할당한다.car1의 주소값을 가져와서 변경하니까 K5출력

	}
}

 

---------- run ----------
car1의 이름 : null
car1의 이름 : 쏘나타
car1의 색상 : 흰색
car1의 제조사 : 현대
car1의 속도 : 30
car1의 속도를 3회 증가!!
car1의 속도 : 60
car1의 속도를 10회 감속!!
car1의 속도 : 0
car2의 이름 : null
car1의 이름 : K5

----------------------------------------------------------------------------------------------------------------------------

public class Car1 {
	int gas;

	void setGas(int gas){ //외부에서 입력한 값 받기
		this.gas = gas; // gas 필드에 외부에서 입력한 gas값을 저장
	}

	boolean isLeftGas(){
		if (gas == 0){
			System.out.println("gas가 없습니다.");
			return false;
		}
		System.out.println("gas가 있습니다.");
		return true; //리턴타입이 있으면 반드시 return문 존재!!
	}

	void run(){
		while(true) {
			if (gas>0){
				System.out.println("달립니다.(gas잔량 : " + gas + ")");
				gas -= 1;
			} else {
				System.out.println("멈춥니다.(gas잔량 : " + gas + ")");
				return;
			}
		}
	}
}
public class CarExample {
	public static void main(String[] args) {
		Car1 myCar = new Car1();

		myCar.setGas(5);

		boolean gasState = myCar.isLeftGas();
		if (gasState){
			System.out.println("출발합니다");
			myCar.run();
		}

		if (myCar.isLeftGas()){
			System.out.println("gas를 주입할 필요가 없습니다.");
		} else {
			System.out.println("gas를 주입할 필요가 있습니다.");
		}
	}
}
---------- run ----------
gas가 있습니다.
출발합니다
달립니다.(gas잔량 : 5)
달립니다.(gas잔량 : 4)
달립니다.(gas잔량 : 3)
달립니다.(gas잔량 : 2)
달립니다.(gas잔량 : 1)
멈춥니다.(gas잔량 : 0)
gas가 없습니다.
gas를 주입할 필요가 있습니다.

 ex)

public class Member {
	String name;
	String id;
	String password;
	int age;

	Member(String name, String id){
		this.name = name;
		this.id = id;
	}	
}
public class MemberService {
	boolean login(String id, String password){
		
		if (id.equals("hong") && password.equals("12345")){ //문자열 비교
			return true;
		} else {
			return false;
		}
	}

	void logout(String id){
		System.out.println("로그아웃 되었습니다.");
	}
}
public class MemberServiceExample {
	public static void main(String[] args) {
		MemberService ms = new MemberService();

		boolean result = ms.login("hong","12345"); //리턴 받을 변수 선언

		if (result){
			System.out.println("로그인 되었습니다.");
			ms.logout("hong");
		} else {
			System.out.println("id 또는 password가 올바르지 않습니다.");
			}
	}
}
---------- run ----------
로그인 되었습니다.
로그아웃 되었습니다.

+ Recent posts