객체(object)는 물리적으로 존재하거나 개념적인 것 중에서 다른 것과 식별 가능한 것
-> 객체는 속성(각 저장 공간과 그 안의 값 : 필드)과 동작(기능 : 메소드)으로 구성되어 있고, 일종의 변수 형태를 가지고 있음
-> 클래스 마찬가지로 속성과 동작으로 구성되어있지만 타입의 형태이라는 것에서 차이점을 보임 (형, 또는 종류!)
-> 객체 생성 방법 : 클래스명 참조변수 = new 클래스명();
-> 클래스의 경우 : 객체를 만들기 위해 선언하는 것!
ex) 모니터를 만들 때 실제로 있지는 않지만 모니터를 만들겠다고 선언하는 것과 비슷!
-> 객체의 경우 : 선언한 것을 실행하는 것!
-> 객체 별로 존재하는 속성 : 멤버 변수
-> 위의 멤버 변수를 선언하기 위한 것이 클래스
-> 멤버 변수를 선언하기 위한 또 다른 방법은 전역변수(정적변수)
-> 객체의 예시 (사람을 예시로 들면)
-> 속성(내부의 값) : 이름 (이동주), 나이(26) :
-> 내부의 기능(동작) 값을 변경하거나 변경을 못할 수도 있음!
-> 동작(메소드) : 웃다, 먹다, 일어나다 등..
-> 객체를 만들고 이 객체들을 하나씩 조립해서 프로그램을 완성하는 구조!
-> 객체와 객체 사이를 연결!
-> 캡슐화(은닉성) : 객체의 데이터와 동작을 (필드와 메소드)를 하나로 묶고 실제 구현 내용을 외부에 감추는 것!
-> 보이기도 하고 감추기도 하는 은닉의 성질을 가짐!
-> 논리적으로 의미를 부여해서 관리하는 것을 의미 (잘못된 접근을 사전에 차단!)
-> 은닉의 종류 :
-> public(공개) :
-> 모든 곳에 공개하여 다른 폴더에서도 사용 가능함.
-> 자바파일명과 클래스명이 대부분 같다.
-> protected(보호)
-> private(개인적으로만 씀)
-> 속성은 private, 동작은 public, 클래스 선언도 public (거의 95% 이상 사용)
-> 상속성 : 부모 객체와 자기 필드와 메소드를 자식 객체에게 물려줘 자식 객체가 사용하게 하는 것! (복사붙여넣기를 하나의 키워드로 만든다는 것!)
-> 상속은 유지보수에 좋음!
-> 다형성 : 사용하는 방법은 동일하나 실행하는 결과가 다름!
-> 굉장히 어려운 개념이고 가장 중요함!
-> 객체 지향 프로그램에서도 객체는 다른 객체와 서로 상호작용하면서 동작함!
-> 객체가 다른 객체의 기능을 이용할 때 메소드를 호출해 데이터를 주고받음!
-> 순서에 맞는 메소드를 호출하기!
-> 매개값(매개변수)
-> 함수가 실행될 때 필요한 인자. 객체가 전달하고자 하는 데이터를 말함
-> 메소드 이름과 함께 괄호 안에 기술함
-> 리턴값
-> 메소드의 실행 결과로 호출한 곳으로 돌려주는 값!
-> 집합 관계 : 완성품과 부품의 관계
-> 자동차를 예시로 들면 자동차와 엔진, 타이어, 핸들 등의 부품들과의 관계!
-> 엔진, 타이어, 핸들 등은 속성에 속함!
-> 사용 관계 : 다른 객체의 필드를 읽고 변경하거나 메소드를 호출하는 단계
-> 상속 관계 : 부모와 자식관계. 필드와 메소드를 물려받음
-> 클래스는 사용자가 정의하는 자료형 (참조 타입)
-> ex) System, Scanner, Math, String 등도 모두 클래스 (oracle에서 직접 만든 자료형)
-> 객체를 생성하기 위한 설계도의 역할을 하므로 객체를 생성하기 위해서는 클래스가 필요함!
-> 클래스로 부터 생성된 객체를 해당 클래스의 인스턴스라고 함
-> 클래스로 부터 객체를 생성하는 과정을 인스턴스화라고 함
-> 동일한 클래스로부터 여러 개의 인스턴스를 만들 수 있음!
package ch06.sec03;
//클래스 선언
//객체를 만들기 위해 반드시 클래스를 생성해야함!
class 사람 {
// 속성
int 나이;
String 이름;
//동작 (메소드)
public void 먹다() {
System.out.println(이름 + "가 음식을 먹는다");
}
public void 웃다() {
System.out.println(이름 + "가 웃는다");
}
}
public class SportsCar {
public static void main(String[] args) {
int a = 10;
System.out.println("a=" + 10);
// 객체 생성
사람 dongju = new 사람();
사람 jinah = new 사람();
// 속성 값 설정
dongju.이름 = "이동주";
jinah.이름 = "이진아";
// 동작, 메소드 호출, 함수 실행
dongju.먹다(); // 객체변수명.메소드();
jinah.먹다(); // 객체변수명.메소드();
}
}
class Tire {
}
-> 객체를 생성하고 객체의 데이터 (속성)과 객체의 동작(메소드)를 정의
-> 클래스 선언은 소스 파일명과 동일하게 작성하기
-> 클래스명은 첫 문자를 대문자로 하고, 캐멀 스타일 (두 가지 이상의 단어를 조합할 경우 각 단어의 첫 문자는 대문자로 하기!)
-> 변수명을 캐멀 스타일로 짓는 경우 : 첫 글자는 소문자, 그 이후 단어의 첫 글자는 대문자
-> 숫자를 포함해도 되지만 첫 문자는 영어로 사용! (,$ 도 사용 가능하지만 $보다는 을 사용하기)
-> 공개 클래스 : 어느 위치에 있든지 패키지에 상관 없이 사용할 수 있는 클래스
-> 클래스로부터 객체를 생성하려면 객체 생성 연산자인 new가 필요
-> new 연산자는 객체를 생성시키고 객체의 주소를 리턴시킴
-> 라이브러리 클래스 : 실행할 수 없으며 다른 클래스에서 사용하는 클래스
-> 실행 클래스 : main() 메소드를 가지고 있는 실행 가능한 클래스
-> 객체 생성 예 : ex) Student s1 = new Student(); 에서
-> Student : 클래스명
-> s1 : 참조 변수
-> new Student() : 인스턴스(객체) 생성
-> 모든 참조변수가 그렇듯 new 연산자를 새로 사용하였을 때는 또 다른 객체를 생성하여 참조함!
-> 동작을 기능별(논리적)으로 분리
-> 필드 : 객체의 데이터를 저장하는 역할 (변수)
-> 일반 메소드 : 일반적인 함수
-> 생성자 함수(메소드) : 객체 생성시 동작하는 함수 (new 연산자), 객체 생성시 초기화됨
-> 작성 순서
필드 > 생성자 메소드 > 일반 메소드(인자 x) > 일반 메소드(인자 o)
-> 필드는 클래스를 따로 생성하여 해당 클래스 블록에서 선언되어야 함 ( 타입 필드명; )
-> 타입은 필드에 저장할 데이터의 종류를 결정하며 기본타입과 참조타입 모두 가능함!
-> 값을 지정하지 않으면 초기값이 들어감 (참조변수 : null, 정수 : 0, 논리타입 : false)
-> 필드에 값을 넣어주면 그 값이 초기값이 됨
-> 필드 = 속성 = 멤버변수
-> 필드값을 읽고 변경하는 것. 클래스로부터 객체가 생성된 후에 필드를 사용할 수 있음
-> 필드는 객체 내부의 생성자와 메소드 내부에서 사용할 수 있고, 객체 외부에서도 접근하여 사용할 수 있음
-> 형태는 참조변수명.메소드명();
package ch06.sec06.exam01;
public class Car {
//필드 선언
String model; // 초기값 : null
boolean start; // 초기값 : false = 0
int speed; // 초기값 : 0
// 은닉성 x
}
-> 위의 코드는 필드를 사용하는 클래스를 선언한 것
-> 선언한 클래스에 외부 객체에서 이용할 필드 값을 선언해주기
package ch06.sec06.exam01;
public class CarExample {
public static void main(String[] args) {
//Car 객체 생성
Car myCar = new Car();
//Car 객체의 필드값 읽기
//참조변수.필드명 의 형태!
System.out.println("모델명: " + myCar.model);
System.out.println("시동여부: " + myCar.start);
System.out.println("현재속도: " + myCar.speed);
}
}
-> 위의 코드는 필드를 생성한 객체를 받아와서 필드값을 출력하는 코드임
-> 객체를 생성하기 위한 형태 : 클래스명 변수 = new 클래스명();
-> 위의 형태를 이용해 Car 클래스의 객체를 생성해보면
-> Car myCar(참조변수) = new Car()(객체 생성); 의 구조를 띔
-> 객체 생성 후 해당 객체의 필드값을 읽기 위한 형태 : 참조변수.필드명;
-> ex) Car 객체의 model이라는 필드명을 읽기 위해서는
myCar(참조변수).model(필드명); 과 같은 구조를 띔!
-> 필드를 생성한 클래스에는 필드변수에 값을 선언하지 않았는데 이 경우 자동적으로 초기값이 적용됨 (참조변수 : null, 정수 : 0, 논리타입 : false)
package ch06.sec06.exam02;
public class Car {
//필드 선언
String company = "현대자동차"; // 초기값
String model = "그랜저"; // 초기값
String color = "검정"; // 초기값
int maxSpeed = 350; // 초기값
int speed; // 초기값 = 0
}
package ch06.sec06.exam02;
public class CarExample {
public static void main(String[] args) {
//Car 객체 생성
Car myCar = new Car();
//Car 객체의 필드값 읽기
System.out.println("제작회사: " + myCar.company); //현대자동차
System.out.println("모델명: " + myCar.model); //그랜저
System.out.println("색깔: " + myCar.color); //검정
System.out.println("최고속도: " + myCar.maxSpeed); //350
System.out.println("현재속도: " + myCar.speed); //0 (초기값)
//Car 객체의 필드값 변경
myCar.speed = 60; // 값이 60으로 변경
System.out.println("수정된 속도: " + myCar.speed); // 60
}
}
-> 위의 두 코드를 보면 필드값을 생성한 클래스에 필드 변수에 값을 대입한 것 처럼 값을 직접 대입할 수 있음
-> 필드변수에 값을 대입할 시 해당 값이 초기값이 됨!
-> 만약 필드값을 변경하고 싶다면 해당 필드 변수에 값을 대입하면 변경됨!
객체참조변수.필드명 : 이게 하나의 변수로 보면 편할듯
package ch06.sec06.exam03;
public class Calc {
public int add(int a, int b) { // a,b : 매개변수!
// 리턴되는 데이터 타입을 선언해주기
return a+b; // a, b 값을 넣으면 a+b의 값을 리턴함!
// void가 아닌 타입을 사용할 때에는 리턴값이 있어야함!
}
public void print(){
// 멤버함수, 멤버변수
// void : 리턴 값이 없을때
System.out.println("출력...");
for(int i=0;i<10;i++) {
if(i>5) {
return ; // void를 사용하는 경우 값을 리턴하지 않음!
// break;와 같은 개념
}
System.out.println(i);
}
}
// 객체 생성 시 호출되는 함수 : 생성자 함수
Calc(){
System.out.println("생성자 호출, 객체 생성됨");
}
}
-> 위의 클래스는 계산기를 사용하기 위한 필드값과 함수를 선언한 클래스임
-> public int add(int a, int b) 에서
-> int a, int b는 매개변수(인자)를 뜻함
-> 기본형 타입의 형태로 메소드를 생성 시 반드시 같은 타입의 형태로 값을 받아야함
-> 위의 내용처럼 값을 받기 위해서는 return 문을 사용함!
-> public void print()
-> void는 멤버함수로 값을 되돌려받지 않는 형태를 가지고 있음
-> 따라서 void 함수를 사용하면 void 함수 내의 내용을 그대로 출력함
-> void 메소드 안에 반복문 등을 사용할 때 빠져나가는 법
-> return ; 과 같은 방식으로 return 값에 아무 값도 넣지 않기!
-> Calc()
-> 이는 생성자 함수로 객체가 생성되었을 때 실행되는 메소드
-> 해당 클래스명과 동일한 객체명을 사용해야함!
package ch06.sec06.exam03;
public class CalcExam {
public static void main(String[] args) {
// TODO Auto-generated method stub
Calc obj = new Calc(); // 객체 생성
int a = obj.add(1, 2); // 함수 호출
System.out.println(a); // 3
obj.print();
Calc obj2 = new Calc();
System.out.println(obj2.add(1,3));
// 함수 호출 : 참조변수.함수(인자값); 의 구조!
}
}
-> 위의 코드는 Calc라는 클래스에서 선언한 함수를 받아 내용을 출력하는 구문
-> Calc obj = new Calc(); : Calc 클래스의 객체를 생성하여 obj 참조변수에 값 저장
-> 객체를 생성함과 동시에 Calc() 생성자 함수에서 지정한 값을 먼저 출력함!
-> obj.add(1,2); : Calc 클래스에서 만든 add 함수에서 사용 가능한 인자를 넣고 이에 따른 값을 리턴함 ex) 1과 2라는 값을 입력받고 리턴값을 1+2로 설정하면 3 출력
-> obj.print(); : void 함수에서 선언한 내용을 그대로 출력
-> new 연산자를 이용해 객체를 생성하면 또 다른 heap 번지가 생성되어 그 번지를 참조!
-> 생성자 : 객체가 생성되는 것으로서 멤버변수를 초기화하는 것!
-> 기본 생성자 : 생성자 메소드에 인자가 없는 것!
-> 일반 생성자 : 생성자 메소드에 인자가 있는 것!
-> 생성자 함수는 클래스명과 같아야함!
-> 생성자 함수는 new 연산자를 통해 호출해야함!!
-> 생성자는 여러개 만들 수 있으나 인자의 수와 인자의 타입을 다르게 해야함!
-> 생성자 함수에서는 멤버변수에 대한 초기화를 수행함
(값을 넣으면 this 연산자를 이용하여 멤버변수 값을 넣어주는 것!)
-> 인자가 없으면 기본 값으로 초기화
-> 인자가 있으면 생성 값에 따라 값을 설정!
package ch06.sec06.exam03;
public class Calc {
// 두 수를 선언 : 속성, 필드, 멤버 변수
int a;
int b;
// 객체 생성 시 호출되는 함수 : 생성자 함수
Calc(){
System.out.println("생성자 호출, 객체 생성됨");
System.out.println(a);
System.out.println(b);
System.out.println(this.a);
System.out.println(this.b);
}
// 생성자 함수: 객체 생성시 호출되는 함수
Calc(int a, int b){
this.a = a; // this = 이것
this.b = b;
// this.a, this.b = int a, int b
// 함수명, 타입, 값의 갯수!
// 함수명 중복정의 : 함수명이 같아도 사용하는 인자 수가 다르면 괜춘함
// this에서 변수 찾는 개념 : 지역변수 > 멤버변수!
}
public int add() {
return a+b;
//return 문은 두번 이상 사용못함!
}
}
package ch06.sec07.exam01;
public class CalcExam {
public static void main(String[] args) {
// TODO Auto-generated method stub
Calc c1 = new Calc();
// 인자를 넣지 않은 기본생성자 함수 호출
Calc c2 = new Calc(1,2);
// 인자를 넣은 일반생성자 함수 호출
c1.sum();
// 인자값이 들어있지 않기 때문에 모두 0이 출력됨
System.out.println(c2.sum());
// 인자값이 들어있지 않은 기본 메소드
// c2에서 매개변수가 멤버변수에 대입되었기 때문에 값이 출력됨 (3 출력)
System.out.println(c2.sum(3,4));
// 인자값이 들어있는 일반 메소드
// 메소드 안의 인자값을 통해 값을 출력함 (7 출력)
}
}
중복 정의
-> 매개변수를 달리하는 생성자를 여러 개 선언하는 것!
-> 매개변수의 타입, 개수, 선언된 순서가 똑같을 경우 매개변수 이름만 바꾸는 것은 생성자 오버로딩이 아님!
-> 생성자가 오버로딩되어 있을 경우, new 연산자로 생성자를 호출할 때 제공되는 매개값의 갯수에 따라 실행될 생성자가 결정
package ch06.sec07.exam02;
public class Calc {
int a;
int b;
int c;
int d;
Calc(){ //인자가 없는 기본생성자 생성
System.out.println("기본 생성자");
}
Calc(int a, int b){ // 인자가 2개인 일반생성자 생성
this.a = a;
this.b = b;
}
Calc(int a, int b, int c){ // 인자가 3개인 일반생성자 생성
this.a=a;
this.b=b;
this.c=c;
}
Calc(int a, int b, int c, int d){ // 인자가 4개인 일반생성자 생성
this.a=a;
this.b=b;
this.c=c;
this.d=d;
}
public int sum() {
// 인자를 모두 더하는 기본메소드
// 반드시 같은 타입의 값으로 리턴해야함
// 만약에 두 개나 세 개의 수를 넣는 생성자를 사용하더라도
// 값이 들어 있지 않은 멤버변수의 초기값은 0이기 때문에 0을 더하게 됨
return a+b+c+d;
}
}
package ch06.sec07.exam02;
public class CalcExam {
public static void main(String[] args) {
Calc c1 = new Calc(); // 기본생성자 호출
Calc c2 = new Calc(1, 2); // 인자값이 2개인 일반생성자 호출
Calc c3 = new Calc(1, 2, 3); // 인자값이 3개인 일반생성자 호출
Calc c4 = new Calc(1, 2, 3, 4); // 인자값이 4개인 일반생성자 호출
System.out.println(c2.sum()); // 기본메소드에서 값을 리턴함
System.out.println(c3.sum()); // 기본메소드에서 값을 리턴함
System.out.println(c4.sum()); // 기본메소드에서 값을 리턴함
}
}
-> 다음은 자동차를 예시로 든 오버로딩 구문이다.
package ch06.sec07.exam04;
public class Car {
// 멤버변수
String company = "현대자동차";
String model;
String color;
int maxSpeed;
// 인자값 x 기본생성자
Car(){}
// 인자값 1개인 일반생성자
Car(String model){
this.model = model;
// this = 멤버변수에 인자값을 대입
}
// 인자값 2개인 일반생성자
Car(String model, String color){
this.model = model;
this.color = color;
// this = 멤버변수에 인자값을 대입
}
// 인자값 3개인 일반생성자
Car(String model, String color, int maxSpeed){
this.model = model;
this.color = color;
this.maxSpeed = maxSpeed;
// this = 멤버변수에 인자값을 대입
}
}
package ch06.sec07.exam04;
public class CarExample {
public static void main(String[] args) {
Car c1 = new Car();
// 기본생성자
System.out.println(c1.company);
// 현대자동차
Car c2 = new Car("자가용");
// 인자가 1개인 일반생성자
System.out.println(c2.company);
System.out.println(c2.model);
// model 멤버변수만 값이 대입되었기 때문에 model 값만 출력
Car c3 = new Car("자가용", "빨강");
// 인자가 2개인 일반생성자
System.out.println(c3.company);
System.out.println(c3.model);
System.out.println(c3.color);
// model, color 멤버변수에 값이 대입됨으로서 두 값이 출력
Car c4 = new Car("택시", "검정", 200);
System.out.println(c4.company);
System.out.println(c4.model);
System.out.println(c4.color);
System.out.println(c4.maxSpeed);
// model, color, maxSpeed 멤버변수에 값이 대입됨으로서 모든 값이 출력
// 인자의 타입에 맞게 순서대로 매개값을 입력하기!
}
}
-> 실행해볼 해당 라인 더블 클릭 후 Debug 실행
-> F6 누르면서 코드 한줄씩 실행

-> 전체 실행하면 오른쪽 Variables에 위에 사진처럼 나옴
-> 세모 모양의 변수는 멤버변수
-> L 동그라미 모양은 참조형 변수
-> 생성자 오버로딩이 많아질 경우 생성자 간의 중복된 코드가 발생할 수 있기 때문에 이를 막기 위해 만들어짐
-> 이 경우 공통코드를 한 생성자에만 집중적으로 작성하고, 나머지는 this()를 사용해 공통 코드를 가진 생성자를 호출!
-> this 연산자의 호출 방법
-> this(값1, 값2, ..) 의 경우 하나만 만들어야함!
package ch06.sec07.exam05;
public class Car {
// 멤버변수
String company = "현대자동차";
String model;
String color;
int maxSpeed;
// 인자가 없는 기본생성자
Car(){
this("자가용", "파랑", 300);
// this : 자신을 뜻하며 this() 괄호 안에 값들을 집어넣으면
// 인자가 가장 많은 일반생성자에 멤버변수 값을 모두 초기화시킴
// 자동적으로 인자가 가장 많은 일반생성자로 이동하여 값을 대입함
}
// 인자가 1개인 일반생성자
Car(String model){
this(model, "검정", 250);
// this : 자신을 뜻하며 this() 괄호 안에 값들을 집어넣으면
// "검정"과 250의 경우 멤버변수 color와 maxSpeed에 값이 대입됨
}
// 인자가 2개인 일반생성자
Car(String model, String color){
this(model, color, 250);
// 250의 경우 멤버변수 maxSpeed에 값이 대입됨
}
// 인자가 3개인 일반생성자
Car(String model, String color, int maxSpeed){
this.model = model;
this.color = color;
this.maxSpeed = maxSpeed;
// 인자 값들을 모두 멤버변수에 대입함!
}
public void print(String name) {
System.out.println(name + ".company: " + this.company);
System.out.println(name + ".model: " + this.model);
System.out.println(name + ".color: " + this.color);
System.out.println(name + ".maxSpeed: " + this.maxSpeed);
}
// void print : 출력을 위한 함수로 return 값을 받지 않고 동작함
}
package ch06.sec07.exam05;
public class CarExam {
public static void main(String[] args) {
Car c1 = new Car("자가용");
// 인자가 1개인 일반생성자 호출
c1.print("c1");
// 임의로 만든 print 함수를 이용하여 출력
// c1.company : 현대자동차
// c1.model : 자가용
// c1.color : 검정
// c1.maxSpeed : 250
Car c2 = new Car("자가용", "은색");
// 인자가 2개인 일반생성자 호출
c2.print("c2");
// 임의로 만든 print 함수를 이용하여 출력
// c2.company : 현대자동차
// c2.model : 자가용
// c2.color : 은색
// c2.maxSpeed : 250
Car c3 = new Car("자가용", "빨강", 200);
// 인자가 3개인 일반생성자 호출
c3.print("c3");
// 임의로 만든 print 함수를 이용하여 출력
// c1.company : 현대자동차
// c1.model : 자가용
// c1.color : 빨강
// c1.maxSpeed : 200
Car c4 = new Car();
// 인자가 없는 기본생성자 호출
c4.print("c4");
// 임의로 만든 print 함수를 이용하여 출력
// c4.company : 현대자동차
// c4.model : 자가용
// c4.color : 파랑
// c4.maxSpeed : 300
}
}