clone, 리플렉션 , Time

28447 단어 JavaJava

객체 복제 clone()

신뢰하지않은 영역으로 원본객체를 넘길경우 원본객체의 데이터가 훼손될수있기때문에 복제본을 넘긴다. 데이터의 보호를 위해서 사용한다.

얕은복제

단순히 필드값을 복사해서 객체를 복제하는것

Object의 clone()메소드는 얕은복제된 객체를 리턴하고 이 메소드로 객체를 복제하려면 원본객체는 java.lang.Cloneable 인터페이스를 구현해야한다. Cloneable 을 implements 한다는것은, 클래스 설계자가 복제를 허용한다고 의도적으로 표시하는것이다.

public class Member implements Cloneable {

 public String id;
 public String name;
 public String password;
 public int age;
 public boolean adult;

    public Member(String id, String name, String password, int age, boolean adult) {
        this.id = id;
        this.name = name;
        this.password = password;
        this.age = age;
        this.adult = adult;
    }

    public Member getMember() {
        Member cloned = null;
        try {
            cloned = (Member) clone();

        } catch (CloneNotSupportedException e) {}
        return cloned;
    }
}

clone()은 예외처리가 필요하다.

 public static void main(String[] args) {

        Member original = new Member("blue", "홍길동", "12345", 25, true); // 원본객체 생성
        Member cloned = original.getMember();
        cloned.password = "56789"; // 복제객체를 얻은 후에 패스워드변경
        System.out.println("password: " + original.password);  // 12345출력, 원본객체는 변하지않음

    }

깊은 복제

얕은복제는 참조타입필드는 번지만 복제되기 때문에 원본객체의 필드와 복제객체의 필드는 같은 객체를 참조하게된다.

복제객체에서 참조객체를 변경하면 원본객체도 변경된객체를 가지게된다.
이것이 얕은복제의 단점이다.

깊은복제는 참조하고있는 객체도 복제한다.

import java.util.Arrays;

public class Member implements Cloneable {

    public String name;
    public int age;
    public int[] scores;
    public Car car;


    public Member(String name, int age, int[] scores, Car car) {
        this.name = name;
        this.age = age;
        this.scores = scores;
        this.car = car;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException{
        Member cloned = (Member) super.clone();// 얕은복사를 해서 name,age 를 복사 , Object의 clone() 호출 
        cloned.scores = Arrays.copyOf(this.scores, this.scores.length); // scores 를 깊은복제
        cloned.car = new Car(this.car.model); // car를 깊은 복제 
        return cloned;
    }

    public Member getMember() {
        Member cloned = null;
        try {
            cloned =(Member)clone();// 재정의된 clone() 메소드 호출 

        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return cloned;
    }
    
    
}

깊은복제후 복제 본변경은 원본에 영향주지않는다.

 public static void main(String[] args) {

        Member original = new Member("홍길동", 25, new int[]{90, 90}, new Car("소나타"));// 원본객체 생성
        Member cloned = original.getMember();
        cloned.scores[0] = 100;
        cloned.car.model = "그랜저"; // 깊은복제후, 참조객체의 데이터를 변경
    }

리플렉션

자바의Class 객체를 이용하면 클래스의 생성자,필드,메소드 정보를 알아낼수있다. 이걸 리플렉션이라고한다.

Class객체는 getDeclaredFields(), getDeclaredMethods() 를 제공하고 이들은 클래스에 선언된 멤버만 가져오고 상속된멤버는 가져오지않는다.

상속된 멤버도 얻고싶으면 getFields(), getMethods()를 이용해야한다.
단 이둘은 public 멤버만 가져온다.

Date, Time

클래스 이름이 Date인데 시간까지 다룬다거나,
멀티스레드 환경같은 경우에서 객체의 상태를 바꿀수있기때문에 thread safe 하지않고,
타입안정성이없다. (월이0부터 시작한다거나...등), month에 아무것도 들어올수있다. -100도 들어갈수도있다.
자바 8이후로는 거의사용하지않는다.

기계용 시간

public static void main(String[] args) {
        Instant instant = Instant.now();
        System.out.println(instant); // 기계시간 출력 , 기준시 UTC(영국), GMT

    }

내 현재시간은 2021-10-29 오후 3시23분인데 다른시간이나왔다.
이를맞춰주기위해 Zone을 설정해야한다.

ZoneID zone = ZoneId.systemDefault();
        System.out.println(zone);
        ZonedDateTime zonedDateTime = instant.atZone(zone);

인류용 시간

    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        System.out.println(now); // 서버가 미국에있다면 미국의 시간을 표현한다.

        LocalDateTime birthday = LocalDateTime.of(1994, Month.MAY, 5, 0, 0, 0); // 생일
        ZonedDateTime nowInKorea = ZonedDateTime.now(ZoneId.of("Asia/Seoul")); // 한국시간 출력
    }

기간을 표현하는 APi

  LocalDate today = LocalDate.now();
        LocalDate thisYearBirthday = LocalDate.of(2021, Month.NOVEMBER, 25);

        Period period = Period.between(today, thisYearBirthday);
        System.out.println(period.getDays()); // 지금부터 다음생일까지의 기간 출력

        Period until = today.until(thisYearBirthday); // 오늘부터 생일까지
        System.out.println(period.get(ChronoUnit.DAYS)); //  일수기준으로 출력

둘다 27출력

기계용 차이를 출력

        Instant now = Instant.now();
        Instant plus = now.plus(10, ChronoUnit.SECONDS);
        Duration between = Duration.between(now, plus);
        System.out.println(between.getSeconds()); //기계용 차이를 출력
    LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter MMddyyyy = DateTimeFormatter.ofPattern("MM/dd/yyyy");
        System.out.println(now.format(MMddyyyy)); // DateTimeFormatter 를 사용하여 원하는 포맷을 정하여 출력가능

        LocalDate parse = LocalDate.parse("05/05/1994", MMddyyyy);
        System.out.println(parse); // 파싱

이것이자바다 참조

좋은 웹페이지 즐겨찾기