
특정 객체가 컴파일을 할 때 실행 파일에 포함되지 않고, 프로그램 실행 중에 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는 자신이 필요로 하는 기능을 빠르게 메모리에서 바로 가지고 와서 사용할 수 있다. 따라서 속도가 빠르다. 프로그램의 속도에 가장 많은 영향을 주는 것은 다른 저장장치에서 데이터를 불러올때 발생하는데, 동적로딩은 이런 면에서 메모리에 해당 기능이 없다면 불러와야 하므로 시간적으로 오래 걸린다.
객체 생성과 상관 없이 프로그램 실행 시 메모리에 생성하여 속성이나 기능을 사용하는 방법
[!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이 쓰이면 상속을 금지한다는 의미이다.
프로그램을 실행한 후 종료할때까지 일정한 값을 유지한다.
public static final String SERVER_IP = "127.0.0.1";
public static final int TOTAL = 40;
'실체가 없는, 구현되지 않은'
기능이 없고 선언만 되어있다라는 뜻.
run(); // abstract method
run(){...} // concrete method
상위 추상클래스에서는 추상 메서드를 선언하고, 상속받는 하위 클래스에서는 상위 추상 클래스에 있는 추상 메서드를 반드시 구현하게 해서 전체 기능에 강제서오가 통일성을 부여함
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_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
}
다른 클래스 내부에 존재하는 클래스를 의미
| 종류 | 특징 |
|---|---|
| member | 외부 클래스의 멤버로 내부 클래스가 정의된다 |
| local | 외부 클래스의 메서드 내에서 정의되는 클래스이다. |
| static | 내부 클래스가 static으로 지정된 클래스이다. |
| anonymous | 내부 클래스가 이름 없이 정의된 경우 |
![[inner_class.excalidraw|center|1000]]
외부 클래스의 멤버처럼 정의된 클래스
내부 클래스를 사용하려면 먼저 외부 클래스의 인스턴스를 생성한 뒤 접근해야 함
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());
}
}
외부 클래스의 메서드 내에서 정의된 클래스
메서드 호출시 생성, 복귀시 소멸
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으로 지정된 클래스
내부 클래스 멤버가 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());
}
}
필요할 때마다 인터페이스를 내부 클래스의 인스턴스로 만들어 동적으로 추상 메서드를 구현한 뒤 사용한다.
자바나 안드로이드에서 이 방법을 이용해 화면에서 이벤트 처리를 한다.
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()메서드를 바로 구현하여 처리한다.