[JAVA-6] 클래스 고급2

ParkJunHa·2023년 10월 18일

추상 클래스

동적 로딩(Dynamic loading)

특정 객체가 컴파일을 할 때 실행 파일에 포함되지 않고, 프로그램 실행 중에 CPU에 의해 호출되어 동적으로 메모리에 적재되는 방법으로서, 작은메모리로 큰 프로그램을 실행 할 수 있음

아래 예시를 먼저 보자

// Main.java
import com.chapter7.Message;  
public class Main {  
    public static void main(String[] args) {  
        Message msg = new Message();  
        msg.getMessage();  
    }  
}
// Message.java
package com.chapter7;  
  
public class Message {  
    public void getMessage(){  
        System.out.println("HelloWorld!");  
    }  
}

여기서 Main 메서드를 실행하면, 인스턴스를 생성할 때 바로 메모리에 인스턴스가 만들어져서 실행하는 것이 아니라, new 키워드에 와서 Message 클래스를 읽어와서 메모리를 생성한다.

즉, 동적로딩 또는 동적링킹은 프로그램 실행시에 실행 파일에 포함되지 않고, 실행 후 필요할 대마다 메모리에 동적으로 생성하여 기능을 사용한다는 개념이다.

[!done] #java/question [[99. Q&A#Chapter 6]]

  • 위에 import 구문을 써도 그거랑 상관없이 동적로딩되는가?

^92d046

동적로딩의 반대개념으로는 정적로딩이 있는데, 대표적으로 C언어가 있다. 이는 프로그램을 실행할 때 모든 기능이 메모리에 존재하므로, CPU는 자신이 필요로 하는 기능을 빠르게 메모리에서 바로 가지고 와서 사용할 수 있다. 따라서 속도가 빠르다. 프로그램의 속도에 가장 많은 영향을 주는 것은 다른 저장장치에서 데이터를 불러올때 발생하는데, 동적로딩은 이런 면에서 메모리에 해당 기능이 없다면 불러와야 하므로 시간적으로 오래 걸린다.

static

객체 생성과 상관 없이 프로그램 실행 시 메모리에 생성하여 속성이나 기능을 사용하는 방법

  • 프로그램 실행 시 static 지정자가 붙어있는 클래스 멤버들은 자바 프로그램이 시작되면 바로 메모리에 생성된다.
  • 프로그램 종료시 메모리에서 소멸된다.
  • 인스턴스 생성과 무관하다.
  • 특정 메서드의 기능이 프로그램에서 자주 사용될 때 만들어 사용하면 실행속도를 높일 수 있다.

static 지정 대상

  • 클래스 : 내부 클래스에 사용된다.
  • 인스턴스 변수 : 인스턴스간 데이터 공유시에 사용된다.
  • 메서드 : 객체 생성 없이 메서드를 사용할 때 사용된다.

[!info] 기본적으로 static 멤버에는 static 멤버가 선언된 클래스의 이름으로 접근하는것이 바람직함.

public class Number{
	private int num;
	static int numCounter=10;
	public static int getNumCounter(){
		return numCounter;
	}
	public Number(){
		num = numCounter;
	}
	public void increaseNum(){
		numCounter++;
	}
}
import com.chapter7.Number;  
public class Main {  
    public static void main(String[] args) {  
        System.out.println("numCount :" +Number.numCounter);  
        Number number1 = new Number();  
        number1.increaseNum();  
        System.out.println("numCount : "+Number.numCounter);  
  
        Number number2 = new Number();  
        number2.increaseNum();  
        number2.increaseNum();  
        System.out.println("numCount : "+Number.numCounter);  
    }  
      
}
numCount :10
numCount : 11
numCount : 13

서로다른 인스턴스간 데이터를 공유할 때 사용한다.

![[static_example.excalidraw|1000]]

[!caution]
1. static 메서드 내에서는 인스턴스 변수를 사용할 수 없다
2. static 메서드 내에서 사용 가능한 변수의 종류 static변수, 지역변수

final

클래스 앞에 final이 쓰이면 상속을 금지한다는 의미이다.

  • 클래스 : 상속을 금지한다
  • 멤버 메소드 : 오버라이딩을 금지한다.
  • 멤버 변수 : 값 변경을 금지한다.

상수

프로그램을 실행한 후 종료할때까지 일정한 값을 유지한다.

  • 모든 인스턴스에서 동일한 값을 공유하게 한다.
  • 상수명을 대문자로 정한다.

형식

public static final String SERVER_IP = "127.0.0.1";
public static final int TOTAL = 40;

abstract

'실체가 없는, 구현되지 않은'
기능이 없고 선언만 되어있다라는 뜻.

  • 클래스 : 추상 클래스로 사용된다
  • 멤버 메서드 : 추상 메서드로 사용된다.

형식

run(); // abstract method
run(){...} // concrete method

추상클래스 특징

  • 인스턴스 생성이 불가능
  • 추상 메서드 없이 추상 클래스 선언 가능
  • 클래스의 멤버에 추상 메서드가 있으면 그 클래스는 반드시 추상 클래스로 선언
  • [[5.클래스 고급 - 1#업캐스팅(upcasting)|업캐스팅]] 타입으로 사용

추상 클래스 용도

상위 추상클래스에서는 추상 메서드를 선언하고, 상속받는 하위 클래스에서는 상위 추상 클래스에 있는 추상 메서드를 반드시 구현하게 해서 전체 기능에 강제서오가 통일성을 부여함

  • 하위 클래스에서 구현해야 하는 기능을 상위 클래스의 추상 메서드 형식을 빌려와 하위 클래스에서 구현하는 방법
  • 따라서 각 하위 클래스의 추상 메서드에 구현한 기능들은 통일성과 강제성을 띔
  • 소스의 구조가 일정하게 유지 할 수 있으므로 표준화 가능
public abstract class ExStudent extends ParentPerson{
// 메소드 생략
public abstract String getTeacher();
}

위처럼 부모 클래스를 추상 클래스로 만들고, 추상 메서드를 집어넣으면 자식메소드들은 위 추상메서드 오버라이딩을 강제하게 된다.

public class InheritStudentElement extends ExStudent{
	// 메소드 생략
	public String getTeacher(){  
	    return "김길순";  
	}
}

또한 추상클래스는 인스턴스 생성이 불가능하다는 특징이 있다.

![[abstract_class.excalidraw|1000]]

인터페이스 (Interface)

interface 키워드로 선언된 추상 클래스
기능만을 하위클레스에 강제하기 위해 사용하는것. 소스의 구조가 통일성을 갖는다.
현실세계에서 법과 같은 역할

  • 인스턴스 생성이 불가능하다
  • [[5.클래스 고급 - 1#업캐스팅(upcasting)|업캐스팅]] 타입으로 사용 가능하다.
  • 추상 클래스가 발전한 개념이다.
  • 맴버로는 상수, 추상메서드만 허용한다.
  • 하위클래스와의 관계는 implements이다.
  • 하위클래스에서 여러 인터페이스르 동시에 implements 할 수 있다.
  • 자바의 단일 상속 기능을 보완할 수 있다.

![[interface_example.excalidraw | center]]

다중 인터페이스

하위 클래스가 여러 인터페이스를 동시에 ==[[5.클래스 고급 - 1#🔏상속|implements]]== 하는 경우
자바에서 제공하는 API는 여러 단계의 상속구조나 다중인터페이스 구조로 대부분 제공하므로 익숙해지는것이 중요함

![[multiple_interface.excalidraw|center]]

interface ITest1{
	public abstract void func1();
}
interface ITest2{
	public abstract void func2();
}
class Child implements ITest1, ITest2{
	public void func1(){
		System.out.println("func1 메서드 호출");
	}
	public void func2(){
		System.out.println("func2 메서드 호출");
	}
}
public class ChildTest{
	public static void main (String[] args){
		Child c = new Child();
		Itest1 i1 = new Child();
		i1.func1();
	}
}

인터페이스 실습

인터페이스를 이용한 회원 관리 기능

![[memberimp.excalidraw|center|300]]

// Member.java
public interface Member{
	public void searchMember();
	public void joinMember();
	public void modMember();
	public void delMember();
}
public class MemberImpl implements Member{
	public void searchMember(){
		// 회원 조회 기능
	}
	public void joinMember(){
		// 회원 등록 기능
	}
	public void modMember(){
		//회원 정보 수정 기능
	}
	public void delMember(){
		//회원 삭제 기능
	}
	// other Methods
}

내부 클래스 (Inner Class)

다른 클래스 내부에 존재하는 클래스를 의미

  • 내부 클래스는 외부 클래스의 멤버에 자유롭게 접근할 수 있다, (private 포함)
  • 클래스 자체를 멤버로 사용할 수 있다.
  • 일반적으로 화면의 이벤트를 처리하는 이벤트 핸들러로 사용한다.
종류특징
member외부 클래스의 멤버로 내부 클래스가 정의된다
local외부 클래스의 메서드 내에서 정의되는 클래스이다.
static내부 클래스가 static으로 지정된 클래스이다.
anonymous내부 클래스가 이름 없이 정의된 경우

![[inner_class.excalidraw|center|1000]]

멤버 내부 클래스 (Member Inner Class)

외부 클래스의 멤버처럼 정의된 클래스
내부 클래스를 사용하려면 먼저 외부 클래스의 인스턴스를 생성한 뒤 접근해야 함

package com.chapter7;  
public class MyOuter1 {  
    private String name;  
    private int age;  
    public MyOuter1(String name, int age){  
        this.name = name;  
        this.age = age;  
    }  
    public String getName(){  
        return name;  
    }  
    public int getAge(){  
        return age;  
    }  
    public class Inner{  
        private String address;  
        public Inner(String address){  
            this.address = address;  
        }  
        public String getUserInfo(){  
            return "name :" + name + "age : " + age + "address : " + address;  
        }  
    }  
}
import com.chapter7.MyOuter1;  
public class Main{  
    public static void main(String [] args){  
        MyOuter1 myOuter = new MyOuter1("홍길동", 20);  
        MyOuter1.Inner inner = myOuter.new Inner("세종시 세종구");  
        System.out.println("PersonalInfo\n"+inner.getUserInfo());  
    }  
}

지역 내부 클래스 (Local Inner Class)

외부 클래스의 메서드 내에서 정의된 클래스
메서드 호출시 생성, 복귀시 소멸

package com.chapter7;  
public class MyOuter2 {  
    private String name;  
    private int age;  
    public MyOuter2(String name, int age){  
        this.name = name;  
        this.age = age;  
    }  
    public String getName(){  
        return name;  
    }  
    public int getAge(){  
        return age;  
    }  
    public void test(){  
        int num = 23;  
        class Inner{  
            private String address;  
            public Inner(String address){  
                this.address = address;  
            }  
  
            public String getUserInfo() {  
                return name + "\n" + age + "\n" + address;  
            }  
        }  
        Inner inner = new Inner("강동구");  
        System.out.println(inner.getUserInfo());  
    }  
}
import com.chapter7.MyOuter2;  
public class Main{  
    public static void main(String [] args){  
        MyOuter2 outer = new MyOuter2("홍길동", 20);  
        outer.test();  
    }  
}

정적 내부 클래스 (Static Inner Class)

내부 클래스가 static으로 지정된 클래스
내부 클래스 멤버가 static으로 지정되었으면 내부 클래스도 반드시 static으로 지정해야한다.

package com.chapter7;  
public class MyOuter3 {  
    private String name;  
    private int age;  
    public MyOuter3(String name, int age){  
        this.name = name;  
        this.age = age;  
    }  
    public String getName(){  
        return name;  
    }  
    public static class Inner{  
        private String address;  
        static String pnumber = "010-1111-2222";  
  
        public Inner(String address){  
            this.address = address;  
        }  
        public String getUserInfo(){  
            return "address : " + address + "\nTEL : " + pnumber;  
        }  
    }  
}
import com.chapter7.MyOuter3;  
public class Main{  
    public static void main(String [] args){  
        MyOuter3.Inner inner = new MyOuter3.Inner("세종시 세종구");  
        System.out.println(inner.getUserInfo());  
    }  
}

익명 내부 클래스 (Anonymous Inner Class)

필요할 때마다 인터페이스를 내부 클래스의 인스턴스로 만들어 동적으로 추상 메서드를 구현한 뒤 사용한다.
자바나 안드로이드에서 이 방법을 이용해 화면에서 이벤트 처리를 한다.

package com.chapter7;  
  
public interface Anony{  
    public void print();  
}
package com.chapter7;  
  
public class AnonyTest {  
    public void printB(Anony a){  
        a.print();  
    }  
  
    public static void main(String [] args){  
        AnonyTest t = new AnonyTest();  
        t.printB(new Anony() {  
            @Override  
            public void print() {  
                System.out.println("익명 클래스 사용중입니다.");  
            }  
        });  
    }  
}

printB메서드를 호출하면서 Anony 인스턴스를 일시적으로 생성한 뒤, print()메서드를 바로 구현하여 처리한다.

profile
PS린이

0개의 댓글