- 객체(Object)를 만들어 내기 위한 설계도
- 객체의
속성(Attribute)
과행동(Behavior)
을 포함- 클래스는 객체 내부의 값을 저장하기 위한
필드(Field)
와 객체의 기능을 나타내기 위한메소드(Method)
로 구성
- 객체(Object)의 속성(Attribute)을 저장하는 변수
- 일반 변수와 달리 자동으로 초기화
- boolean 타입 필드 :
false
- 숫자 타입(int, double 등) 필드 :
0
- 참조 타입(String 등) 필드 :
null
- 객체마다 필드(속성)값이 다르다.
Person 클래스의 예시
이름, 나이, 직책, 결혼유무를 저장할 수 있는 필드를 Person 클래스에 선언하고,
Person 클래스 내부에서만 접근할 수 있도록 private 접근 지시자를 부여한다.
public class Person {
private String name;
private int age;
private String position;
private boolean isMarried;
}
필드 구현 코드
변수
라고 부르지 않고, 클래스 안에 있는 필드(Field)
라고 부른다.
필드는 일반 변수와 달리 자동으로 초기화된다.
// 필드 5개 // 초기화
String id; // null
String password; // null
String email; // null
int point; // 0
boolean isVip; // false
메인 메소드를 만들어서 필드를 출력하고자 한다.
주의!
동일 패키지 안에 있는 클래스는 클래스명을 적어서 사용할 수 있다. (import가 안됨)
필드 값 변경할 때는 변수값 변경하는 것처럼 하면 된다.
public class UserMain {
public static void main(String[] args) {
// 필드 객체 선언
User user = new User();
// 필드값 변경
user.id = "admin";
user.password = "123456";
user.email = "admin@web.com";
user.point = 1000;
user.isVip = (user.point) >= 10000;
// 출력
System.out.println(user.id);
System.out.println(user.password);
System.out.println(user.email);
System.out.println(user.point);
System.out.println(user.isVip);
}
}
모든 user
객체는 필드값을 가지고 있다.
user.
마침표(.)를 이용해서 필드값을 호출하여 자동 완성하면 된다.
학교의 학생들 정보 저장
- 바다중학교에 다니는
손석구 11025
박은빈 11026
필드 클래스
package ex01_field;
public class School {
String name;
Student[] students = new Student[2]; // { null, null }
}
package ex01_field;
public class Student {
String stuNo;
String name;
}
Student 클래스
에서 학생번호
와 학생이름
데이터를 저장했고, 그 학생정보들을 다시 School 클래스
에 Students 배열
에 저장을 했다.
실행클래스
package ex01_field;
public class SchoolMain {
public static void main(String[] args) {
School school = new School();
school.name = "바다중학교";
Student student1 = new Student();
student1.stuNo = "11025";
student1.name = "손석구";
Student student2 = new Student();
student2.stuNo = "11026";
student2.name = "박은빈";
school.students[0] = student1;
school.students[1] = student2;
for(int i = 0; i < school.students.length; i++) {
System.out.println(school.students[i].stuNo);
System.out.println(school.students[i].name);
} // 11025
} // 손석구
} // 11026
// 박은빈
student1
과 student2
는 new
를 이용해 새로운 객체를 만들었으므로 서로 다른 주소값에 데이터가 저장이 된다.
/* |--------|
students | 0x123 |
|--------|
|--------|
students[0] | 0x1111 | 0x123
students[1] | 0x2222 |
|--------|
|--------|
student1 | 0x1111 |
|--------|
student2 | 0x2222 |
|--------|
|--------|
| 11025 | 0x1111
| 손석구 |
|--------|
| 11026 | 0x2222
| 박은빈 |
|--------|
| |
*/
- 객체(Object)의 행동(Behavior)을 의미하는 함수
- 함수(Function)
- 독립적인 기능을 수행하는 프로그램의 단위
- 기능별로 구분한 프로그램 단위로 재사용이 가능
접근권한 반환타입 메소드명(매개변수) {
실행코드
return 반환값
}
public double getCircleArea(int r) {
final double PI = 3.14;
double area = PI * r * r;
return area;
}
매개변수 int r에 10을 전달하면 (314.0) = (10 * 10 * 3.14)
계산하면 area의 값 314.0이 반환된다.
더하기, 빼기, 곱하기, 나누기 - 계산기 만들기
메소드클래스
add / sub / mul / div
메소드 정의int
: 반환타입(각 메소드를 실행하면 int 타입의 결과값이 반환
된다.)add / sub / mul / div
: 메소드명(자율)int a, int b
: 매개변수(각 메소드를 호출할 때는 int 타입의 값 2개가 전달되어야 한다.)package ex01_method;
public class Calculator {
// add 메소드 정의
int add(int a, int b) {
int result = a + b;
return result; // 반환값
}
// sub 메소드 정의
int sub(int a, int b) {
int result = a - b;
return result;
}
// mul 메소드 정의
int mul(int a, int b) {
int result = a * b;
return result;
}
// div 메소드 정의 (div(7,2) --> 3.5)
double div(int a, int b) {
double result = (double)a / b;
return result;
}
}
실행클래스
add() / sub() / mul() / div()
메소드 호출package ex01_method;
public class CalculatorMain {
public static void main(String[] args) {
// 객체 생성
Calculator calculator = new Calculator();
// 변수를 생성하여 Calculator 클래스에 전달할 매개변수 입력
int answer = calculator.add(2, 3);
System.out.println(answer); // 5
// sub() 메소드 호출
System.out.println(calculator.sub(100, 85)); // 15
// mul() 메소드 호출
System.out.println(calculator.mul(3, 15)); // 45
// div() 메소드 호출
System.out.println(calculator.div(7, 2)); // 3.5
}
}
커피 자판기
- 1잔 = 1000원
- 종류 : 1(아메리카노), 2(카페라떼)
메소드클래스
package ex02_method;
public class VendingMachine {
String getCoffee(int money, int button) {
String[] menu = {"", "아메리카노", "카페라떼"};
return menu[button] + " " + (money / 1000) + "잔";
}
}
실행클래스
package ex02_method;
public class VendingMachineMain {
public static void main(String[] args) {
VendingMachine machine = new VendingMachine();
String coffee1 = machine.getCoffee(1000,1);
String coffee2 = machine.getCoffee(2000,2);
System.out.println(coffee1); // 아메리카노 1잔
System.out.println(coffee2); // 카페라떼 2잔
}
}
자동차를 엑셀, 브레이크, 계기판 확인하기
- 속도는 25씩 증가, 최대 속도 120
- 기름은 1씩 사용
package ex03_method;
public class Car {
// 필드
int oil;
int speed;
// 메소드
// 1. 기름넣기
// 반환타입 : void (반환값이 없다)
// 메소드명 : addOil
// 매개변수 : int o
void addOil(int o) {
oil += o;
if(oil > 60) {
oil = 60;
}
}
// 2. 달리기
// 반환타입 : void
// 메소드명 : pushAccel
// 매개변수 : X
void pushAccel() {
if(oil == 0) {
return; // 반환타입이 void일때만 사용 가능
}
if(speed == 120) {
oil--;
return;
}
speed += 25;
if(speed > 120) {
speed = 120;
}
oil--;
}
// 3. 브레이크
// 반환타입 : void
// 메소드명 : pushBrake
// 매개변수 : X
void pushBrake() {
if(speed == 0) {
return;
}
speed -=25;
if(speed < 0) {
speed = 0;
}
}
// 4. 계기판(기름, 속도) 확인
// 반환타입 : void
// 메소드명 : panel
// 매개변수 : X
void panel() {
System.out.println("기름 " + oil);
System.out.println("속도 " + speed);
}
}
실행클래스
package ex03_method;
public class CarMain {
public static void main(String[] args) {
// 객체 생성
Car car = new Car();
car.addOil(50); // 기름 50 추가
car.addOil(5); // 기름 5 추가
car.addOil(100); // 기름 100 추가
car.pushAccel(); // 속도 25 증가
car.pushAccel(); // 속도 25 증가
car.pushBrake(); // 속도 25 감소
car.panel(); // 기름 58
// 속도 25
}
}
- 같은 이름의 메소드가 2개 이상 존재한다.
- 오버로딩 조건
- 메소드 이름이 동일해야 한다.
- 매개변수가 달라야 한다.
- 반환타입은 상관이 없다.
성공
public int add(int a, int b) {
return a + b;
}
public int add(int a, int b, int c) {
return a + b + c;
}
→ 메소드 이름이 같고, 매개변수가 다르다.
실패
public int add(int a, int b) {
return a + b;
}
public double add(int a, int b) {
return (double)(a + b);
}
→ 반환타입이 다르지만, 메소드 이름과 매개변수가 모두 같다.
메소드 오버로딩을 이용하여 계산기 만들기
메소드클래스
package ex01_method_overload;
public class Calculator {
int add(int a, int b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
int add(int a, int b, int c, int d) {
return a + b + c + d;
}
int add(int[] arr*) {
int total = 0;
for(int n : arr) {
total += n;
}
return total;
}
}
main에 있는 arr*이랑 같은 이름의 다른 변수이지만, 내용은 같아서 같은 이름으로 줬다.
실행클래스
package ex01_method_overload;
public class CalculatorMain {
public static void main(String[] args) {
Calculator calculator = new Calculator();
System.out.println(calculator.add(1, 1)); // 2
System.out.println(calculator.add(1, 1, 1)); // 3
System.out.println(calculator.add(1, 1, 1, 1)); // 4
int[] arr = {1, 2, 3, 4, 5};
System.out.println(calculator.add(arr)); // 15
}
}
객체(Object) 생성할 때 사용되는 특별한 메소드
특징
형식
접근권한 생성자명(매개변수) { public class Person {
실행코드 // Person 생성자
} public Person() {
}
}
public class Person {
private String name; // 첫 번째 객체 생성
public Person() { Person p1 = new Person();
} // 두 번째 객체 생성
public Person(String n) { Person p2 = new Person("한소희");
name = n;
}
}
- 개발자가 클래스에서 생성자를 만들지 않으면 자바가 자동으로 디폴트 생성자가 사용
- 객체 생성 역할만 있고, 필드 초기화는 불가능
- 생성자를 하나라도 만든다면 디폴트 생성자는 사용 불가
- 아무 일도 안하는 상태
Computer() { }
→new Computer()
생성자가 없는 Person 클래스
public class Person {
private String name;
public void walk() {
System.out.println("Walking");
}
}
디폴트 생성자가 자동으로 생성해서 사용한다.
public class Person {
private String name;
public Person() { *****
}
public void walk() {
System.out.println("Walking");
}
}
필드 / 메소드 클래스
package ex_constructor;
public class Computer {
// 필드
String model;
int price;
// 생성자 | 매개변수
Computer() {
}
Computer(String pModel, int pPrice) {
model = pModel;
price = pPrice;
}
// 메소드
void printComputerStatus() {
System.out.println("모델명 : " + model);
System.out.println("가격 : " + price);
}
}
실행 클래스
package ex_constructor;
public class ComputerMain {
public static void main(String[] args) {
// 인수
Computer myCom = new Computer("gram", 150);
myCom.printComputerStatus(); // 모델명 : gram
// 가격 : 150
Computer yourCom = new Computer();
yourCom.printComputerStatus(); // 모델명 : null
// 가격 : 0
}
}
public
private
default
protected
필드 / 메소드 클래스
package ex_access_modifier;
public class User {
// 필드는 private
private String id;
private String password;
private String email;
private int point;
private boolean isVip;
// 메소드는 public
public String getId() {
return id;
}
public void setId(String pId) {
id = pId;
}
public String getPassword() {
return password;
}
public void setPassword(String pPassword) {
password = pPassword;
}
public String getEmail() {
return email;
}
public void setEmail(String pEmail) {
email = pEmail;
}
public int getPoint() {
return point;
}
public void setPoint(int pPoint) {
point = pPoint;
setVip(point >= 10000);
}
public boolean getVip() {
return isVip;
}
public void setVip(boolean pVip) {
isVip = pVip;
}
}
실행 클래스
package ex_access_modifier;
public class UserMain {
public static void main(String[] args) {
User user = new User();
user.setId("admin");
System.out.println(user.getId()); // admin
user.setPassword("1234abc");
System.out.println(user.getPassword()); // 1234abc
user.setEmail("admin@web.com");
System.out.println(user.getEmail()); // admin@web.com
user.setPoint(15000);
System.out.println(user.getPoint()); // 15000
System.out.println(user.getVip()); // true
}
}
- 현재 객체의 참조값(Reference)
- 현재 객체의 멤버(필드, 메소드)를 호출할 때 사용
- 생성자 내부에서 다른 생성자를 호출할 때 this() 형태로 사용
this.필드
또는 this()
형태로 사용this.필드
this()
public class Person {
private String name;
public void setName(String name) {
this.name = name;
}
}
학교에 다니는 학생들의 명단을 작성해보자.
package ex_this;
public class Student {
// 필드
private String stuNo; // this.stuNo 와 동일
private String name; // this.name 와 동일
// 생성자
public Student() {
}
public Student(String stuNo, String name) {
this.stuNo = stuNo;
this.name = name;
}
// 메소드
public String getStuNo() {
return stuNo;
}
public void setStuNo(String stuNo) {
this.stuNo = stuNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
this
를 사용하면 메소드에 매개변수를 넣어 필드에 값을 넣을 때 이름이 동일해도 구분할 수 있다.
package ex_this;
public class School {
// 필드
private Student[] students;
private int idx; // students 배열의 인덱스, students 배열에 저장된 학생수와 같다.
// 생성자
public School(int cnt) {
students = new Student[cnt]; // cnt에 2가 대입되서 student[0], student[1]
}
// add 메소드
public void addStudent(Student student) {
if(idx == students.length) {
System.out.println("Full"); // students 배열이 꽉차면 Full이라 출력
return;
}
students[idx++] = student;
}
// 일반 for문 활용해서 출력방법
public void printStudents() {
for(int i = 0; i < idx; i++) {
System.out.println(students[i].getName() + "," + students[i].getStuNo());
} // 값이 없어도 반복하게 되니까 초기값인 null값이 반환된다.
} // 문법적인 오류는 없지만, 작성한 코드 많을 경우 어디서 null값이 나오는지 코드 전부를 찾아봐야해서 이 방법은 옳지 않다.
// 향상 for문 활용해서 출력방법
public void printStudents() {
for(Student student : students) {
if(students != null) { // null값이 아닌 경우 일떄만 출력함
System.out.println(student.getName() + "," + student.getStuNo());
}
}
}
}
실행 클래스
package ex_this;
public class SchoolMain {
public static void main(String[] args) {
Student student1 = new Student();
student1.setStuNo("11025");
student1.setName("한소희");
Student student2 = new Student("11026", "안보현");
// School 클래스의 생성자 cnt에 2가 들어간다.
School school = new School(2);
// School 클래스의 add 메소드 student에 student1과 student2가 들어간다.
school.addStudent(student1); // 한소희, 11025
school.addStudent(student2); // 안보현, 11026
}
}
public class Person {
private String name;
public String *getName() {
return name;
}
public void *setName(String name) {
this.name = name;
}
}
사용방법
Source - Generate Getter and Setter 클릭
name과 stuNo를 체크하고 Generate 클릭하면 자동으로 메소드가 완성된다.
직사각형과 정사각형의 둘레와 넓이 구하기
package ex1_this;
public class Rectangle {
// 필드
private int width;
private int height;
// 생성자
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
public Rectangle(int n) {
// this.width = n;
// this.height = n;
this(n, n); // 인수 2개인 다른 생성자를 호출한다. (바로 위 생성자 이용)
}
// 메소드
public int getArea() {
return width * height;
}
public int getCircumference() {
return 2 * (width + height);
}
}
package ex1_this;
public class RectangleMain {
public static void main(String[] args) {
// 직사각형
Rectangle rect1 = new Rectangle(3, 4);
// 정사각형
Rectangle rect2 = new Rectangle(5);
System.out.println("넓이 : " + rect1.getArea()); // 넓이 : 12
System.out.println("둘레 : " + rect1.getCircumference()); // 둘레 : 14
System.out.println("넓이 : " + rect2.getArea()); // 넓이 : 25
System.out.println("둘레 : " + rect2.getCircumference()); // 둘레 : 20
}
}
클래스 구성 연습
- 학생이름 : Emily
- 중간고사 성적
ex) 국어 : 50, 영어 : 50, 수학 : 50, 총점 : 150, 평균 : 50.0점- 국, 영, 수학 점수 0 ~ 100 사이 램덤 생성
package quiz05_exam;
public class Exam {
private String examName;
private int kor;
private int eng;
private int mat;
public Exam(String examName) {
super();
this.examName = examName;
}
public void setScore() {
kor = (int)(Math.random() * 101);
eng = (int)(Math.random() * 101);
mat = (int)(Math.random() * 101);
}
public void examInfo() {
System.out.println(examName + " 성적");
System.out.println("국어 : " + kor + ", 영어 : " + eng + ", 수학 : " + mat);
int total = kor + eng + mat;
System.out.println("총점 : " + total + ", 평균 : " + (total / 3.0));
}
}
package quiz05_exam;
public class Student {
private String name;
private Exam exam;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Exam getExam() {
return exam;
}
public void setExam(Exam exam) { // 실제로 이것만 사용
this.exam = exam;
}
public void info() {
System.out.println("학생이름 : " + name);
exam.examInfo();
}
}
package quiz05_exam;
public class Main {
public static void main(String[] args) {
Exam exam = new Exam("중간고사");
exam.setScore();
Student student = new Student("Emily");
student.setExam(exam);
student.info();
// 학생이름 : Emily
// 중간고사 성적
// 국어 : 50, 영어 : 50, 수학 : 50, 총점 : 150, 평균 : 50.0점
}
}
반환값
학생이름 : Emily
중간고사 성적
국어 : 45, 영어 : 60, 수학 : 51
총점 : 156, 평균 : 52.0
package ex_static;
public class MyMath {
// 필드
public static final double PI = 3.141592;
// final이라서 값이 바뀌지 않아서 공개(public)
// 메소드
public static int abs(int n) {
return (n >= 0) ? n: -n;
// 어차피 공식이 똑같으니까 static
// Math. 요소는 공식을 새로 만들지 않는다. 전부다 static
}
public static int pow(int a, int b) {
// a의 b제곱 반환
// for문 구현
int result = 1;
for(int cnt = 0; cnt < b; cnt++) {
result *= a;
}
return result;
}
}
Math
는 객체를 불러와서 계산하는 것과 객체를 새로 생성해서 계산하는 것이 차이가 없기 때문에 추가로 객체를 만들지 못하게 한다.
그래서 객체를 따로 생성하지 않고, static
정적 요소를 사용한다.
package ex_static;
public class MyMathMain {
public static void main(String[] args) {
System.out.println(MyMath.PI); // 3.141592
System.out.println(MyMath.abs(-5)); // 5
System.out.println(MyMath.pow(2, 5)); // 2의 5제곱(32)
}
}