Java - accidentlywoo/sec GitHub Wiki
Java 정리
객체지향 프로그래밍을 하자!
- 목적 : 클래스 재사용성을 높이자.
객체지향언어의 조건
-
상속 단일 상속
extends : class 하위클래스 extends 상위클래스{}
상속은 "Is A"||"Kind Of" 관계일때 사용한다. 논리적인 설계를 하자!
"Has A"관계로 표현할 수 있어야 한다.
-
캡슐화 - 접근제어
-
다형성
접근제어
- public : 누구나
- protected : 동일 패키지에서 접근가능, 다른 패키지의 하위클래스에서 접근가능
- deault(package) : 동일 패키지에서 접근가능
- private : 자기자긴만 쌉 가능
캡슐화
은닉된 정보에 접근할 수 있는 기능을 제공한다. 설정(set) / 얻기(get)
컴포넌트[JavaBean]
자바빈이 되기위한 조건 4가지.
-
public class
-
public 매개변수없는 새성자
-
프로퍼티용 인스턴스변수는 public 이면 안됨
-
프로퍼티용 public setter 메서드 / public getter 메서드
public class Star{
private String color;
private String size;
public void setColor(String color) {
// 설정 제어문 작성
this.color = color;
}
public String getColor(){return color;}
}
정적 멤버와 static
클래스 로딩시 초기화된다. this 키워드 사용불가. 클래스 이름으로 접근하는게 메모리 효율에 좋다.
class Single{
static int sv;
private Single() {}
static void plus(int i) {
sv = sv+i;
}
static Single getInstance() {
return new Single();
}
}
class Main{
public static void main(String[] args) {
System.out.println(Single.sv);
Single s1 = Single.getInstance();
System.out.println(s1.sv);
}
}
static 필드를 인스턴스화해서 인스턴스 객체로 접근하면 스택에서 힙영역을 뒤지고 없으면 ClassArea를 뒤지기 때문에 효율이 떨어진다.
System.out.println(s1.sv); //효율 쌉 손해, IDE에서 warning을 표시한다.
System.out.println(Single.sv); // 이렇게 사용하자.
lass Single{
int iv;
static int sv;
private Single() {}
static void test() {
// System.out.println(this);
// System.out.println(iv);
// System.out.println(this.iv);
// System.out.println(plus);
// System.out.println(this.plus);
}
static void plus(int i) {
sv = sv+i;
}
static Single getInstance() {
return new Single();
}
}
static method는 인스턴스화한 객체의 method영역에서 메서드 시그니처가 없다. class Area에서 뒤적거림
static method를 사용함으로써 장점을 뽑을 수 있는 메소드
- 유틸 클래스
- 정적 팩토리 메서드
- 빌더 패턴
- 싱글톤
상속
힙 메모리를 그릴때, 자식객체의 메모리안에 부모객체의 영역이 먼저 생긴다. (책이 잘못됨. 따로 생겨서 상속받거나 그렇지 않다.)
Is A 관계
class Person{
String name;
String addr;
}
class Customer extends Person{
String id;
String pwd;
}
Customer은 Person이다.
class Person{
String name;
String addr;
}
class Account extends Person{
String id;
String pwd;
}
Account는 Person이 아니다.
Has A 관계
class Person{
String name;
String addr;
}
class Account{
String id;
String pwd;
Person PersonInfo;
}
Account는 Person정보를 갖는다.
상속시 멤버필드명 중복
class GrandParent{
int i;
}
class Parent extends GrandParent{
String i;
void pm(){
super.i = 10;
}
}
class Child extends Parent{
boolean i;
void m(){
this.i = true;
super.i = "hello";
pm();
}
}
new Child().i = false;
super 키워드는 현재 객체에서 부모객체에 접근.
super() 부모 생성자 호출하라!
다형성의 개념을 체크하자.
- auto up casting
- 강제 down casting
오버라이드 규칙
- 상속관계 메서드
- 메서드명 동일, 매개변수(자료형, 개수, 순서) 동일, 반환형도 동일
- 상위 메서드 접근범위 <= 하위메서드 접근범위
class P{ // 컴파일러에서 class P extends Object{ 로 변환
void m(){}
void m1(){}
}
class C extends P{
public void m(){}
private void m1(){} // 컴파일 오류
}
- 예외선언
Object 최상위 객체
Object
- +hashCode():int
- +toString():String
- +equals(Object):boolean
String
- +hashCode():int
- +toString():String
- +equals(Object):boolean
StringBuffer
- +toString():String
Final Class 와 Abstract Class
클래스의 역할
- 객체를 만드는 틀(final class)
- 하위 클래스들의 공통점을 모아둠(abstract class)
일반적인 클래스들은 이둘의 특징을 모두 갖는다.
Final Method 와 Abstract Method
- final 메서드 : 재정의(overriding 못함) 금지
- abstract 메서드 : 반드시 재정의 필요, 추상 메소드를 갖고있는 클래스는 반드시 추상 클래스여야 한다.
Abstract Class
new 키워드를 사용해서 인스턴스화 할 수 없다.
생성자가 있는데 protected 접근 제어자가 붙어있다.
-> 하위 클래스에서 확장했을때, 생성자가 필요하기 때문에 만들어져있다.
ex) Abstract Class 인 Calendar 클래스는 Calendar(), Calendar(TimeZone zone, Locale aLocale) 생성자가 있는다.
Calendar 클래스의 하위 클래스인 GregorianCalendar는 Calendar.getInstance()로 인스턴스화할 수 있다.
GregorianCalendar클래스는 확장한 Calendar 추상 클래스의 생성자를 사용해(super()) 생성자 활용한다!
Interface
interface A{
int A_CNT = 1;
void a();
}
interface B{
void b();
}
interface ABC extends A, B{
void abc(); // public abstract void abc();
}
class ABCImp implements ABC{
//void abc(){} 접근제어자 컴파일 에러
public void abc(){}
public void a(){}
public void b(){}
}
abstract class ABCImp2 implements ABC{} // 컴파일 에러 나지 않는다.
class ABCImp3 extends Parents implements ABC{
public void abc(){}
public void a(){}
public void b(){}
}
Exception
- 효율성을 생각하고 코드를 작성하는 것이 좋다.
ex) for문에서 Exception 체크를 해야할 때는
// Bad Code
for(int i = 0 ; i < 10000; i++){
try{
exceptionCheckPlease(i);
}catch{}
}
// good code
try{
for(int i = 0; i < 10000; i ++){
exceptionCheckPlease(i);
}
}catch{}
매번 체크하는 것보다. for문이 깨질때 catch하는 것이 좋다. (설계에 따라 다름)
Exception 에서 setMessage() 는없다. 메세지를 설정하고 싶다면?
강제로 Exception을 발생시키고, 생성자에 메시지를 담고, 클래스 생성한다.
throw new IOException("예외 발생");
throws를 JVM으로?
throws를 뒤지게 써서 main메소드까지 넘기면 JVM까지 넘길 수 있다.
멀티 Exception
디테일한 Exception catch구문을 작성하고 싶다면, 하위클래스부터 catch 구문을 작성해야 flow에 맞다.
사용자 정의 Exception
서비스단의 Exception때문에 코드가 지저분해질 수 있기때문에 사용자 정의 Exception을 작성할 수 있다.
주로 기능별, 메소드별로 만들 수 있다.