** 붕어빵 생각하기
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 ----------
로그인 되었습니다.
로그아웃 되었습니다.