728x90

 

💡 어떤 클래스의 (객체) 모든 멤버가 static 멤버인 경우를 생각해보자

 

하나의 클래스 내부에 선언된 모든 메서드가 static으로 선언되었을 시 메인 메서드가 선언된 클래스에서 static 메서드로 접근할 시 클래스이름.메서드이름으로 접근이 쉽게 할 수 있습니다.

static 으로 선언한 메서드를 new연산자를 생성하여 객체 생성을 해서 사용할 수도 있기 때문에 코드를 작성할 때, 생성자 메서드(default method)를 private로 접근을 제한하여 선언해주면 객체생성을 못하도록 인위적으로 막을수가 있습니다.

https://velog.io/@steadygo247

자바 API에서는 private 생성자를 가지고 있는 클래스도 있다 ex) System , Math 등

//AllStatic 클래스

public class AllStatic {

    private AllStatic() {}
    public static int hap(int a, int b) {
        int v = a+b;
        return v;
    }
    
    public static int max(int a, int b) {
        return a>b ? a : b;
    }
    
    public static int min (int a, int b){
        return a<b ? a : b;
    }
}

//메인 메서드 클래스

public class AllStaticTest {

    public static void main(String[] args) {
    
        //AllStatic st = new AllStatic();
        //System.out.println(st.hap(3,5));
        //System.out.println(st.max(10,5));
        //System.out.println(st.min(10,5));
        
        System.out.println(AllStatic.hap(10,20));
        System.out.println(AllStatic.max(10,20));
        System.out.println(AllStatic.min(10,20));
    }
}

AllStatic 클래스내에서 Allstatic 생성자 메서드를 접근제어자 private를 사용해서
외부클래스 메인 메서드에서 객체 생성이 되지 않도록 막아두었음.

 

🎈 Class, Object, Instance 구분해보기

객체지향의 가장 기본이라고 볼 수 있는 용어들이며 , 객체를 나타내는 말들이지만 생성되는 시점에 따라서 조금씩 용어들이 달라질 뿐이다. 객체지향의 기본 개념은 인스턴스를 이용하여 생성된 객체에 접근하는 것이 가장 기본!

  • Class (클래스) : 객체를 모델링 하는 도구 (설계도) / 새로운 자료형을 만드는 도구! ex) public class Student { … }
  • Object(객체) : 클래스를 통해서 선언되는 변수 ex) Student st(객체변수 - 학생이라는 객체를 담을 변수(담을 예정)) → 앞으로 가리킴 변수가 구체적인 실체(대상)을 가리키지 않는 상태 / 객체가 서로 구분이 되지 않는 시점
  • Instance(인스턴스 , 실체) : 객체생성에 의해 메모리 (Heap Memory)에 만들어진 객체를 인스턴스(Instance)라고 한다. ex) st = new Student(); (인스턴스 - new 연산자와 생성자 메서드를 이용하여 객체가 생성되며 구체적인 실체로 할당을 받으면서 객체변수에서 인스턴스변수로 변하게 된다) 객체가 서로 구분이 되는 시점 (name , age, email, year …등)
728x90
반응형
728x90
📄 static 메서드란?
객체의 생성 없이 클래스 이름을 통해 직접 호출할 수 있는 메서드입니다.

static 메서드는 static이 붙어있는 메서드(static멤버는) 클래스를 사용하는 시점에서 자동으로 static-zone에 로딩됩니다. 정적 메서드 코드는 프로그램이 실행될 때 메모리의 static-zone에 로드되며, 메서드 호출 시 실행됩니다.

❓ main(시작) 클래스는 왜 객체생성없이 (new)로 객체 생성하지 않았는데 실행이 되었을까

         public class Static Test{
                 public static void main(String[] args) {
                         System.out.println(”Hello Java:);
                }
        }

main 클래스의 동작 방식
  1. run을 통해 실행하게 되면 내부의 JVM이 실행할 클래스를 찾습니다.
  2. 찾은 후에 설계된 클래스(파일)가 실행이 되려면 메모리 위에 올라와야 하는데, new를 하지 않은 상황에선 static 키워드가 붙어있는 멤버들( static 키워드가 붙은 메서드는 main) 정해진 메모리(static-zone) 위치에 한번 자동으로 로딩이 됩니다. → static 멤버들은 클래스를 사용하는 시점 즉, 클래스이름.메서드이름으로 호출될 때, 에서 딱 한번 Method Area 메모리에 로딩된다는 점이 중요합니다. 위의 코드에서는 main() 메서드가 static이기 때문에 메모리에 자동으로 로딩합다.
  3. JVM이 static-zone에서 main() 메서드를 호출합니다.
  4. 호출된 메서드를 Call Stack Frame Area(Stack Area)에 push(기계어 코드를 넣고)한 뒤 동작을 시작한다.

** Stack이 텅 비어있으면 현재 모든 프로그램이 종료된 상황 **

https://yang-droid.tistory.com/52

 

//Math 클래스 안에 static으로 작성된 클래스들

public class Math {
    public static int add(int a, int b) {
        return a + b;
    }


    public static int multiply(int a, int b) {
        return a * b;
    }
}


public class Main {
    public static void main(String[] args) {
    
        int sum = Math.add(5, 3);
        System.out.println("더하기: " + sum);


        int multiple = Math.multiply(4, 2);
        System.out.println("곱하기: " + multiple);
        
    }
}

//출력 -> 더하기 : 8 / 곱하기 : 8

위의 코드에서 Math 클래스에는 두 개의 정적 메서드인 addmultiply가 있습니다. 이 메서드들은 static 키워드로 선언되었기 때문에 클래스의 인스턴스를 생성하지 않고도 직접 접근하여 사용할 수 있습니다. 접근하는 방법은 dot( . ) 연산자를 이용하여 클래스이름.(static)메서드이름으로 매개변수를 전달하여 호출할 수 있습니다.

클래스이름.메서드이름

자주 사용하거나 빈번하게 사용하는 클래스 멤버들은 static으로 설정하여 멤버에 접근이 용이하도록 작성해주는 것이 좋습니다. ****static 메서드는 클래스의 인스턴스 없이도 호출되며, 간편하게 사용할 수 있습니다.

 

💡 none-static 메서드의 접근 방법 (인스턴스 메서드 / static이 붙지 않음)
- 객체를 생성해서 메모리에 로딩시켜야 합니다.

 

//Myutil1 클래스로 static이 작성되지 않음.

public class Myutil1 {
    public int hap(int a, int b ) {
        int v = a+b;
        return v;
    }
}


//main 메서드의 클래스
import model.Myutil1;

public class NoneStaticAccess {
    public static void main(String[] args) {
    
        int a = 10;
        int b = 16;
     //static이 아닌 클래스를 사용한다면 객체를 생성해주면 된다.
     
        Myutil1 ut = new Myutil1();
        int sum = ut.hap(a,b);
        System.out.println("sum = " + sum);
    }
}

 

💡 Method Area : 메서드의 기계어 코드가 할당되는 메모리 공간 / static 멤버들의 할당되는 메모리 공간
💡 Heap Area : 객체가 생성(new)되는 메모리공간

 

https://velog.io/@yonii/JAVA-Static이란

 

💡 JVM내에서의 메모리 모델

 

.크게 4가지로 구분지어서 확인할 수 있습니다.

  1. Method Area : static-zone과 none-static-zond으로 구성되어 있으며, 메서드의 바이트코드(기계어코드)가 할당되는 공간입니다. static 멤버들은 static-zone에 할당됩니다.
  2. Heap Area : 실제 객체가 생성되는 메모리 공간(new 연산자) / Java 프로그램의 메모리 구조 중 하나이며, 메모리 관리와 객체의 동적 생성 및 소멸에 중요한 역할을 합니다. GC(Garbage Collector)에 의해서 메모리가 수집됩니다. Heap Area는 우리가 객체를 생성되기 때문에 객체를 사용 후에는 소멸이 되어야 하는데, 메모리 계속 쌓이게 되면 용량을 차지하게 됩니다. 이 후, 객체를 생성할 때 메모리 용량이 부족하면 지연시간이 생기거나 에러가 날 수 있습니다. 이 때, GC라는 프로세스를 통해 Heap Area에 더이상 사용이 되지 않고 남아있는 Garbage 객체들은 주기적으로 clear 해주는 역할을 합니다. GC가 한번 Heap Area를 스캔하며 지나갈 때 각각의 객체가 사용중이라면 , 각각의 스캔 주기를 세대로 설정해줍니다. (맨 처음은 1세대) 이 후, 두번째 프로세스로 돌아왔을 때 기존에 사용중인 게 있다면 2,3,4..세대로 계속 업데이트를 해줍니다. 이 때 , 숫자가 높은 것들부터 GC를 진행하는 것을 Generation이라고 합니다.
  3. Thread : 스레드(Thread)는 프로그램 실행의 기본 단위로, 독립적으로 실행될 수 있는 작업 단위입니다. (JVM도 하나의 스레드라고 볼 수 있습니다) 스레드를 사용하면 여러 작업이 동시에 진행되는 것처럼 보이며, 다양한 작업들을 병렬적으로 처리할 수 있습니다. 스레드는 프로세스 내에서 독립적으로 실행되며, 각각의 스레드는 독립적인 작업 공간인 스택(Stack Area - Call Stack Frame Area)과 프로그램 카운터(Program Counter)를 가지고 있습니다. 메서드가 호출되면 메서드의 기계어코드를 할당 받고 메서드가 실행되는 공간(Call Stack Frame Area) - 지역변수, 매개변수들이 만들어지는 공간 PC에 의해서 현재 실행중인 프로그램 위치가 관리된다. LIFO(Last In First Out)구조로 운영되는 메모리공간
  4. Runtime Constant Pool (Literal Pool) : 상수 값 할당이 되는 메모리 공간 문자열 중 문자열 상수 (Literal : 리터럴)가 할당되는 메모리공간 (ex) 문자열 = “APPLE” → 리터럴)
728x90
반응형
728x90

 

배열 → 기억공간 여러개를 만들어서 사용
클래스 → 기억공간 여러개를 하나의 구조로 만들어서 사용 (바구니)
배열과 클래스는 모두 데이터를 담는 역할은 같지만 만들어지는 구조는 서로 다릅니다. Object(객체)로 여겨지기 때문에 기억공간 여러개가 붙어있는 상태라면 두가지를 구분하기 힘들지만, 큰 차이는 메모리 공간에 저장되는 데이터가 동일한 데이터타입이라면 배열, 이질적인 데이터타입들이 담아 구조를 직접 설계하여 내가 원하는 형태로 만들어야하는 경우 클래스로 만들게 됩니다.


💡 객체배열(Object Array)의 메모리 표현

객체 배열은 배열의 각 요소가 객체인 배열을 말합니다.
즉, 객체 배열은 동일한 클래스의 객체를 여러 개 저장하기 위해 사용됩니다.

Student[] = new Student[3];

// Student 클래스
public class Student {
    private String name;
    private int age;

// ↓ 위에서 만들어진 생성자 메서드 오버로딩
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getter와 Setter 메서드 생략

    // 기타 메서드 및 속성 정의
}

// main 메서드내부에서의 객체 배열 사용 예시
public class Main {
    public static void main(String[] args) {
        // Student 객체 배열 생성
        Student[] students = new Student[3];

        // Student 객체 생성하여 배열에 저장
        students[0] = new Student("피카츄", 20);
        students[1] = new Student("파이리", 22);
        students[2] = new Student("꼬부기", 21);

        // 객체 배열 순회하며 정보 출력
        for (int i = 0; i < students.length; i++) {
            System.out.println("Name: " + students[i].getName());
            System.out.println("Age: " + students[i].getAge());
            System.out.println();
        }
    }
}

//출력 -> 
Name: 피카츄
Age: 20

Name: 파이리
Age: 22

Name: 꼬부기
Age: 21

 

위의 예시에서는 "Student" 클래스의 객체 배열을 생성하고, 각 요소에 학생 객체를 생성하여 저장하였습니다.
그 후, 배열을 순회하며 각 학생의 정보를 출력하였습니다. 객체 배열은 여러 객체를 관리하고 접근하기 위한 유용한 자료구조입니다.

💡 system.arraycopy - 배열의 요소를 다른 배열로 복사하는 메서드

** System.arraycopy는 Java에서 배열의 요소를 다른 배열로 복사하는 메서드입니다. 이 메서드를 사용하여 배열 요소의 복사, 이동, 잘라내기 등 다양한 작업을 수행할 수 있습니다.

문법 : System.arraycopy(srcArray, srcPos, destArray, destPos, length);

  • srcArray: 복사할 원본 배열입니다.
  • srcPos: 원본 배열에서 복사를 시작할 인덱스(숫자를 입력)입니다.
  • destArray: 복사한 요소를 저장할 대상 배열입니다.
  • destPos: 대상 배열에서 복사한 요소를 저장할 시작 인덱스(숫자를 입력)입니다.
  • length: 복사할 요소의 개수(길이)입니다.

**srcArray의 srcPos 인덱스부터 시작하여 length 개수만큼의 요소를 **destArray**의 destPos 인덱스부터 시작하는 위치에 복사합니다.

예시 코드

int[] startArray = {1, 2, 3, 4, 5};
int[] copyArray = new int[3];

System.arraycopy(startArray, 1, copyArray, 0, 3);

// 복사된 요소 출력
for (int i = 0; i < copyArray.length; i++) {
    System.out.println(copyArray[i]);
}
// 출력 : 2,3,4

 

위의 예시에서는 startArray의 인덱스 1부터 시작하여 3개의 요소를 copyArray의 인덱스 0부터 시작하는 위치로 복사하였습니다. 결과적으로 copyArray에는 {2, 3, 4}가 저장되어 출력됩니다.

728x90
반응형
728x90

 

 

🔐 정보은닉(Informaiton hiding)


  • 정보은닉 : 다른 객체에게 자신의 정보를 숨기고 자신의 동작, 기능, 연산만을 통해 접근을 허용하는 것으로, 클래스 외부에서 특정 정보에 접근을 막는다는 의미이다. 캡슐화와 연관성이 밀접한 단어이다.

  • 캡슐화 : 정보 은닉은 객체의 속성과 메서드를 적절하게 그룹화하여 외부에 노출시키지 않습니다. 객체 내부의 구현 세부 사항은 외부로부터 숨겨지고, 오직 공개된 인터페이스만을 통해 상호작용할 수 있습니다. 이를 통해 객체는 자신의 상태와 동작을 캡슐화하고, 외부에서는 그 구체적인 내용을 알 필요 없이 사용할 수 있습니다.
💡 정보은닉이 되어있는 상태정보에 접근하는 방법 (private에 접근하는 방법) 2가지의 대표 방법이 있다.

데이터에 쉽게 접근하지 못하게 상태정보를 private로 설정해두었다면, 해당 데이터를 메인 클래스에서
객체를 생성하여 사용하지 못하게 됩니다. ( private는 자기자신을 제외 모든 패키지에서 접근이 불가하기 때문입니다.)


 

1. Getter와 Setter

객체 지향 프로그래밍에서 클래스의 속성(=상태정보) 에 접근하고 값을 가져오거나 설정하기 위한 메서드를 말합니다.
일반적으로 속성은 private으로 선언되어 외부에서 직접 접근할 수 없으므로, Getter와 Setter를 사용하여 간접적으로 필드에 접근하고 값을 가져오거나 설정합니다.

 

< Getter와 Setter의 예시 >

< Getter와 Setter의 예시 >

public class Person {
    private String name; // private 필드

    public String getName() { // Getter 메서드
        return name;
    }

    public void setName(String newName) { // Setter 메서드
        name = newName;
    }
}

public class Main {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("John"); // Setter를 통해 필드 값 설정

        String name = person.getName(); // Getter를 통해 필드 값 읽기
        System.out.println(name); // 출력: John
    }
}

 

🎈  Getter는 속성의 값을 반환하는 메서드로, 외부에서 속성 값을 읽을 수 있도록 합니다.
      Getter는 일반적으로 속성 이름 앞에 "get" 접두사를 붙이고, 속성의 데이터 타입과 일치하는 값을 반환합니다.
      밖으로 데이터를 보내주는 용도 get멤버변수(이 때, 멤버변수의 시작은 대문자로 시작한다)

🎈 Setter는 속성에 값을 설정하는 메서드로, 외부에서 속성 값을 변경할 수 있도록 합니다.
     Setter는 일반적으로 속성 이름 앞에 "set" 접두사를 붙이고, 속성의 데이터 타입과 일치하는 매개변수를 받아 필드 값을 변경합니다.
     저장하는 용도 set멤버변수(이 때, 멤버변수의 시작은 대문자로 시작한다) → 메서드로서 매개변수로 name이라는 변수를 받아,
     this로 접근하여 받아온 name을 값을 this.name(클래스가 가지고 있는 멤버변수)에다가 할당해준다.

💡 Getter와 Setter의 주요 목적은 정보 은닉(Encapsulation)을 유지하면서 속성에 접근하는 기능을 제공하는 것
입니다. 속성을 private으로 선언하여 직접 접근을 제한하고, Getter와 Setter를 통해 필드에 접근하면서 캡슐화를 유지할 수 있습니다.

private로 접근이 제한된 변수들을 get,set을 사용하여 public으로 외부 클래스에서도 접근이 가능할 수 있게 설정해주었습니다.
set속성으로 해당 메모리공간을 불러온 후 ( )안에 출력되기를 원하는 데이터를 입력한 후, get속성으로 출력할 수 있습니다.

 

2. 생성자 메서드를 통해서 접근 가능(객체 초기화)

 

  • 생성자 메서드를 아무것도 만들지 않으면 컴파일러가 자동으로 default 생성자가 생성되어 있는데 그 default 생성자 안에 this.속성(상태정보) = “데이터”; 와 같은 문법으로 객체를 생성한 후 초기화를 하여 정보은닉화 된 메모리 공간에 값을 저장해 줄 수 있습니다.
  • 생성자 메서드의 역할은 객체를 생성한 후, 객체가 가지고 있는 상태정보에 데이터를 바로 저장할 때 생성자 메서드를 사용하게됩니다.
  • private 접근 제한자는 같은 클래스 내에서는 자기자신의 데이터로 접근이 허용되고 생성자 메서드 내부에서 this를 이용해메모리공간에 값을 입력하는 것이 가능합니다.

setter 대신 생성자를 초기화하여 속성 값에 데이터를 입력해주면 setter는 작성할 필요없이 getter로 main메서드에서 호출하여 사용하면 된다.

 

public class Person {
    private String name;
    private int age;

    // 생성자 초기화
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getter 메서드
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

public class Main {
    public static void main(String[] args) {
        // 생성자를 통해 객체 생성 및 초기화
        Person person = new Person("John", 25);

        System.out.println(person.getName()); // 출력: John
        System.out.println(person.getAge(); // 출력: 25
    }
}

 

 

 

 

3. 생성자 메서드를 오버로딩(Overloading)해서 초기화 가능

 

PersonVO p = new PersonVO(”홍길동”, 50, “010-1234-4567”); 위와 같이 작성하여 객체를 생성함과 동시에 p에 값들을 입력해주고, 해당 값들을 class PersonVO에 생성자 메서드를 오버로딩하여 초기화가 가능하다.
public PersonVO(String name, int age, String phone) {
               this.name = name;
               this.age = age;
               this.phone = phone;
}

 

PersonVo class 

//생략된 생성자 메서드가 있다. -> 기본생성자 (default Constructor)
    public PersonVo() {
        this.name = "홍길동";
        this.age = 30;
        this.phone = "111-1111-1111";
    }

    public PersonVo(String name, int age, String phone) {
        //객체를 생성하는 코드는 내부에서 만들어진다.
        //객체를 초기화 한다.
        this.name = name;
        this.age = age;
        this.phone = phone;
    }


import model.PersonVo;

public class Capsul_personvo {
    public static void main(String[] args) {

        //Q. 한사람의 [회원] 정보를 저장할 [객체를 생성]하세요.
        PersonVo vo = new PersonVo();
        PersonVo vo1 = new PersonVo("나길동" , 50, "222-2222-2222");
        PersonVo vo2 = new PersonVo("나길동" , 50, "222-2222-2222");

        System.out.println(vo.getName() + "\t" + vo.getPhone() + "\t" + vo.getAge());
        System.out.println(vo1.getName() + "\t" + vo1.getPhone() + "\t" + vo1.getAge());
        System.out.println(vo2.getName() + "\t" + vo2.getPhone() + "\t" + vo2.getAge());
    }
}

 

🎈  toString() 메서드를 활용하여 객체가 가지고 있는 모든 값을 리턴하기

생성자 메서드를 활용하여 개발자가 입력한 데이터를 입력하여 객체를 출력할 수 있게는 하였지만, getter를 각각의 속성들 마다 입력하여 불러오는 번거로움이 발생합니다.

이 때, toString() 메서드를 활용하면 객체 내부에 저장된 모든 값들을 한번에 문자열로 출력할 수 있게됩니다. 그럼 getter를 하나하나 입력하는 것이 아닌, toString 메서드에 만들어진 retrun 값대로 출력할 수 있게됩니다.

public String toString() {
        return name + "\t"+age+"\t"+phone;
    }

import model.PersonVo;

public class ToStringPrint {
    public static void main(String[] args) {
        //Q.생성자 메서드를 통해서 PersonVo객체에 원하는 이름, 나이, 전화번호를 저장하고 toString() 메서드로 출력하세요.
        PersonVo vo = new PersonVo("홍길동" , 34, "111-1111-1111");
        System.out.println(vo.getName() + "\t" + vo.getAge()+"\t"+vo.getPhone());
        System.out.println(vo.toString());
        //getter를 세번이나 입력해서 출력을 반복하는 것보다 toString
				System.out.println(vo); -> vo.toString() 과 동일한 출    
		}
}

여기서 toString의 생략도 가능해진다. 생성자 메서드로 저장된 vo객체만 입력하여 출력했다고 하더라도, 컴파일러가 객체가 가지고 있는
모든 데이터를 출력해야한다고 판단하여, vo.toString이라는 메서드를 찾아서 toString 메서드에 의해서 출력될 수 있도록 진행해준다.

 

💡 잘 설계된 VO 클래스란 ?

1. 모든 상태정보 ( = 속성)을 정보 은닉하기 (private)
2. default 생성자를 반드시 만들기
3. 생성자 메서드를 오버로딩하여 객체 초기화 하기
4. setter 메서드를 만들기( 값을 저장하기 위한 용도)
5. getter 메서드를 만들기( 값을 가져오기위한 용도)
6. toString() 메서드를 만들기( 객체가 가지고 있는 전체 값 출력 용도)

 

💡 intelliJ에서 제공하는 Generate 이용하기

 

먼저 VO파일을 생성한 후 우클릭을 누르면 Generate라는 메뉴가 보이는데 해당 메뉴를 이용하여 default 생성자 및 getter setter를 손쉽게 생성할 수 있다.

 

 

Constructor를 클릭하여 default생성자 및 만들어진 기본 생성자를 오버로딩하는 메서드도 만들 수 있고, Getter and Setter를 클릭하면 선언된 속성에 따르는 getter setter를 바로 만들 수 있다.

728x90
반응형
728x90
  • 객체 지향 프로그래밍에서는 객체들 간의 접근을 제어할 수 있어야 합니다. 상태와 동작을 상호간에 접근을 허용할 수도 있어야하고, 접근을 막아야 하는 경우도 있습니다. 접근 제어자를 사용하는 이유는 클래스의 내부에 선언된 데이터를 보호하기 위해서인데, 데이터가 유효한 값을 유지하도록 또는 비밀번호와 같은 데이터를 외부에서 함부로 변경하지 못하도록 하기 위해서 외부로부터 접근을 제한하는 것이 필요합니다.
  • 이를 데이터 감추기(data hiding)이라고 하며, 객체지향개념에서는 캡슐화에 해당하는 내용입니다. 또 다른 이유로는, 클래스 내에서만 사용되는, 내부 작업을 위해 임시로 사용되는 멤버 변수나 부분 작업을 처리하기 위한 메서드 등의 멤버들을 클래스 내부에 감추기 위해서입니다. 외부에서 접근할 필요가 없는 멤버들을 private로 접근을 제한하면 코드의 복잡성도 줄일 수 있습니다.

 

접근제어(Access Modifier) 란?

객체의 상태정보(=멤버 변수) 는 중요하기 때문에 다른 클래스에서의 접근을 허용하지 않습니다. (정보은닉)
상태정보에 다른 객체가 접근하여 값을 수정하게 된다면, 객체가 불필요한 정보들을 갖게될 수 있고, 잘못된 데이터를 가지게 될 수도 있습니다.

  • 객체의 행위정보(=멤버 메서드) 는 상호작용이 필요하기 때문에 클래스끼리의 접근을 허용합니다.
  • 클래스나 멤버변수, 메서드, 생성자에 접근 제어자가 지정되어 있지 않다면, 접근 제어자가 default임을 뜻합니다.

 

https://cloudstudying.kr/lectures/201

 

       public > proteced > (default) > private

  1. public : 모든패키지에서 접근 가능 (모든 클래스 , 멤버 메서드는 public)
  2. private : 모든 패키지에서 접근 불가 (자기 자신만 접근 가능 / 모든 멤버변수는 private) 일반적으로 상태변수는 private으로 접근을 제한해주는 것이 일반적
  3. protected : 상속 관계에서 하위 클래스에서 상위 클래스 접근가능 자식이 부모에 있는 기능들을 사용하고 싶다면 protected로 제한한다.
  4. default : 동일한 패키지에서만 접근 가능 (코드에 작성되어 있지 않고 생략되어 있음)
    → 접근 제한자를 작성하지 않는다면 기본적으로 default이며, 클래스끼리는 동일한 패키지 내에서의 클래스끼리는 다 접근이 가능하다는 의미
    public이라고 작성하는 이유는 외부 패키지에서도 해당 클래스에 접근할 수 있도록 하기위해서 일반적으로 class를 작성할 때는 public을 작성해준다.

    📋 접근 제어자는 클래스와 클래스 내부에서 만들어지는 멤버변수, 멤버 메서드에 접근 제한자를 사용할 수 있다.

 

💡 Package란?

서로 기능이 비슷한 클래스들끼리 모아서 관리를 쉽게 하기 위해서 사용 (폴더 개념)
java는 대부분 2단계의 폴더구조를 가지고 있다 (API) / 기능이 비슷한 API들끼리 묶어서 패키지로 보관하여 사용하고 있다.

https://jeniffer0812techstory.tistory.com/24

 

  • 클래스를 접근하는 이름 이해하기

패키지를 포함하지 않는 클래스 이름은 (class name) 패키지를 포함한 클래스 이름 (class full name) → 패키지.패키지.클래스 이름
ex) 문자열을 처리하는 클래스 → java.lang.String 키보드로부터 데이터를 읽어드리는 클래스 → java.util.Scanner

해당 API 또는 클래스가 어디에 있는지 구조를 알고 있어야 class full name을 통해 해당 클래스로 접근이 가능해진다.

728x90
반응형
728x90
모델 

 ✔  클래스를 역할에 따라 부르는 이름

현실 세계에서는 다양한 객체들이 존재하고, 그 객체들은 자신의 역할이 있는데, 역할이 정해져있다는 의미로
객체를 설계할 때는 모델을 만든다라고 합니다. 모델이라 함은 역할에 따라 전부 구분되어져 부르는 이름이라고 생각하면 됩니다.

💡  클래스 = 모델을 설계하는 도구

시작 클래스 (main)

DTO(Data Transfe Object), VO(Value Object) Model : 데이터를 담는 (이동) 모델 / 데이터를 하나로 수집하는 역할 !

  • DTO : 주로 데이터베이스로부터 데이터를 검색하거나 데이터를 저장하기 위해 사용됩니다.
  • DTO는 데이터를 저장하는 속성(멤버 변수)과 해당 데이터에 접근하기 위한 getter 및 setter 메서드를 가지고 있습니다.
  • DTO는 일반적으로 데이터베이스로부터 데이터를 검색하여 그 결과를 전달하거나, 클라이언트와 서버 간의 데이터 교환에 사용됩니다.
    주로 데이터베이스의 레코드나 특정 도메인 객체의 필드를 담고 있는 단순한 데이터 구조로 구성됩니다. DTO는 주로 읽기 전용이며, 데이터를 보관하고 전달하기 위한 목적으로 사용됩니다.

💡 DTO는 일반적으로 다음과 같은 특징을 가지고 있습니다

  1. 데이터 전달: DTO는 데이터를 전송하거나 전달하기 위한 목적으로 사용됩니다.
    예를 들어, 데이터베이스의 결과를 클라이언트에 전달하거나, 클라이언트에서 서버로 데이터를 전송할 때 DTO를 사용할 수 있습니다.
  2. 필드와 접근 메서드: DTO는 데이터 구조를 나타내기 위해 필드(field)를 가지고 있습니다. 일반적으로 필드는 데이터를 저장하거나 조회하는 용도로 사용됩니다.
    또한 필요에 따라 접근자(getter)와 설정자(setter) 메서드를 제공하여 필드에 접근할 수 있도록 합니다.
  3. 직렬화(Serialization): DTO는 데이터 전송을 위해 직렬화(serialization)될 수 있습니다.
    직렬화는 객체를 바이트 스트림 등의 형태로 변환하여 저장하거나 네트워크 상에서 전송할 수 있도록 하는 과정을 의미합니다. DTO는 주로 네트워크 통신이나 분산 시스템에서 사용되므로 직렬화가 필요할 수 있습니다.
  • DTO는 비즈니스 로직을 담지 않고, 순수한 데이터를 전달하는 목적으로 사용됩니다.
    따라서 DTO는 보통 속성(필드)과 그에 대한 접근자(getter)와 설정자(setter) 메서드를 가지는 간단한 데이터 구조로 구성됩니다. DTO는 데이터의 일관성과 효율성을 유지하며, 객체 간의 데이터 전달을 간편하게 만들어 줍니다.

 

 

 

 

DAO(Data Access Object) Model : 데이터를 처리(DB)를 하는 모델

- DAO : 데이터베이스에 데이터(VO, DTO)를 저장, 수정하거나 검색, 삭제를 하기 위해서 만들어지는 모델(클래스) 
   해당 역할을 하는것이 DAO 클래스 - CRUD 동작을 가지고 있는 클래스, 비즈니스 로직을 처리하는 클래스

   

     1) 수집된 데이터를 데이터 베이스에 저장 : insert 수정 : update
     2) 데이터베이스에 저장된 데이터를 검색 : select 삭제 : delete CRUD
         동작을 통해 DB와 서로 데이터를 주고받을 수 있다

 

💡 SQL은 Structured Query Language (구조적 질의 언어)로 관계형 데이터베이스 시스템에서 자료를 관리 및 처리하기 위해 설계된 언어이다.

DAO를 만들 때 저장 , 수정, 검색, 삭제 기능을 만들 때 SQL 명령문을 이용해서 만들 수 있다. 명령문을 이용해 DB를 제어할 수 있다.
DAO는 "Data Access Object"의 약어로, 데이터베이스와의 상호작용을 담당하는 객체를 말합니다. DAO는 데이터베이스에 접근하여 데이터를 조회, 삽입, 수정, 삭제 등의 데이터 조작 작업을 수행하는 역할을 담당합니다.
DAO는 일반적으로 데이터베이스에 대한 접근을 추상화하고, 비즈니스 로직과 데이터베이스 로직의 분리를 지원합니다.
이를 통해 애플리케이션의 유지 보수성과 확장성을 향상시킬 수 있습니다.
DAO는 데이터베이스에 직접적인 접근을 처리하므로, 데이터베이스 종류에 따라 다른 DAO 구현체를 작성해야 할 수도 있습니다.
일반적으로 DAO는 CRUD(Create, Read, Update, Delete) 작업을 수행하는 메서드를 포함합니다.
이를 통해 데이터베이스와 상호작용하면서 애플리케이션의 데이터 관리를 담당합니다.
DAO는 데이터베이스 연결, SQL 문 실행, 결과 처리 등을 담당하며, 비즈니스 로직에서는 DAO를 사용하여 데이터를 조작하고 처리합니다.

 


        import java.util.Scanner;

        public class CarInsertTest {
            public static void main(String[] args) {
                //자동차 정보를 키보드로부터 입력을 받아서 데이터 베이스에 저장을 해라.
                Scanner scan = new Scanner(System.in);
                System.out.print("자동차의 일련번호를 입력해주세요 = ");
                int carSN = scan.nextInt();
                scan.nextLine();

                System.out.print("자동차의 이름을 입력해주세요 = ");
                String carName = scan.nextLine();

                System.out.print("자동차의 가격을 입력해주세요 = ");
                int carPrice = scan.nextInt();
                scan.nextLine();

                System.out.print("자동차의 소유자의 이름을 입력해주세요 = ");
                String carOwner = scan.nextLine();

                System.out.print("자동차의 연식을 입력해주세요 = ");
                int carYear = scan.nextInt();

                scan.nextLine();

                System.out.print("자동차의 타입을 입력해주세요 = ");
                String carFlue = scan.nextLine();


                CarDTO car = new CarDTO();
                car.carSN = carSN;
                car.carName = carName;
                car.carPrice = carPrice;
                car.carOwner = carOwner;
                car.carYear = carYear;
                car.carFlue = carFlue;

                CarDAO carDAO = new CarDAO();
                carDAO.carInsert(car);
                carDAO.carSelect();

            }

 

carDAO.carInsert(car)에서 매개변수로 car를 입력하는 이유는 carInsert() 메서드의 시그니처에 맞게 데이터를 전달하기 위해서입니다.
carInsert() 메서드는 CarDTO 객체를 매개변수로 받아서 해당 객체에 저장된 자동차 정보를 데이터베이스에 저장하는 역할을 수행합니다.
따라서 carDAO.carInsert(car)는 입력받은 자동차 정보를 car 객체에 저장한 후, car 객체를 carInsert() 메서드에 전달하여 데이터베이스에 저장합니다.
반면에 carDAO.carSelect()는 매개변수를 입력하지 않는 이유는 해당 메서드에서는 데이터베이스로부터 자동차 정보를 조회하는 기능만을 수행하기 때문입니다.
자동차 정보를 조회하는 데에는 별다른 매개변수가 필요하지 않기 때문에 carDAO.carSelect()처럼 매개변수를 입력하지 않습니다.

Utility Model : 도움(Utility)을 주는 모델

  • Utility : 반복적으로 사용해야 될 동작(기능)을 별도의 클래스로 만들어놓고 필요할 때 사용하는 클래스 / 꼭 필요한 것은 아니고, 필요하면 만들어서 사용하면 됩니다.

    Utility 모델은 다음과 같은 특징을 가지고 있습니다:
    1. 정적 메서드: Utility 클래스의 메서드는 일반적으로 정적(static)으로 선언됩니다. 이는 객체의 인스턴스 생성 없이 직접 클래스 이름을 통해 메서드에 접근할 수 있다는 의미입니다.
    2. 인스턴스화 불가능: Utility 클래스는 주로 유틸리티 함수를 제공하기 위한 목적으로 사용되므로, 인스턴스화할 필요가 없습니다. 따라서 일반적으로 생성자는 private으로 선언하여 인스턴스화를 방지합니다.
    3. 공통 기능 제공: Utility 클래스는 일반적으로 다양한 클래스나 모듈에서 공통으로 사용되는 기능들을 제공합니다. 예를 들어, 문자열 처리, 날짜 및 시간 계산, 파일 조작 등과 같은 작업을 수행할 수 있는 메서드들이 Utility 클래스에 포함될 수 있습니다.

  • Utility 모델의 주요 목적은 코드의 재사용성과 유지보수성을 향상시키는 것입니다. 반복적이고 공통적인 작업들을 유틸리티 함수로 추상화하여 중복 코드를 피하고, 코드를 모듈화하여 관리하기 쉽게 만듭니다.
    또한 Utility 클래스는 객체 지향 프로그래밍에서 정적 메서드를 통해 유틸리티 함수를 호출하기 때문에, 호출하는 코드가 간결해지고 사용하기 쉬워집니다.

  • 주의할 점은 Utility 클래스가 지나치게 많은 역할과 책임을 가지지 않도록 하는 것입니다.
    즉, 단일 책임 원칙을 지키기 위해 너무 많은 기능을 Utility 클래스에 넣지 않는 것이 좋습니다.
    작은 범위의 관련된 유틸리티 함수들을 포함하는 작은 클래스들을 만들고,
    필요한 유틸리티 함수를 필요한 곳에서 적절히 활용하는 것이 바람직합니다.
    Utility 모델은 주로 간단한 독립적인 메서드들의 집합으로 구성되며, 특정한 작업을 수행하기 위한 유틸리티(도구) 함수를 제공하는 클래스입니다.
728x90
반응형

+ Recent posts