728x90
String 클래스
== 와 equals()
- == : 비교하는 두 대상의 주소값을 비교
- equals() : 비교하는 두 대상의 값을 비교
public class StringExam {
public static void main(String[] args) {
String str1 = "hello";
String str2 = "hello";
String str3 = new String("hello");
String str4 = new String("hello");
System.out.println(str1 == str2); // true
System.out.println(str1.equals(str2)); // true
System.out.println(str2 == str3); // false
System.out.println(str2.equals(str3)); // true
System.out.println(str3 == str4); // false
System.out.println(str3.equals(str4)); // true
}
}
추상 클래스
- abstract 키워드를 사용하여 클래스를 정의한다.
- 확장 만을 위한 용도로 정의되는 클래스
- 추상 클래스는 인스턴스가 될 수 없다.
- 추상 클래스를 상속받는 자손이 인스턴스가 된다.
- 추상 클래스는 보통 1개 이상의 추상 메소드를 가진다. (없어도 오류 발생은 X)
public abstract class 클래스명 { ... }
추상 메소드
- 추상 메소드는 메소드에 대한 구현을 가지지 않는다.
- 추상 클래스의 자식 클래스가 해당 메소드를 구현 하도록 강요하기 위해 존재
- 추상 메소드는 추상 클래스에만 조재할 수 있다.
✔ 추상 클래스를 사용하는 이유
- 공통된 필드와 메서드를 통일할 목적
- 필드와 메서드 이름을 통일하여 유지보수성을 높이고 통일성을 유지할 수 있다.
- 실체 클래스 구현시, 시간절약
- 강제로 주어지는 필드와 메서드를 가지고 실체 클래스의 성격대로 구현만 하면 된다.
- 설계 시간이 절약되며, 구현하는데만 집중할 수 있다.
- 규격에 맞는 실체 클래스 구현
- 공통된 속성은 규격에 맞게 구현할 수 있다는 의미
- → 추상 클래스를 상속받은 실체 클래스들은 반드시 추상 메서드를 재정의해서 실행 내용을 작성해야 하기 때문
- 그 외의 것은 자유롭게 구현이 가능하다.
→ 중요한 것은, 소스 수정시 다른 소스의 영향도를 적게 가져가면서 변화에는 유연하게 만들기 위해 추상클래스를 사용한다는 점 !
추상클래스의 상속
- 추상 클래스의 상속에도 extends 키워드 사용
- 추상 클래스를 상속하는 클래스는 반드시 추상 클래스의 추상 메소드를 구현해야 함
- 추상 클래스간의 상속에서는 추상클래스를 구현하지 않아도 됨
- 추상 클래스의 추상 메소드를 상속받아 정의하는 예시
abstract class Shape {
public abstract double calculateArea();
}
class Triangle extends Shape {
private double x;
private double y;
public Triangle(int x, int y) {
this.x = x;
this.y = y;
}
public double calculateArea() {
return this.x * this.y / 2;
}
}
class Rectangle extends Shape {
private double x;
private double y;
public Rectangle(int x, int y) {
this.x = x;
this.y = y;
}
public double calculateArea() {
return this.x * this.y;
}
}
public class ShapeDemo {
public static void main(String[] args) {
Shape triangle = new Triangle(10, 5);
System.out.println("삼각형의 너비: " + triangle.calculateArea());
Shape rectangle = new Rectangle(10, 20);
System.out.println("사각형의 너비: " + rectangle.calculateArea());
}
}
- 추상 클래스의 연속 상속
abstract class Aclass {
public abstract void Amethod(); // 추상 메소드
}
abstract class Bclass extends Aclass { // 추상 클래스를 상속받은 추상 클래스
public abstract void Bmethod();
}
public class Cclass extends Bclass {
public void Amethod() { ... } // 반드시 구현해야 함
public void Amethod() { ... } // 반드시 구현해야 함
**}**
템플릿 메소드 패턴(Template Method Pattern)
- 디자인 패턴 중 하나로, 알고리즘의 구조를 메소드에 정의하고,
- 알고리즘의 일부 단계를 서브클래스에서 구현하도록 하여 알고리즘의 일부 변경을 허용하는 패턴이다.
- → 공통의 알고리즘 과정이 있지만, 그 과정 중 일부가 클래스마다 다를 때 유용하다.
- 추상 클래스를 사용하여 템플릿 메소드를 정의하고, 구체적인 작업은 서브클래스에서 오버라이드하여 구현
구조
- 추상 클래스(Abstract Class)
- 알고리즘의 단계를 정의하는 템플릿 메소드와 알고리즘의 일부를 구현하는 하나 이상의 추상 메소드로 구성
- 구체 클래스(Concrete Class)
- 추상 클래스를 상속받아 추상 메소드를 구현한다. (알고리즘의 일부 단계를 구체화)
abstract class BeverageRecipe {
public **final** void prepareRecipe() { // 템플릿 메소드
boilWater();
brew();
pourInCup();
addCondiments();
}
abstract void brew(); // 추상 메소드
abstract void addCondiments(); // 추상 메소드
public void boilWater() {
System.out.println("물을 끓입니다.");
}
public void pourInCup() {
System.out.println("컵에 따릅니다.");
}
}
class Coffee extends BeverageRecipe {
@Override
void brew() {
System.out.println("필터를 통해 커피를 우려냅니다.");
}
@Override
void addCondiments() {
System.out.println("설탕과 우유를 추가합니다.");
}
}
class Tea extends BeverageRecipe {
@Override
void brew() {
System.out.println("차를 우려냅니다.");
}
@Override
void addCondiments() {
System.out.println("레몬을 추가합니다.");
}
}
public class TemplateMethodPatternDemo {
public static void main(String[] args) {
BeverageRecipe tea = new Tea();
tea.prepareRecipe();
BeverageRecipe coffee = new Coffee();
coffee.prepareRecipe();
}
}
Java Interface
개념
- 서로 관계가 없는 물체들이 상호 작용을 하기 위해서 사용하는 장치나 시스템
- 클래스 구조상의 관계와 상관 없이 클래스들에 의해 구현되어질 수 있는 규약
목적
- 클래스들 사이의 유사한 특성을 부자연스러운 상속 관계를 설정하지 않고 얻어냄
활용
- 하나 또는 그 이상의 클래스들에서 똑같이 구현되어질 법한 메소드를 선언하는 경우
- 클래스 자체를 드러내지 않고 객체의 프로그래밍 인터페이스를 제공하는 경우
클래스 vs 인터페이스
- 완결한 메소드(Concrete method)
- 메소드의 구현을 포함한 일반적인 메소드를 concrete method라 함
- 추상 메소드(Abstract Method)의 반대 개념
✔ 인터페이스의 상속
- 인터페이스는 다중 상속을 지원하지 않는 자바에서 다중 상속의 장점을 활용하기 위해 도입
- 한 클래스는 하나의 부모 클래스를 가지며 하나 이상의 인터페이스를 구현할 수 있다.
- 인터페이스 사이에서는 다중 상속이 가능하다.
- interface 키워드로 선언하고 implements 키워드로 사용
- 인터페이스를 구현한 클래스에서 추상 메소드를 반드시 정의해야 함
interface Ainter {
public void aMethod();
public void same();
}
interface Binter extends Ainter{
public void bMethod();
}
interface Cinter{
public void cMethod();
public void same();
}
interface Dinter extends Cinter, Binter{
// 인터페이스들 간에는 다중 상속이 가능하다.
public void dMethod();
}
class DImpl implements Dinter{
@Override
public void aMethod() {
System.out.println("aMethod 구현");
}
@Override
public void bMethod() {
}
@Override
public void same() {
}
@Override
public void cMethod() {
System.out.println("aMethod 구현");
}
@Override
public void dMethod() {
System.out.println("aMethod 구현");
}
}
public class InterfaceDemo{
public static void main(String[] args) {
// 인터페이스도 타입이다.
Ainter ainter = new DImpl();
Cinter cInter = new DImpl();
// 자기가 정의한 것만 사용 가능
ainter.aMethod();
cInter.cMethod();
Binter binter = new DImpl();
Dinter dinter = new DImpl();
binter.aMethod();
binter.bMethod();
binter.same();
/* 타입이 아는 것 까지만 쓸 수 있고,
* 외의 것을 쓰고 싶다면 형변환이 필요 */
((DImpl)ainter).say();
}
}
default 메소드
- 인터페이스가 default 키워드로 선언되면 메소드가 구현될 수 있다.
- 또한 이를 구현하는 클래스는 default 메소드를 오버라이딩 할 수 있다.
- 인터페이스가 변경이 되면, 인터페이스를 구현하는 모든 클래스들이 해당 메소드를 구현해야 하는 문제가 있다.
- → 이런 문제를 해결하기 위하여 인터페이스에 메소드를 구현해 놓을 수 있도록 함
interface Calculator {
public int plus(int i, int j);
public int multiple(int i, int j);
default int exec(int i, int j) { // default로 선언함으로 메소드를 구현할 수 있다.
return i + j;
}
}
class MyCalculator implements Calculator {
@Override
public int plus(int i, int j) {
return i + j;
}
@Override
public int multiple(int i, int j) {
return i * j;
}
}
public class CalculatorDemo {
public static void main(String[] args) {
Calculator cal = new MyCalculator();
System.out.println(cal.plus(5, 10));
System.out.println(cal.multiple(5, 10));
int value = cal.exec(5, 10);
System.out.println(value);
}
}
인터페이스의 static
변수
- 인터페이스에서 int a = 10; 과 같이 멤버 변수를 선언하게 되면 static final 로서 선언된다. (생략 가능, 생략 하더라도 static final 로서 선언됨)
- 즉, 인터페이스에서 변수를 선언하게 되면, 그 변수는 상수가 된다.
- → 상수로서 변수와 구분을 위해 대문자로 선언하는 것이 관례이다.
static 메소드
- 인터페이스에 static 메소드를 정의하는 것은, 클래스에 static 을 정의하는 것과 동일하다.
- 인터페이스에서 메소드 구현이 가능하다.
- 반드시 클래스 명으로 메소드를 호출해야 한다.
728x90
'Spring > Spring Boot' 카테고리의 다른 글
Spring 이메일 인증 기능 구현하기 2 : 비밀번호 찾기 (0) | 2024.08.20 |
---|---|
Spring 이메일 인증 기능 구현하기 1편 : 회원가입시 이메일 인증 (0) | 2024.08.20 |
SpringJPA : 영속성 컨텍스트, 엔티티 매핑, @OneToMany, @ManyToOne (1) | 2024.06.21 |
DB - JOIN, SUBQUERY (0) | 2024.05.03 |
객체 지향 프로그래밍이란? (0) | 2024.03.28 |