우리 주변의 모든것이 객체이다. 객체 지향 언어는 클래스와 객체개념을 도입하였다.
//클래스
class Animal{
String name; //필드
int age; //필드
void eat(){...}; //메소드
void speak() {...}; //메소드
void love() {...}; //메소드
}
객체를 캡슐로 싸서 그 내부를 보호하고 볼 수 없게함(실제 구현을 외부로부터 숨김)
그러나 외부와의 접속을 위해 몇 부분만을 공개 노출한다.
(public and private)
상속 : 상위 개체의 속성이 하위 개체에 물려져서 하위 개체가 상위 개체의 속성을 모두 가지는 관계
-> 코드 재사용성 향상 및 유지보수 시간 최소화
class Animal{
String name;
int age;
void eat(){}
void speak(){}
void love(){}
}
class Human extends Animal{
String hobby;
String job;
void work() {...}
void cry() {...}
void laugth() {...}
}
Human클래스는 Animal 클래스를 상속받아서, age필드 love()메소드 등을 똑같이 가진다.(다시 선언할 필요X)
같은 이름의 메소드가 클래스 혹은 객체에 따라서 다르게 동작함
메소드 오버로딩 : 클래스 내에서 같은 이름의 메소드를 여러개 만든다.
각각은 다른 파라미터를 가진다.
-> 메소드 오버로딩은 컴파일 시간에 결졍됨(static polymorphism)
메소드 오버라이딩: 슈퍼클래스에서 구현된 메소드를 서브 클래스에서 자신의 이름에 맞게 동일한 이름으로 다시 구현하는 것
-> 메소드 오버라이딩은 런타임에 결정됨(dynamic polymorphism)
실세상의 물체를 객체로 표현하고, 이들사이의 관계, 즉 상호작용을 프로그램으로 나타냄.
Field, Consturctor, Method 3가지로 구성된다.
public class Circle{
int radius;
String name;
public double gertArea(){
return 3.14*radius*radius;
}
public static void main(String[] args){
Circle pizza;
pizza = new Circle();
pizza.radius = 10;
pizza.name = "자바피자";
double area = pizza.getArea();
System.out.println(pizza.name + "의면적은" + area);
}
}
- 객체에 대한 레퍼런스 변수 선언 : Circle pizza;
- 객체 생성: pizza = new Circle();
- new 연산자는 어딘가에서 Circle타입의 크기 만한 메모리 할당받아 그 메모리에 대한 주소를 pizza에 리턴한다. : Circle pizza = new Circle();
생성자는 객체개 생성될 때 초기화를 위해 실행되는 메소드이다.
-> 생성자는 '화장'과 비슷하다. 맨얼굴(얼굴객체)
public class Circle{
int radius;
String name;
public Circle() {
radius=1; name="";
}
public Circle(int r, String n){
radius = r; name = n;
}
public double gertArea(){
return 3.14*radius*radius;
}
public static void main(String[] args){
Circle pizza = new Circle(10, "자바피자");
double area = pizza.getArea();
System.out.println(pizza.name + "의면적은" + area);
Circle donut = new Circle();
donut.name = "도넛피자";
area = pizza.getArea();
System.out.println(donut.name + "의면적은" + area);
}
}
생성자의 이름은 클래스 이름과 동일하다.(다른 메소드와 쉽게 구분할 수 있음)
생성자를 여러개 작성할 수 있다.(매개변수의 개수와 타입이 다름)
생성자는 객체를 생성할 때 한번만 호출된다.(객체 생성시 자동으로 호출)
생성자에 리턴타입 지정할 수 없음(리턴 없음)
매개변수가 없고 실행코드도 없음
class Circle{
public Circle() {}
}
컴파일러는 생성자가 하나도 없으면 바이트코드 파일(*.class)에 기본 생성자를 삽입해서 기본생성자가 호출되게 한다
그러나 기본생성자외에 생성자가 하나라도 있으면 기본생성자를 삽입해주지는 않음(그 이미 있는 생성자를 호출한다)
객체 자신에 대한 레퍼런스임(객체가 있어야 this도 의미가 있음)
메소드 안에서 사용된다.
public class Book{
String title;
String author;
public Book(){
this("", "");
System.out.println("생성자 호출됨");
}
public Book(String title){
this(title, "작자미상");
}
public Book(String title, String author){
this.title = title;
this.author = author;
}
public static void main(String[] args){
Book littlePrince = new Book("어린왕자", "생텍쥐페리");
Book loveStory = new Book("춘향전");
Book emptyBook = new Book();
}
}
1) 먼저 인자 2개짜리 생성자가 호출됨(인자로 전달된것이 객체에 담긴다) -> littlePrince가 그 객체의 레퍼런스가 된다.
2) 그다음은 인자 1개짜리 생성자가 호출됨, this는 다른 생성자를 호출함(인자2개짜리) -> Book("춘향전", "작자미상")이렇게 호출됨
자바에서는 객체를 원소로 하는 배열을 만들 수 있다.
레퍼런스를 원소로 갖는 배열임
Circle [] c = new Circle[5];
for(int i=0; i<c.length; i++)
c[i] = new Circle(i);
- 배열의 원소는 객체가 아니라 Circle 객체에 대한 레퍼런스임
즉 c는 레퍼런스 변수이다.
(즉 각 객체5개를 가리킬 레퍼런스를 5개 만든것임)- 그 후, Circle 객체를 하나씩 생성하여 배열 c[]의 각 레퍼런스에 대입한다.

자바의 메소드 호출시 인자전달방식은 call-by-value 이다. (실인자의 값이 복사되어 메소드의 인자로 전달됨)
int, char, byte 등은 그냥 매개변수에 값이 복사되어 전달됨
메소드의 매개변수가 클래스 타입인 경우는 객체의 레퍼런스값이 전달된다.
즉 객체의 레퍼런스값이 복사되어 전달됨
public class ReferencePassing{
public static void main (String args[])
{
Circle pizza = new Circle(10);
increase(pizza);
}
static void increase(Circle m){
m.radius++;
}
}

이것 역시 객체와 마찬가지로 배열에 대한 레퍼런스만 전달된다.
메소드 오버로딩(method overloading): 자바에서는 클래스 내에 이름이 같지만 매개변수의 타입이나 개수가 서로 다른 여러개의 메소드를 작성할 수 있다.
public class MethodSample{
public int getSum(int i, int j){
return i + j;
}
public int getSum(int i, int j, int k){
return i + j + k;
}
public double getSum(double i, double j){
return i + j;
}
}
public class Samp{
public Samp(int x) {this.id = x;}
public static void main(String[] args)
{
Samp ob1 = new Samp(3);
Samp ob2 = new Samp(4);
Samp s;
s = ob2;
ob1 = ob2;
System.out.println("ob1.id="+ob1.get());
System.out.println("ob2.id="+ob2.get());
}
}
-> ob1은 가리킬 것이 없어지고 ob1이 가리키던 객체는 가비지가 된다.

객체 생성 : new 연산자
객체 소멸 : X
-> 개발자가 마음대로 객체를 소멸시킬 수 없다.
자바에서는 JVM이 알아서 "사용하지 않고 있는 객체나 배열 메모리"를 수거한다.(개발자의 부담 줄어든다)
할당받은 객체나 배열 메모리 중에서 더 이상 사용하지 않게 된 메모리를 가비지라고 함.
1> 가비지가 많아지면 응용프로그램에게 할당해줄 수 있는 가용메모리의 양이 줄어든다.
2> 가용메모리의 양이 일정 크기 이하로 줄어들면 JVM이 가비지를 회수하여 가용메모리 공간을 늘린다.(가비지 컬렉션)
-> 실시간 프로그램에서 가끔 일시적으로 프로그램이 실행중에 중단되는 경우가 있다.
(자바프로그램이 실행을 멈추고 가비지 컬렉션이 끝나기를 기다린다.)
System.gc(); //가비지 컬렉션 자동 요청
이 코드로 가비지 컬렉션을 강제 수행시킬 수 있다.
자바에서는 상호 관련 있는 클래스 파일들을 패키지(package)에 저장하여 관리한다.
패키지 이름은 모두 소문자로 쓰인다.
접근 지정자는 클래스나 멤버들을 다른 클래스에서 접근해도 되는지의 여부를 선언하는 지시어이다.
1> private
2> protected
3> public
4> 접근 지정자 생략(디폴트 접근 지정)
패키지와 상관없이 다른 어떤 클래스에게도 사용이 허용됨
public class World{
}
오직 같은 패키지 내에 있는 클래스들에게만 사용이 허용됨
class Local{
}
패키지를 막론하고 모든 클래스들이 접근 가능하다.
클래스 내의 멤버들에게만 접근이 허용됨

같은 패키지 내의 모든 클래스에서 접근이 가능함
다른 패키지에 있더라도 자식 클래스인 경우는 접근이 허용됨
동일한 패키지 내에 있는 클래스들만 디폴트 멤버를 자유롭게 접근할 수 있다.
static : 모든 객체에 1 고정되어 2 공유된다.
static int m;
static void f(){}
static 멤버는 클래스당 하나만 생성되는 멤버로서, 동일한 클래스의 모든 객체들이 공유한다.
static 멤버: 클래스 멤버
non-static 멤버 : 인스턴스 멤버
static 멤버는 프로그램을 시작할 때나 클래스 로딩 시에 생성된다. 즉 객체를 생성하기 전에도 static 멤버는 사용할 수 있다.
-> 따라서 static 멤버는 클래스 이름만으로 해당 필드나 메소드에 접근할 수 있다.
public class A{
class Sample{
static int m = 0;
}
public static void main(String[] args){
Sample.m = 3; //바로 클래스이름으로 접근
}
}
또한 객체가 소멸된 후에도 static 멤버는 살아 공간을 차지한다.
static 멤버는 프로그램이 종료될때 소멸된다.
반면 non-static a멤버는 객체가 생길때 함께 생성되고 객체가 사라지면 함께 사라진다.(생명주기를 객체와 함께 함)
자바에서는 어떤 변수나, 함수도 클래스 바깥에 존재할 수 없다. 따라서 전역변수나 전역함수를 만들고자 한다면 static으로 선언한다.
static으로 선언된 필드나 메소드는 이 클래스의 객체들 사이에서 공유된다.
예를 들어, 만약 Counter라는 클래스에 static int count = 0;이라는 필드가 있다면, Counter의 모든 인스턴스는 이 count 필드를 공유하게 된다. 어떤 인스턴스가 이 필드 값을 변경하면, 다른 모든 인스턴스에 대해서도 그 변경이 보여진다. 이는 static 필드가 클래스에 속하고 모든 인스턴스에 의해 공유된다는 사실을 반영한다. -> 객체로 여러개 찍어도 그냥 static은 다같이 공유된다.
static은 정적영역에 컴파일되면서 상주한다. 반면 인스턴스 메소드는 객체를 선언해야 사용할 수 있다. 따라서 객체를 선언하지 않고 인스턴스 메소드를 사용하면 이것은 사용할 수 없는 것이다.
따라서 객체를 선언하고 이를 사용해야한다.
인스턴스 메소드에서, 인스턴스 메소드는 사용가능하다
static 메소드는 객체 없이도 존재하기 때문임
final이 클래스 이름 앞에 사용되면 클래스를 상속받을 수 없음을 지정한다.
final class FinalClass{
}
class SubClass extends FinalClass{
}
메소드 앞에 final이 붙으면 이 메소드는 더이상 오버라이딩 할 수 없음을 지정함
-> 즉 부모클래스의 특정 메소드를 오버라이딩 못하게 하고 상속은 받고 싶다면 사용한다.
public class SuperClass{
protected final int finalMethod(){...}
}
class SubClass extends SuperClass{
protected int finalMethod() {...}
}
final로 필드를 선언하면 필드는 상수가 된다.
public class FinalFieldClass{
final int ROWS = 10;
void f(){
int[] int Array = new int[ROWS];
ROWS = 30; // 컴파일 오류
}
}
만약 final 키워드를 public static과 함꼐 선언하면, 프로그램 전체에서 공유할 수 있는 상수가 됨.
class SharedClass{
public static final double PI = 3.14;
}
double area = SharedClass.PI*radius*radius;