- 클래스의 구조
- 필드
- 객체 데이터, 상태 저장하는 변수
- 멤버 변수
- Goods.java
package com.javaex.oop.goods.v1; public class Goods { // 필드 String name; int price; }
- GoodsApp.java
-
결과package com.javaex.oop.goods.v1; public class GoodsApp{ public static void main(String [] args) { Goods camera = new Goods(); camera.name = "nikon"; camera.price = 400000; Goods smartphone = new Goods(); smartphone.name = "iPhone 13"; smartphone.price = 1000000; System.out.println("이름 : " + camera.name + "\n가격 : " + camera.price); System.out.println("이름 : " + smartphone.name + "\n가격 : " + smartphone.price); } }
이름 : nikon
가격 : 400000
이름 : iPhone 13
가격 : 1000000
- 생성자
- 객체 생성시 수행되는
- 목적 : 객체 초기화 -> heap 객체 생성 -> 조소값 받기
- 메소드
- 접근 제한자
public > protected > default > private
- public
- protected
- default
- 아무것도 안 적으면 default
- private
- 자신의 클래스 안에만 사용 가능
- 메서드
- 매개변수
- 메소드 호출에서 들어가는 구체적인 값 : 인자(Argument)
- 반환타입
- int일 때, return 비워두면 안 된다.
- 메서드 이름
- 메서드 명은 기능을 알기 쉽게 작성해야함 (ex. a, b, c, -> 무슨 기능인지 알 수 없음)
-
package com.javaex.oop.methods; public class MethodsEx { public static void main(String[] args) { //입력 x, 출력 x printMessage(); //입력 o, 출력 o double result = getSum(4,5); System.out.println("4 + 5 = "+ result); //입력 x, 출력 o //입력 o, 출력 x printTotal("합계", 1,2,3,4,5,6,7,8,9); } //고정인수, 가변 인수 private static void printTotal(String message, double ... values) { System.out.println(message+ " : " + getTotal(values)); } //가변 인수를 이용한 다수 인수 전달 private static double getTotalVar(double ... values) { return getTotal(values); } private static double getTotal(double[] values) { double total = 0; for(double value: values) { total += value; } return total; } }
- 가변 인수
- 매개 변수의 개수를 알 수 없을 때 사용
- 고정인수, 가변인수 같이 올 때 -> ① 고정인수, ②가변인수 (순서 중요)
public class MethodsEx { public static void main(String[] args) { printTotal("합계", 1,2,3,4,5,6,7,8,9); } //고정인수, 가변 인수 private static void printTotal(String message, double ... values) { System.out.println(message+ " : " + getTotal(values)); } private static double getTotal(double[] values) { double total = 0; for(double value: values) { total += value; } return total; } }
- Getter, Setter
- 객체 외부에서 직접적으로 접근하는 것을 막음
Goods.java
-
Goods.App.javapackage v2; public class Goods { // 필드 private String name; private int price; //외부 접근 방식 노출 // getter/setter // getter : 데이터 참조하기 위함 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void showInfo() { System.out.println("상품이름 : " + name); System.out.println("가격 : "+ price); } }
package v2; public class GoodsApp{ public static void main(String [] args) { Goods camera = new Goods(); camera.setName("nikon"); camera.setPrice(400000); Goods smartphone = new Goods(); smartphone.setName("iPhone 13"); smartphone.setPrice(1000000); // System.out.println("이름 : " + camera.getName() + "\n가격 : " + camera.getPrice()); camera.showInfo(); // System.out.println("이름 : " + smartphone.getName() + "\n가격 : " + smartphone.getPrice()); smartphone.showInfo(); } }
생성자
- 생성자를 실행시키지 않고 클래스로부터 객체 만들 수 없다.
- void 안 씀
- setter가 없으면 readOnly
this
- 현재 사용중인 instance 자신
- this() : 현재 인스턴스에 있는 다른 생성자 호출
public Goods(String name) { this.name = name; } // 생성자 2. public Goods(String name, int price) { this(name); // 다른 생성자 호출 this.price = price; }
메소드 오버로딩
- 하나의 클래스에 같은 이름의 메소드 존재 가능
static, instance, local
- static :
- 클래스 영역
- 해당 클래스로 만들어진 인스턴스
- new 아니라도 접근 가능
- static내에서는 static 멤버만 접근 가능
- static -> instance 접근 (x)
public class StaticEx { public static int refCount; // 클래스(static) 멤버 public static String classVar; // 클래스 멤버 public String instanceVar; // 인스턴스 멤버 // static 블록으로 static 영역의 초기화 static { refCount = 0; classVar = "static Member"; //instanceVar = "Instance Member"; -> 에러 // 중요 : sataic 영역에서는 static 만 접근 가능 } }
- static -> instance 접근 (x)
- instance
- 클래스 영역
- new 키워드로 인스턴스 사용
- 인스턴스 내에서 사용
- instance -> static영역 접근 가능
public class StaticEx { public static int refCount; // 클래스(static) 멤버 public static String classVar; // 클래스 멤버 public String instanceVar; // 인스턴스 멤버 // static 블록으로 static 영역의 초기화 static { refCount = 0; classVar = "static Member"; //instanceVar = "Instance Member"; -> 에러 // 중요 : sataic 영역에서는 static 만 접근 가능 } StaticEx(){ // 참조 카운트 증가 // 인스턴스 멤버 -> sataic 멤버 접근 가능 refCount++; System.out.println("인스턴스 갯수 : " + refCount); } }
- StaticEx.java
StaticApp.javapackage com.javaex.oop.staticmember; public class StaticEx { public static int refCount; // 클래스(static) 멤버 public static String classVar; // 클래스 멤버 public String instanceVar; // 인스턴스 멤버 // static 블록으로 static 영역의 초기화 static { refCount = 0; classVar = "static Member"; //instanceVar = "Instance Member"; -> 에러 // 중요 : sataic 영역에서는 static 만 접근 가능 System.out.println("static Block"); } StaticEx(){ // 참조 카운트 증가 // 인스턴스 멤버 -> sataic 멤버 접근 가능 refCount++; System.out.println("인스턴스 갯수 : " + refCount); System.out.println("생성자 호출 : 인스턴스 생성"); } }
-
package com.javaex.oop.staticmember; public class StaticApp { public static void main(String[] args) { StaticEx s1 = new StaticEx(); //static 멤버는 new 없이 접근 가능 System.out.println("RefCount"+ StaticEx.refCount); StaticEx s2 = new StaticEx(); System.out.println("RefCount"+ StaticEx.refCount); } }
- static영역 먼저 실행
- StaticApp의 생성자 실행
- StaticApp mian의 프린트 실행
- 객체 초기화 : null 로 설정해주면 됨 (heap 메모리에 남아있지만, GTC를 통해 없어짐)
// 소멸자 @Override protected void finalize() throws Throwable{ refCount--; System.out.println("소멸자 호출"); super.finalize(); }
가비지 수집기 : 사용하지 않은 메모리를 자동적으로 회수하는 서비스GC클래스 : 가비지 수집기 제어// 주의 : 가비지 컬렉터를 직접 호출하지 않는다. System.gc(); try { Thread.sleep(3000);//3초간 대기 }catch(Exception e) {
- local 영역
- 메서드 영역
- 메소드 내에서 사용
- 벗어나면 찾을 수 없음
singleton (static의 활용)
- 단 하나의 인스턴스만 유지
- 함부러 생성자 호출 불가능하게 -> 생성자를 private로
- 단 한번만 수행 -> static으로 객체 만들기
Singleton.java
package com.javaex.oop.staticmember;
// 목표 : 어떤 상황에서든 단 한개의 인스턴스만 유지
public class Singleton {
// 생성자
private Singleton() {
}
}
SingletonApp.java
package com.javaex.oop.staticmember;
public class SingletonApp {
public static void main(String[] args) {
Singleton s1 = new Singleton(); // 생성 불가
}
}
- static 블록에서 생성자 호출
- Singleton.java
package com.javaex.oop.staticmember;
// 목표 : 어떤 상황에서든 단 한개의 인스턴스만 유지
public class Singleton {
// static 블록에서 생성자를 호출
private static Singleton instance = new Singleton();
// 생성자
private Singleton(){
}
public static Singleton getInstance() {
return instance;
}
}
- SingletonApp.java
package com.javaex.oop.staticmember; public class SingletonApp { public static void main(String[] args) { // private static s1 = new Singleton(); // 생성 불가 Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); //객체 주소가 같으면 같은 객체다. System.out.println("s1, s2 같은 객체? " + (s1 == s2)); } }
상속 ( Inheritance )
- 클래스간 계층적 분리 및 관리 가능
- 중복 상속을 제거한다. (오직 하나만 상속한다.)
- ex) 엄마, 아빠 클래스 중 뭐 쓸까 고민,,하는거 안 해도 됨
- 가급적으로는 상속 배제하도록
- 상속의 깊이이가 길어지면 유지보수가 어려워진다.
- 최상위 클래스 : java.lang.Object
- 자식 생성자에서 특별한 지시가 없으면 부모 클래스의 기본 생성자가 선택됨
- 부모의 특정 생성자 사용시에는 명시 해줘야한다. -> super(x,y);
- 부모의 필드나 메서드에 접근시에는 super 키워드 사용
메서드 오버라이딩 (Method Overriding)
- 물려받은 것을 사용하지 않고, 다른 기능 사용하는 것
- 같은 이름, 같은 리턴타입, 같은 시그너쳐
- 부모 메서드 무시
- @Overriding ( 일종의 지시자 )
- 매서드 앞에 명시 -> 부모에게 메서드가 있는가?
- 진짜로 오버라이딩 한 건가?
- 컴파일러에게 맡김
- 시그너쳐 위반 했는지 안 했는지
- 매서드 앞에 명시 -> 부모에게 메서드가 있는가?
- 객체를 참조하고자 할 때
- 자식 객체를 부모 타입으로 참조할 수 있다.
- 부모 참조
- person p1 = new Student( );
- 참조 타입(person) 설계도 내의 메서드만 호출 가능
- p1.getName( ) (O)
- p1.getSchoolName( ) (X) -> person에 없음
- p1.showInfo( ) -> 오브라이딩 된 자식 클래스의 메소드
- person p1 = new Student( );
- 자기자신 타입으로 참조
- Studnet s1 = new Student( );
- s1.getName( ) (O)
- s1.getSchoolName( )
- s1.showInfo( ) -> 자기자신의 오버라이딩 된 메소드
- Studnet s1 = new Student( );
- 다형성의 일부
- ex) 주소록을 만들 때,
- Student[] s = new Studnet[3];
- s[0] = new Student( );
- s[1] = new Student( );
- s[2] = new Person( ); -> 안 됨
- ex2 ) 주소록
- Person p[] = new Person[3];
- p[0] = new Student( );
- p[1] = new Student( );
- p[2] = new Person( ); (O)
- ex) 주소록을 만들 때,
- 부모 타입으로 자식객체를 참고할 수 있다.
- override해도 부모의 메소드 사라지지 않는다.
- point.v4패키지
- Point.java
package point.v4; // v4. 상속 public class Point { protected int x; protected int y; // 기본 생성자 : 매개 변수가 없는 // public Point() { // // } // // 전체 필드 초기화 생성자 public Point(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public void draw() { System.out.printf("점[x=%d, y=%d]을 그렸습니다.\n",x,y); } //메서드 오버로딩 //매개변수 타입, 갯수, 순서가 같은 이름의 메서드 public void draw(boolean bDraw) { String message = String.format("점[x=%d, y=%d]을 ", x, y); if(bDraw) { // true라면 message += "그렸습니다."; }else { message += "지웠습니다."; } System.out.println(message); } }
- ColorPoint.java
package point.v4; // 상속 public class ColorPoint extends Point{ private String color; // 생성자 public ColorPoint(int x, int y, String color) { super(x,y); this.color = color; } @Override // 컴파일러에게 이 메서드가 오버라이딩한 메서드인지 확인 public void draw(boolean bDraw) { //부모로부터 물려 받은 메서드를 덮어 쓰기 String message = String.format("색깔점[x = %d, y = %d, color = %s]을 ", x, y, color); message += bDraw ? "그렸습니다.":"지웠습니다"; System.out.println(message); //부모의 메서드 호추하려면 super.draw(bDraw); } }
- PointApp.java
package point.v4; public class PointApp { public static void main(String[] args) { Point p = new Point(4,4); p.setX(10); p.setY(20); p.draw(); p.draw(true); p.draw(false); Point p2 = new Point(60,40); p2.draw(); p2.draw(true); p2.draw(false); ColorPoint cp1 = new ColorPoint(10,20,"RED"); cp1.draw(true); // 다형성 : 부모타입으로 자식객체 참조 Point cp2 = new ColorPoint(30, 40,"RED"); cp1.draw(true); } }
- Point.java
- 위의 같은 경우에서 point.java의 매개변수 없는 생성자와, ColorPoint의 매개변수 없는 생성자를 만들고 실행시키면, point 생성자 먼저 실행되고, ColorPoint 생성자가 실행된다.
- 그렇지만, Point의 생성자를 만들지 않고 ColorPoint의 생성자를 만들면 오류생긴다.
업캐스팅, 다운 캐스팅
특정 객체 다운 캐스팅 할 때, instanceof로 확인해라.
casting 패키지
Animal.java
package com.javaes.oop.casting;
public class Animal {
protected String name;
// 생성자
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + " is eating");
}
public void walk() {
System.out.println(name + " is walking");
}
}
Dog.java
package com.javaes.oop.casting;
public class Dog extends Animal{
//생성자 Animal 없어서 오류났음 -> 생성자 ㅏ만들어줘야 함
public Dog(String name) {
//부모생성자의 일부 호출해줘야한다.
super(name);
}
public void bark() {
System.out.println(name + ": 멍멍!");
}
}
Cat.java
package com.javaes.oop.casting;
public class Cat extends Animal{
public Cat(String name) {
super(name);
}
public void meow() {
System.out.println(name + ": 야옹!");
}
}
AnimalApp.java
package com.javaes.oop.casting;
public class AnimalApp {
public static void main(String[] argv) {
// 업 캐스팅, 다운 캐스팅
Dog dog1 = new Dog("스누피");
dog1.eat();
dog1.walk();
dog1.bark();
// 업 캐스팅 : 참조 자료형에 있는 설계된 멤버에만 접근 가능
Animal dog2 = new Dog("아지");
dog2.eat();
dog2.walk();
// dog.bark(); //오류남
// 다운 캐스팅
// animal -> dog로
((Dog)dog2).bark(); // 일시적으로 변환
// 업 캐스팅
Animal cat1 = new Cat("야옹이");
cat1.eat();
cat1.walk();
// ((Dog)cat1).bark();// 오류남,,-> cat과 Dog 서로 캐스팅 안 됨
if(cat1 instanceof Dog) { //cat1이 Dog의 인스턴스인가?
((Dog)cat1).bark();
}else if(cat1 instanceof Cat){ // cat1이 Cat의 인스턴스?
((Cat)cat1).meow();
}
// Dog[] pets = new Dog[3];
Animal[] pets = new Animal[3];
pets[0] = dog1;
pets[1] = (Dog)dog2;
pets[2] = new Dog("멍멍이");
// pets[3] = new Cat("아즈라엘");// 오류남
for(Animal pet : pets) {
pet.eat();
pet.walk();
if(pet instanceof Dog) {
((Dog)pet).bark();
}else if(pet instanceof Cat)
((Cat)pet).meow();
}
}
}
- 다운 캐스팅 : 자료형에 있는 설계된 멤버만 접근 가능
- Animal dog2 = new Dog()
- 이면, Dog에만 있는 dark()는 오류가 난다.
- 같은 부모를 상속하는 자녀 사이에 캐스팅이 안 된다.
- Cat과 Dog는 서로 캐스팅이 안 됨
- Dog[] pets = new Dog[3];을 한 뒤,
- pets[3] = new Cat() -> 오류난다.
- Dog객체에 Cat을 넣었기 때문.
'study > JAVA 전문가' 카테고리의 다른 글
인터페이스 (0) | 2021.12.07 |
---|---|
예외 (0) | 2021.12.07 |
추상 클래스 (0) | 2021.12.07 |
[모의 필기테스트] 오답노트 & 정리 (0) | 2021.12.07 |
[DAY+2]Java Programming (0) | 2021.12.03 |