Programming/Java

[Java9 프로그래밍] 09. 자바 객체지향 - more

빠모스 2020. 3. 19. 00:37
반응형

Static

클래스에 선언된 메소드나 멤버변수는 반드시 객체화시켜야 사용 가능

 

메소드의 사용 조건

Calculator(클래스) calculator(객체) = new Calculator( 10, 50 ); (생성자)

int result = calculator.f (50);

=> calculator 객체를 사용해서 Calculator 클래스 내부의 f 메소드를 호출.

 

  • f(x) 메소드를 인스턴스화 시키지 않고 사용하고 싶다면, static을 사용 (객체 변수를 만들고싶지 않다면 = 인스턴스화 시키지 않고 싶다면)

static method

public class Calculator {

	public static int f (int x) {

	}
}

 

=> 이렇게 되면 객체 만들지 않고 바로 클래스에 접근할 수 있다.

 

int result = Calculator.f (50);

 

단순 반복 처리작업을 해야 할 경우 종종 사용. 이 메소드 자체로 유틸리티 형태로 사용할 때 이렇게 사용한다. 

 

ex)

Math.random : Math라는 클래스의 random이라는 메소드 바로 접근.

이렇게 수학적인 함수는 멤버변수를 사용하는것이 아니라 순수하게 파라미터를 통해서 데이터를 연산하고 결과값을 내주기 때문에 Math 내의 모든 메소드는 static 메소드로 정의해서 사용한다.

 

 

static 상수

 

static 변수는 주로 상수로 많이 사용됨.

 

public class Math {

	public static final double PI = 3.1.41592….

}

 

  • 프로그램에서 이 상수를 Math.PI로 바로 접근 가능하기 때문에 상수를 static 변수로 정의함. 
  • 어떤 변수가 static으로 선언됬다면 아, 상수구나 생각하면 됨.
  • 상수는 PI처럼 대부분 변수명을 대문자로 네이밍한다.

 

static 초기화 블록

 

  • 생성자는 객체를 생성할 때 수행
  • static 초기화 블록은 클래스가 최초로 메모리에 로딩될 때 수행
  • 정적 변수 초기화
  • 클래스 선언부에 나타난 순서대로 실행 

 

실습 코드

  • com.acompany라는 새로운 패키지에 Product 클래스를 생성한다.
  • 멤버변수, 세터, 게터, 생성자, toString을 만든다.
  • 멤버변수는 해당 클래스 내의 데이터, 세터와 게터는 메소드를 거쳐 저장된 데이터를 get하고, 외부 파라미터를 클래스로 옮겨 메소드를 실행시키기위해 외부 파라미터를 set한다.
  • toString은 클래스의 멤버변수를 하나의 문자열로 표현해준다.
  • toString에서 오버라이딩이 된 이유는 자바 내부 메서드인 toString은 자바 최상위 클래스 Object에서 정의되었는데, 하위 클래스에서 사용해주면서 오버라이딩을 통해 멤버변수를 출력할 수 있게 재정의하지 않으면 클래스 주소값만 나오기 때문.
package com.acompany;

public class Product {
    // 멤버변수로 데이터 타입을 정해보자.
    // 일반적으로 자바는 private으로 멤버변수 정의.
    private long productId; // 20억개 이상의 상품명이 나올것을 예상
    private String title;
    private int price;
    private String createDate;
        // => 멤버변수가 4개인 Product 클래스가 만들어짐.
        // 멤버변수가 private이기 때문에 외부에서 접근하지 못해서 Setter, getter를 만들어서 사용해야 함.

    //// 생성자와 게터 세터 만들자 ////
    // 마우스 오른쪽 클릭 -> Generate

    public Product(long productId, String title, int price, String createDate) {
        this.productId = productId;
        this.title = title;
        this.price = price;
        this.createDate = createDate;
    }
    // 생성자를 위에처럼 인위적으로 만들면 디폴트 생성자가 자동으로 안만들어지기 때문에 
    // 디폴트 생성자 따로 만들기
    public Product() {
        productId=22;
        title="iphone7";
        price=5000;
        createDate="2020-03-18";
    }

    // 게터 세터 만들기
    public long getProductId() {
        return productId;
    }

    public void setProductId(long productId) {
        this.productId = productId;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public String getCreateDate() {
        return createDate;
    }

    public void setCreateDate(String createDate) {
        this.createDate = createDate;
    }

    // toString 생성 (똑같이 Generate에서)
    // toString : 멤버변수들의 입력값을 모두 한 줄로 묶어 문자열 형태로 출력
    @Override
    public String toString() {
        return "Product{" +
                "productId=" + productId +
                ", title='" + title + '\'' +
                ", price=" + price +
                ", createDate='" + createDate + '\'' +
                '}';
    }
}
  • Product 클래스를 Main 함수에서 사용하기 위해 com.acompany 패키지의 하부패키지 app을 만든다.
  • Product 클래스를 사용할꺼니 import 해준다.
  • Product 내의 필드(멤버변수)와 메소드를 사용하기 위해 myProd라는 디폴트 객체를 만든다.
  • 세터를 통해 파라미터값을 주어 Product 클래스를 사용한다.
package com.acompany.app;
// com.acompany 밑의 app 패키지
import com.acompany.Product;
// Product 클래스를 사용할거니 import 해준다.

public class AppMain {
    public static void main(String[] args) {
        Product myProd = new Product ();
        // Product 클래스를 사용하기 위한 디폴트 객체 생성 (파라미터 사용하지 않음)
        System.out.println(myProd);
        // => 파라미터를 사용하지 않았으므로 네 개의 멤버변수의 디폴트값이 출력됨

        System.out.println();

        // 이젠 세터를 통해 파라미터값 줘서 출력하기.
        myProd.setProductId((1));
        myProd.setPrice(2000);
        myProd.setTitle("Iphone 5");
        myProd.setCreateDate("2020-08-15");
        System.out.println(myProd);

    }

 

 

 

 

 

 

 

 

 

 

static 블럭은 위의 코드중에 static { } 이부분이다. 

이 예시는 드라이버 로딩을 하는것인데, 데이터베이스와의 연동 요청을 한 번만 하면 된다. 이때 스태틱 블럭을 포함시키면서 데이터베이스의 드라이버가 단 한번 요청되게 된다. 

 

 

static 메소드 - 팩토리 메소드

 

팩토리 메소드

 

static 메소드는 흔히 팩토리 메소드를 만드는 데 사용됨

클래스를 새로운 인스턴스를 반환하는 static 메소드

불필요하게 새 객체를 생성하는 대신 공유 객체를 반환하는 것도 가능 

 

 

 

 

 

 

 

 

 

 

팩토리 메소드 : 객체를 만들어주는 메소드다. 주로 static으로 존재한다.

getCurrencyInstance()는 클래스를 통해 바로 접근하므로 스태틱 메소드다. 이 메소드는 넘버포맷의 객체를 만들어 currencyFormatter에 할당한다.

 

 

패키지

 

패키지 - 자바에서는 연관된 클래스를 한 패키지에 넣어둠

작업을 조직화하고, 다른 사람이 제공한 코드와 라이브러리를 분리

표준 자바 라이브러리도 모두 패키지로 구분

java.lang, java.util, java.math

 

 

패키지 : 클래스들을 특정 관련이 있는것들끼리 분리시켜놓는것. 파일 시스템의 디렉토리와 같다.

 

패키지 선언

 

패키지 이름은 java.util.regex처럼 점으로 구분된 식별자 목록

패키지 이름에서 유일함을 보장하기 위해 인터넷 도메인 명을 뒤집어서 사용

클래스를 패키지 안에 넣으려면 소스 파일의 첫 문장에 package 문 추가

 

ex) 

package com.demo; // com 밑에 demo라는 패키지에 새 클래스를 집어넣는다.

public class Employee {

 

}

 

 

클래스 패스

 

 

Jar 파일

 

클래스 파일을 포함하는 아카이브 파일 - zip 파일과 구조가 같음

클래스 파일을 파일시스템에 바로 저장하지 않음

라이브러리 뿐만 아니라 프로그램을 묶는데도 사용됨

 

 

클래스 패스

 

프로젝트에서 라이브러리 JAR 파일을 사용할 때 클래스 패스 지정

해당 파일 위치를 컴파일러와 JVM에게 알려줌

 

 

클래스 임포트

 

import문을 사용하면 전체 이름 없이도 클래스 사용 가능

import java.util.Random; 문을 사용하면, 

java.util.Random 대신에 Random으로 사용할 수 있음

와일드 카드 사용 가능 - java.util.*;

 

 

정적 임포트

 

import static java.lang.Math.*;

sqrt(pow(x, 2) + pow(y, 2)); // 즉, Math.sqrt와 Math.pow를 의미

=> 정적 임포트를 하게되면 스태틱 메소드를 임포트하게되면 클래스 명 없이 메소드이름만 가지고 사용가능하다.

 

 

ThinkPoint

Static 메소드의 장단점은?

Static에 대한 장점을 크게 두가지로 나눌 수 있다.

첫째로, static을 쓴 변수나 메소드는 객체생성 없이 모든 객체가 아무런 제약없이 공유할 수 있다.

둘째로, static을 쓴 변수는 값을 공유하므로 연속적으로 그 값의 흐름을 이어갈 수 있다는 것이다.

다시말해서 일반변수는 객체생성시마다 그 값이 초기화되지만 정적변수는 객체생성을 하지 않으므로 다른 객체에서 계속적으로 이어서 그 값을 변화시킬 수 있다는 것이다.

자바에서 상수를 쓸때 static과 final을 함께 사용한다.

반응형