반응형

public class ChanningClass {
    public final String status;

    private ChanningClass(String status){
        this.status = status;
    }

    // BuildersImpl 인스턴스를 처음 생성할 메서드가 필요하다.
    public static Builders startMethod() {
        return new BuildersImpl();
    }
    
    // Builder 인터페이스
    interface Builders{
        Builders method1(String doSomething);
        Builders method2(String doSomething);
        ChanningClass build();
    }
    
    // Builder 구현체
    private static class BuildersImpl implements Builders{
        private String status;

        BuildersImpl(){
            this.status = "";
        }

        @Override
        public Builders method1(String doSomething) {
            this.status = this.status + doSomething;
            return this;
        }

        @Override
        public Builders method2(String doSomething) {
            this.status = this.status + doSomething;
            return this;
        }
        
        // 작성한 상태값을 인스턴스를 만들며 반환
        @Override
        public ChanningClass build() {
            return new ChanningClass(this.status);
        }
    }
}

 

메서드를 시작할 때 startMethod() 내부 인스턴스를 만들고,

 

인터페이스를 이용해 메서드 체이닝을 한다.

 

메서드가 오버라이딩 되어있다면 자식 메서드가 동작한다는 점을 이용하여 동작시킨다.

 

메서드가 종료할 때 build() 외부 인스턴스를 만들어 반환한다.

 

 

 

 

 

 


ChanningClass builders1 = ChanningClass.startMethod().method1("aaaa").method2("bbbb").build();
ChanningClass builders2 = ChanningClass.startMethod().method2("bbbb").method1("aaaa").build();

System.out.println(builders1.status);
System.out.println(builders2.status);

 

 

 


@Builder

 

public static Book.BookBuilder builder() {
   return new Book.BookBuilder();
}

 

public static class BookBuilder {
   private Long id;
   private String BookName;
   private Publisher publisher;
   private List<BookLoan> loanBookList;
   private List<BookReservation> bookReservationList;

   BookBuilder() {
   }

   public Book.BookBuilder id(final Long id) {
      this.id = id;
      return this;
   }

   public Book.BookBuilder BookName(final String BookName) {
      this.BookName = BookName;
      return this;
   }

   public Book.BookBuilder publisher(final Publisher publisher) {
      this.publisher = publisher;
      return this;
   }

   @JsonIgnore
   public Book.BookBuilder loanBookList(final List<BookLoan> loanBookList) {
      this.loanBookList = loanBookList;
      return this;
   }

   @JsonIgnore
   public Book.BookBuilder bookReservationList(final List<BookReservation> bookReservationList) {
      this.bookReservationList = bookReservationList;
      return this;
   }

   public Book build() {
      return new Book(this.id, this.BookName, this.publisher, this.loanBookList, this.bookReservationList);
   }

 

@Builder는 굳이 인터페이스까진 만들지 않는다.

 

내부 인스턴스를 만드는 builder(), 외부 인스턴스를 만드는 build() 

 

시작과 끝 메서드의 사용 방식은 같다.

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

반응형
반응형

본 글은 책 자바의 정석을 ref 하여 요약한 것입니다.


https://komas.tistory.com/68

 

[JAVA]자바 익명 클래스와 람다식 정리

익명 클래스는 말 그대로 클래스의 이름이 없다는 말이다. 이름이 없으므로 생성자를 가질 수 없다. 익명 클래스를 정의하려면 상속을 받거나 인터페이스로 구현해야한다. 참조 변수에 넣어두

komas.tistory.com

 

https://komas.tistory.com/69

 

[JAVA] 자바 메소드 참조

메서드 참조란 말 그대로 다른 클래스의 메소드를 참조하여 사용한다입니다. 빌려쓴다고 이해하시면 편합니다. (호출이 아닌 구현부를 빌림) 코드로 설명하겠습니다. public class ProviderClass { public

komas.tistory.com

 

 

 

 


 

스트림

자바 8부터 추가된 함수적 스타일 처리

중간처리는 지연되고, 최종 처리가 시작되면 처리를 시작한다.

 

✔ 스트림의 종류

Stream, IntStream, LongStream, DoubleStream

 


 

✔ 스트림 만들기

List<Integer> list = Arrays.asList(1,2,5,3);
Stream<Integer> slist= list.stream();

long[] arr = {1,2,10,5,3,4,3};
LongStream sarr = Arrays.stream(arr);

 

컬렉션 프레임워크는 Stream<T>  로 변환된다.

mapToXXX()로 변환하면 IntStream, LongStream, DoubleStream로 변경할 수 있다.

 

기본형 배열은 type에 맞게  IntStream, LongStream, DoubleStream 로 변환된다.

객체 배열일 경우 Stream<T> 로 변환된다.

 

 

객체는 Stream<T>

기본형 배열은 IntStream, LongStream, DoubleStream

 

 


 

✔ 중간 처리 함수

매핑, 필터링, 정렬

 

 

skip(n)

개수만큼 건너뛴다.

 

 

limit(n)

개수만큼 제한한다.

 

 

peek(Consumer)

forEach와 비슷한 역할을 하는 중간 연산이라고 보면 된다.

보통 단순히 중간 조회를 위해 사용됨

 

 

distinct()

중복을 제거한다. equals() 값이 같으면 제거, IntStream, LongStream, DoubleStream 일 경우 값이 같으면 제거

 

 

filter(Predicate)

true인 값만 남기고 제거한다.

 

 

map(Function)

요소를 대체하는 새로운 요소로 구성된 스트림을 만든다. (보통 type변환, 일괄 연산 등)

 

map() -> (객체 -> 객체), (기본형 -> 기본형), 값 변환

mapToInt -> IntStream으로 변환

mapToLong -> LongStream으로 변환

mapToDouble -> LongStream으로 변환

mapToObj -> 객체로 변환

type 변환과 값 변경도 가능

 

List<Integer> list = Arrays.asList(1,2,5,3);
Stream<Integer> slist= list.stream();
IntStream is = slist.mapToInt(e->e);

long[] arr = {1,2,10,5,3,4,3};
LongStream sarr = Arrays.stream(arr);
Stream<Integer> bs = sarr.mapToObj(e -> (int) e);

 

flatMap()

스트림의 요소가 배열일때  flatten Stream을 만들 때 사용한다.

 

 

boxed()

IntStream, LongStream, DoubleStream  ---->   Stream<T>

 

 

sorted(Comparator)

정렬을 제공한다.

Comparable이 제공된 객체를 사용하거나, Comparator를 제공해주면 된다.

* IntStream, LongStream, DoubleStream 일 경우 인수를 제공하지 않으면 오름차순으로 정렬, 내림차순을 원할 경우 Comparator.reverseOrder()

 

* thenComparing() - 정렬 추가가 가능

* reversed() - 내림차순 가능

 

List<Student> students = Arrays.asList(
                new Student("Lee", 1),
                new Student("Lee", 2),
                new Student("Park",1),
                new Student("Park",2),
                new Student("Kim",2)
        );

       List<Student> sortedList= students.stream().sorted(
               Comparator.comparing(Student::getName)
               .thenComparing(Student::getNumber)
               .reversed()
               ).collect(Collectors.toList());

        System.out.println(sortedList);
        
//        [Student{name='Park', number=2}, Student{name='Park', number=1}, 
//        Student{name='Lee', number=2}, Student{name='Lee', number=1}, Student{name='Kim', number=2}]

 


 

✔ 최종 처리 함수

반복, 카운팅, 평균, 총합

최종 처리 함수의 반환 타입은 기본형이거나 OptionalXXX

 

 

forEach(Consumer)

요소를 하나하나씩 처리한다.

 

 

sum() - IntStream, LongStream, DoubleStream

반환 타입

타입에 맞는 기본형

 

 

count() - IntStream, LongStream, DoubleStream

반환 타입

long

 

 

max(), min() - IntStream, LongStream, DoubleStream

Stream<T> 일 경우 인수로 Comparator 필요

IntStream, LongStream, DoubleStream 일 경우 필요하지 않다.

반환 타입

Stream<T>일 경우 Optional<T>

IntStream, LongStream, DoubleStream 일 경우 OptionalXXX

 

 

average() - IntStream, LongStream, DoubleStream

반환 타입

OptionalDouble

 

 

findFirst()

반환 타입

Stream<T>일 경우 Optional<T>

IntStream, LongStream, DoubleStream 일 경우 OptionalXXX

 

 

reduce(identify, BinaryOperator)

identify는 요소가 없을 때 반환하는 값(Default)

BinaryOperator에 요소 하나하나씩 누적해가며 계산한다.

반환 타입

identify를 지정하면 기본형으로 반환

지정하지 않으면 OptionalXXX로 반환

 

 

allMatch(Predicate)

모든 요소가 일치하면 true 반환

anyMatch(Predicate)

하나의 요소라도 true라면 true 반환

noneMatch(Predicate)

모든 요소가 false라면 true 반환

 


 

✔ collect(Collector)

collect 함수는 내부에 수집기를 정의해줘야 한다.

보통 Collectors(수집기 구현체)에 구현된 메서드들을 활용한다.

 

Student[] students = {new Student("Lee",23), new Student("Park",26), new Student("Kim",26)};

List<Integer> ageList = Arrays.stream(students)
        .map(e-> e.age)
        .collect(Collectors.toList());
System.out.println("ageList " + ageList);

Set<Integer> ageSet = Arrays.stream(students)
        .map(e-> e.age)
        .collect(Collectors.toSet());
System.out.println("ageSet " + ageSet);

TreeSet<Integer> ageTreeSet = Arrays.stream(students)
        .map(e -> e.age)
        .collect(Collectors.toCollection(()-> new TreeSet<Integer>())); // TreeSet::new
System.out.println("ageTreeSet " + ageTreeSet.higher(23));

 

 

 

collect() 사용자 직접 정의

Collector(수집기) 인터페이스를 구현하기 위해선 대략 3가지의 요소가 필요하다.

 

supplier

 - 수집된 데이터를 담을 구현체 생성 (싱글 스레드는 하나, 멀티 스레드는 여러개가 생성)

accumalator

 - 생성된 객체에 원하는 요소 수집

combiner

 - 병렬 처리된 각 컨테이너 객체들을 결합 지정

 

List<Student> students = Arrays.asList(
        new Student("Lee", 1),
        new Student("Park",1),
        new Student("Kim",2),
        new Student("Cha",2)
);

List<Student> ls = students.stream().
        filter((s)-> s.getNumber() == 1).
        collect(ArrayList::new, List::add, List::addAll);

System.out.println(ls);
// [Student{name='Lee', number=1}, Student{name='Park', number=1}]

 

 

 

collect() 그룹핑

Collectors.groupingBy()

- 내부에서 key, Collector(수집기)를 지정한다.

 

Collectors.mapping(Function, Collector)

- 매핑한 후 Collector(수집기)를 사용한다.

 

List<Student> students = Arrays.asList(
        new Student("Lee", 1),
        new Student("Park",1),
        new Student("Kim",2),
        new Student("Cha",2)
);

Map<Integer, List<Student>> m1 = students.stream()
        .collect(Collectors.groupingBy(Student::getNumber)); // key
System.out.println(m1);
// {1=[Student{name='Lee', number=1}, Student{name='Park', number=1}], 2=[Student{name='Kim', number=2}, Student{name='Cha', number=2}]}


Map<Integer,List<String>> m2 = students.stream()
                .collect(Collectors.groupingBy(
                        Student::getNumber, // key
                        Collectors.mapping(Student::getName, Collectors.toList()))); // value
System.out.println(m2);
// {1=[Lee, Park], 2=[Kim, Cha]}


Map<Integer,List<String>> m3 = students.stream()
        .collect(Collectors.groupingBy(
                Student::getNumber, // key
                HashMap::new, // 구현체 지정 가능
                Collectors.mapping(Student::getName, Collectors.toList()))); // value
System.out.println(m3);
// {1=[Lee, Park], 2=[Kim, Cha]}

 

 

 

partioningBy(Predicate, Collector)

true인 것만 적용하여 분리

반환 타입은 <boolean>

 

 

Collectors 수집기 함수

averagingDouble() 

counting()

maxBy(Comparator)

minBy(Comparator)

summingInt, Long, Double()

 

reducing(identity, BinaryOperator

joining(구분자) - 문자열 결합

 

 

 

collect 개략도

collect( 수집기 )

collect( Collectors.groupingBy ( 키, 수집기 ) )

collect( Collectors.groupingBy ( 키, Collectors.mapping ( 매핑, 수집기 ) )

 

 

 


 

반응형
반응형

본 글은 책 자바의 정석을 ref 하여 요약한 것입니다.


 

프로세스

실행 중인 프로그램

하나의 프로세스는 하나 이상의 스레드 이상을 갖는다.

 

스레드

실제 작업을 수행하는 단위

 

멀티태스킹

여러 프로세스를 동시에 실행

 

멀티쓰레딩

여러 스레드가 동시에 실행

 

* 하나의 cpu코어는 번갈아서 여러 작업을 동시성 처리한다. 

매우 빠른 속도로 여러 스레드를 처리하기 때문에 병렬적으로 처리하는 것처럼 보인다.

 


 

구현

Thread를 상속받아서 run()을 오버 라이딩

Runnable을 구현해서 run()을 오버 라이딩, Thread 생성자의 인수로 제공

 

실행

start() 메서드로 시작, 사실 시작하는 것은 아니고 실행 대기상태가 된다.

* start()는 새로운 call stack을 생성한 후, run()을 호출한다.

* 한 스레드에서 예외가 발생해도 다른 스레드에 영향을 미치지 않는다.

종료된 스레드는 재실행이 불가능하다. 새로 생성하여 start() 해야 한다.

 


 

스레드 그룹

폴더 안에 폴더를 만들듯이 스레드 그룹에 하위 스레드 그룹을 생성할 수 있다.

쓰레드 그룹을 지정하지 않는다면 main 쓰레드 그룹에 속한다.

모든 스레드 그룹은 기본적으로 main스레드 그룹 하위에 속하게 된다.

 

데몬 쓰레드

일반 스레드가 모두 종료되면 강제적으로 종료되는 보조 쓰레드

데몬 스레드를 지정 후 start() 해야 한다. 역은 성립하지 않는다.

 


 

스레드의 실행 제어

NEW - 아직 start()되지 않은 상태

RUNNABLE - 실행 대기 상태, 실행 중

* 실행 대기열에서 저장되어 자신의 차례가 되면 실행

BLOCKED - 동기화 블록에 의해 일시 정지된 상태

WAITING, TIMED_WAITING - 일시 정지 상태

TERMINATED - 종료

 

 

static sleep()

스레드를 멈추게 한다.

항상 try - catch문으로 예외 처리해줘야 한다.

interrupt()가 호출되면 깨어나 실행 대기 상태가 된다.

Thread.sleep()   자신에게 적용한다. 

 

static yield()

다음 차례의 스레드에게 양보한다.

Thread.yield()   자신에게 적용한다.

 

join()

ThreadB.join()

A인 자신을 멈추고, ThreadB가 먼저 작업을 수행하도록 한다.

ThreadB가 작업을 마치면 수행한다.

항상 try - catch문으로 예외 처리해줘야 한다.

sleep()과 같이 interrupt()로 대기상태에서 벗어날 수 있다.

 

interrupt()

일종의 flag

1. 스레드를 멈추라고 요구한다.

** 강제로 멈추진 못하고 interrupted(), isInterrupted() 상태를 true로 바꾼다.

2. 일시정지 상태인 스레드를 실행 대기 상태로 바꾼다.

** 일시정지 상태에서 실행 대기 상태로 바뀌면, interrupted(), isInterrupted() 상태를 false로 바꾼다.

 


 

스레드의 동기화

공유 데이터를 사용하는 곳에 임계 영역을 설정하여 하나의 스레드만 접근할 수 있도록 한다.

1. 메서드 전체를 임계 영역으로 지정

2. 특정한 영역을 임계 영역으로 지정

** 공유 데이터가 있는 곳에 synchronized를 선언한다.

 

wait(), notify(), notifyAll()

** 동기화 블록 내에서만 사용할 수 있다.

** Object에 정의되어 있다.

 

번갈아 작업하는 교대작업 시

 

wait()

현재 공유 객체를 사용중인 쓰레드를 정지

스레드가 락을 반납하고 대기한다.

 

notify()

이전에 작업을 중지했던 임의의 스레드를 실행 대기 상태로 만든다.

오래 기다린 스레드가 락을 얻는 것을 보장하진 못한다.

 

** 제공자 스레드가 데이터를 충분히 제공했다면 wait(), 소모자 스레드를 깨운다. notify()

** 소모자 쓰레드가 데이터를 전부 소진했다면 wait(), 제공자 쓰레드를 깨운다. notify()

 

 

Lock과 Condition을 이용한 동기화

ReentrantLock 

** 락을 풀고 다시 락을 얻어서 진입한다.

** 수동으로 락을 걸고, 해제해야 한다.

 

ReentrantReadWriteLock

** 읽기 락이 걸려있다면 다른 읽기 락도 중복해서 접근할 수 있다.

 

StampedLock

** 낙관적 읽기 락이 추가됐다.

** 낙관적 읽기 락은 쓰기 락에 의해 바로 풀린다.

** 낙관적 읽기 락이 실패했다면, 읽기 락을 걸어서 읽어와야 한다.

 

 

Condition

스레드 종류에 따라 구분하여 통지할 수 있게 한다.

락으로부터 여러 Condition을 생성한다.

Condition을 제공자, 소모자에게 부여하여 통지 대상을 명확하게 한다.

 


 

volatile

싱글 코어에서는 문제가 없지만, 멀티 코어에서는 캐시 메모리에 저장된 값을 사용하여 문제가 발생한다.

volatile을 사용하게 되면 캐시가 아닌 메모리에서 읽어오기 때문에 불일치가 해결된다.

synchronized 또한 캐시와 메모리 간의 동기화가 이루어지기 때문에 불일치가 해결된다.

 

JVM이 4byte로 데이터를 처리하기 때문에 int 이하에서는 한 번에 읽고 쓰는 것이 가능하지만,

long, double은 8byte이기 때문에 데이터를 처리하는 중에 다른 스레드가 끼어들 수 있다.

이러한 문제를 해결하기 위해 변수에 volatile을 선언해주어 원자화로 만들어 주면 된다. (동기화는 아니다.)

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형
반응형

본 글은 책 자바의 정석을 ref 하여 요약한 글입니다.


 

제네릭스

컴파일 타임 시 타입 체크를 해주는 기능

다룰 객체의 타입을 미리 명시하여 형변환을 제거

추가적인 형변환을 하지 않아 성능이 향상된다.

컴파일 이후부터는 지정된 타입으로 바뀐다.

클래스와 메서드에 선언할 수 있다.

 

 

제한

static 에는 사용 불가능 (클래스 변수는 공유가 되는데, 인스턴스마다 제네릭 타입이 달라지므로)

new 배열 생성 코드 불가능 (new 연산자는 컴파일 타임 때 타입을 정확히 알아야 함)

 

 

형변환

지정된 제네릭 타입의 자손을 사용하면 형변환이 된다.

void add(T t)

*T가 부모일 경우 T의 자손도 인수로 사용할 수 있다.

 

 

제한된 지네릭 

<T extends 부모 클래스>

부모 클래스와 자손 클래스들만 사용 가능

불필요한 다른 타입의 사용을 막는다.

사용할 수 있는 필드, 메서드는 부모 클래스의 것으로 제한된다.

 

 

✔ 제네릭 메서드

메서드의 리턴 타입 앞에 제네릭 타입을 지정하며 지역변수와 비슷하게 사용된다.

클래스의 제네릭 타입과는 관련이 없다. 메서드 내부에서만 사용된다.

<사용할 제네릭 타입> 리턴타입 메서드명(매개인자)

 

 

 

 

✔ 와일드카드

메서드의 리턴 타입, 매개 인자에 사용된다.

제네릭 타입이 불공변이기 때문에 사용한다.

 * 불공변: 변하지 않는다.

 * List<Object> list = new ArrayList<Integer>()

 * 컴파일 안된다. 제네릭은 형변환 개념이 없다 <Object> 와 <Integer>는 아무 상관이 없다.

 

제네릭 형 변환

Clazz<String>  <==>  Clazz<Object>   형변환 // 불가능 (불공변)

Clazz<?>   <==>   Clazz<Object>   형변환  //  가능 (와일드 카드 사용 이유)

논제네릭과 제네릭   형변환  //  가능

 

 

메서드 인자 제네릭 타입

메서드는 타입이 달라야 오버 로딩이 가능한데, 지네릭 타입이 불공변이라 오버로딩이 되지 않는다.

 

void add(FruitBox<Fruit> f)   // FruitBox<Fruit> 만 인수로 들어올 수 있다.
void add(FruitBox<Apple> f)    // FruitBox<Apple> 만 인수로 들어올 수 있다.
오버로딩 불가능

어떤 제네릭 클래스가 들어올지 몰라서,
void add(FruitBox<?> f)

 

 

와일드카드는 메서드의 인수가 제네릭 타입만 다를 때 여러 제네릭 타입이 사용될 수 있도록 한다.

와일드카드를 사용하면 제네릭 타입이 무엇인지 알 수 없다.

정확한 제네릭 타입을 몰라서 확실하게 사용할 수 있는 기능만 사용한다.

 

메서드 인자로 와일드 카드를 사용할 때 메서드 구현부에서의 제한

 

(1)  <?> 제한 없음

 

(2)  <? extends T> T와 그 자손들만 가능

상한 제한으로 하게 되면 출력은 할 수 있고, 입력이 불가능하다.

출력: T의 출력 메서드를 자손 클래스들이 모두 상속했거나, 오버라이딩하여 가능하다.

입력: 제네릭 클래스가가 T의 하위 타입을 사용할 경우 T를 입력할 수 없다.

 

(3)   <? super T> T와 그 조상들만 가능

하한 제한으로 하게 되면 반대로 출력을 할 수 없고, 입력만 할 수 있다.

입력: T와 그 조상들을 타입 변수로 제한하므로 T 타입은 무조건 입력이 될 수 있다.

출력: 상위 타입이 T타입의 메서드를 갖고 있지 않을 수 있다.

 

(가능한 경우에도 자바에서는 상한 제한에서 입력, 하한 제한에서의 출력을 불가능하게 막아둠)

 

 

 

 

✔ 제네릭 타입의 제거

하위 자바 버전과의 호환성을 유지하기위해 컴파일때 제거

 


 

열거형 (Enum)

 

서로 관련있는 상수를 편하게 관리하기 위해 등장

사용할 도메인 범위를 지정할 수 있다는 장점을 갖는다.

값뿐만 아니라 타입까지 사용하기 때문에 정확한 비교가 가능하다.

 

메서드

ordinal() 열거형 상수의 순서를 반환

name() 열거형 상수의 이름을 반환

values() 열거형 상수들을 배열에 담아서 반환

 

지정된 멤버 추가

enum Direction { EAST(-1), SOUTH(5), WEST(100), NORTH(10);

private final int value;

Direction(int value){

     this.value = value;

}

불연속 열거형 값을 사용하기 위해선 생성자와 인스턴스 변수가 필요하다. (생성자는 private가 생략됨)

상수에 두가지 값을 사용하려면 두가지의 인스턴스 변수가 필요하다.

 

열거형 상수의 이해

열거형 상수 하나하나가 객체다.

객체의 주소가 바뀌지 않으므로 == 비교가 가능하다.

 

 

 


 

어노테이션

주석처럼 프로그램에 영향을 미치지 않으면서, 다른 프로그램에게 유용한 정보를 제공

 

 

메타 어노테이션 - 어노테이션을 위한 어노테이션

 

@Target

적용 가능한 대상을 지정

 

@Retention

어노테이션이 유지되는 기간

Runtime으로 지정시 Reflection을 통해 정보를 읽어서 처리할 수 있다.

 

@Inherited

자손 클래스에 상속되도록 한다.

 

@Repeatable

해당 어노테이션을 여러번 지정 가능

 

 

 

 

어노테이션 타입 지정

어노테이션에 선언된 메서드를 요소라고 한다.

요소들의 값을 빠짐없이 적어주어야 한다. (default가 지정되어 있으면 적어주지 않아도 된다.)

요소가 하나일 경우 이름 생략 가능

 

[규칙]

메서드 선언에는 매개변수를 사용할 수 없다.

예외를 선언할 수 없다.

메서드의 반환형에는 기본 타입, 문자열, 배열, 열거형, Class<> 클래스, 어노테이션 

상수를 선언할 수도 있다.

 

 

 

 

반응형
반응형

 

 

HashSet에서는 equals()와 hashCode()를 둘 다 사용한다?

 

HashSet은 hashCode()만 사용해서 구현을 하는 줄 잘못 알고 있었다.

 

 


 

기본적으로 bucket에 데이터를 입력할 때 hashCode()를 이용하는 것은 맞다.

 

hashCode 값이 같은 데이터의 발생 즉, 충돌이 일어난다면 그때 equals()를 사용한다.

 

예를들어 "5"라는 데이터를 입력했을 때 "9"라는 데이터가 같은 hashCode를 반환할 수 있기 때문이다.

 

그때 equals()를 사용해서 정말 같은 데이터인지 확인할 때 사용한다.

 


 

(1) hashCode()가 같다. equals()가 같다. => 중복 데이터이므로 저장이 불필요 

 

(2) hashCode()가 같다. equals()가 다르다. => 우연하게 hashcode가 같은 경우이므로 데이터 저장

* chaining 기법으로 충돌을 해결

* LinkedList로 연결해놓는다. value가 8개를 넘어가면 RBtree로 변환.

* 검색시에는 hashcode()로 bucket index를 찾고, equals()로 비교하여 value를 확인한다.

 


 

hashCode()는 bucket index를 찾을 때, equals()는 내부에서 bucket value를 비교할 때 사용한다.

그래서 hashCode(), equals()를 둘다 overrirde해줘야 하고, 같은 field를 사용해야 한다.

 

반응형
반응형

 

 

인터페이스 Collection <- (List, Set)

 

✔ 전체

clear()

isEmpty()

equals(Collection)

List<Integer> list1 = new ArrayList<>();
list1 = Arrays.asList(1,2,3);
System.out.println(list1.equals(Arrays.asList(1,2,3))); // true

 

✔ 요소

add(Object)

addAll(Collection)

remove(Object)

removeAll(Collection)

retainAll(Collection)

//removeAll
Collection<Integer> list1 = new ArrayList<>(Arrays.asList(1,2,3));
Collection<Integer> list2 = new ArrayList<>(Arrays.asList(1,2));
list1.removeAll(list2);
System.out.println(list1); // 3

//retainAll
Collection<Integer> list3 = new ArrayList<>(Arrays.asList(1,2,3));
Collection<Integer> list4 = new ArrayList<>(Arrays.asList(1,2));
list3.retainAll(list4);
System.out.println(list3); // 1, 2

 

✔ 변환

toArray()

iterator()

 

 


인터페이스 List <- (ArrayList, LinkedList)

 

✔ 요소

add(Object)

get(idx)

set(idx, Object)

remove(Object)

 

✔ 조회

contains(Object)

indexOf(Object)

lastIndexOf(Object)

 

✔ 정렬, 서브리스트

sort(Comparator)

subList(idx start, idx end)

 


구현체 ArrayList

 

Collection, List 메서드를 구현

배열을 이용해서 구현했기 때문에 위치 삽입, 삭제시 시간이 소모 된다.

대신 idx를 이용한 조회는 O(1)

 

ensureCapacity(N)

trimToSize()

 

add(idx, Object)

 

 

 


구현체 LinkedList

 

Collection, List 메서드를 구현

양쪽 노드를 참조하는 참조값으로 구현했기 때문에 위치를 알고 있다면 삽입, 삭제시 빠르다.

대신 idx를 이용한 조회는 O(n)

 

Queue의 구현체로 이용됨

isEmpty()

 

peek()

peekFirst()

peekLast()

 

offer(Object)

offerFirst(Object)

offerLast(Object)

 

poll()

pollFirst()

pollLast()

 

 

 

 

 

 



 

인터페이스 Set <- (HashSet, TreeSet)

 

✔ 요소

add(Object)

remove(Object)

 

✔ 조회

contains(Object)

 


구현체 HashSet

 

중복을 판단하기 위해 equals(), hashCode()를 호출한다.

 

 

 


구현체 TreeSet

 

레드 - 블랙트리로 구현되어 있다.

정렬된 위치에 Object를 저장한다. 정렬되어 있기 때문에 조회, 범위 조회에서 이점을 갖는다.

정렬을 위해 Comparator를 생성자에 부여하거나, Object가 Comparable을 구현하고 있어야 한다.

 

 

✔ 단일 조회

first()

last()

 

higher(Object)

ceiling(Object) - Object 포함 검색

floor(Object) - Object 포함 검색

lower(Object)

 

✔ 범위 조회

headSet(Object) - Object가 head(가장 큰 값)

headSet(Object, boolean) - Object를 포함할지 boolean으로 결정

 

tailSet(Object) - Object가 tail(가장 작은 값)

tailSet(Object, boolean) - Object를 포함할지 boolean으로 결정

 

subSet(Object , Object)

subSet(Object, boolean, Object, boolean) - Object를 포함할지 boolean으로 결정

 

 

 

 

 

 

 

 

 



인터페이스 Map

 

전체

clear()

isEmpty()

size()

 

요소

get(key)

put(key, value)

remove(key)

 

✔ 조회

containsKey(key)

containsValue(value)

 

✔ 변환

keySet()

values()

entrySet()

 

 

인터페이스 Map.Entry

 

getKey()

getValue()

setValue(value)

 


구현체 HashMap

 

getOrDefault(key, value) - 키가 있다면 value반환, 없다면 매개변수 value로 생성, 반환

 

 


구현체 TreeMap

 

하나를 찾을 경우 반환은 Entry, Key (메서드 접미사로 지정)

범위로 찾을 경우 반환은 Map

정렬을 위해 Comparator를 생성자에 부여하거나, Object가 Comparable을 구현하고 있어야 한다.

 

 

 

✔ 조회 - Entry, Key

 

firstEntry(key)

firstKey(key)

lastEntry(key)

lastKey(key)

 


 

키를 포함하지 않고 검색

higherEntry(key)

higherKey(key)

 

키를 포함하여 검색

ceilingEntry(key)

ceilingKey(key)

 

키를 포함하여 검색

floorEntry(key)

floorKey(key)

 

키를 포함하지 않고 검색

lowerEntry(key)

lowerKey(key)

 

 

✔ 범위 조회 - Map

 

headMap(key)

headMap(key, boolean)

 

tailMap(key)

tailMap(key, boolean)

 

subMap(key, key)

subMap(key, boolean, key, boolean)

반응형
반응형

본 글은 책 자바의 정석을 ref 하여 요약한 글입니다.


 

자바의 날짜와 시간 클래스 변화 과정

Date -> Calendar -> time패키지

* time패키지를 사용하는 것이 좋지만 Calendar를 오랫동안 사용했기 때문에 하위 호환성을 위해 알아두면 좋다.

 


Date

특정 시점의 날짜 정보를 저장하는 역할만 한다.

 

Calendar

시스템의 국가와 지역 설정을 확인하여 현재 날짜와 시간를 사용

getInstance로 객체를 가져온다. 

 

get(Calendar.MONTH)를 이용하여 날짜, 시간 등을 사용할 수 있다. 

* MONTH의 경우 1~12가 아닌 0~11로 되어있다.

 

set(년, 월, 일, 시간, 분, 초)를 이용하여 시간을 지정할 수 있다.

* 년이 맨 앞 기준으로 오버 로딩이 돼있으므로 맞춰서 사용

* 연도 없이 시, 분, 초 등을 사용할 경우 set(Calendar.HOUR, 3)을 이용해서 따로 지정해야 함

 

두 날짜의 차이를 구할 때는 getTimeInMillis()를 이용해서 구한다. ms단위로 반환하기 때문에

1000을 나눈 후 초단위로 사용하면 된다.

 

add(Calendar.MONTH, -10)를 이용하여 이전 시간, 이후 시간을 구해줄 수 있다.

* add()는 다른 속성의 날짜, 시간을 계산하지만, roll() 메서드는 다른 속성에 영향을 주지 않는다.

 


 

자바time패키지

 

LocalTime - 시간 클래스

LocalDate - 날짜 클래스

LocalDateTime - 날짜 시간 클래스

ZonedDateTime - 특정 타임존의 날짜 시간 클래스 (UTC, ASIA/Seoul..)

Instant - 특정 시점의 타임스탬프 클래스 (차이를 비교, 순서를 비교 하는데 유리)

 

시간 지정

now() - 현재 시간

of() - 인수로 지정

parse() - 문자열을 시간으로 지정

 

시간 가져오기

get...() - 지정 시간속성 가져오기

 

시간 조작

with...() - 특정 시간 변경

plus...() - 특정 시간 더하기

minus...() - 특정 시간 빼기

* 변경 후 대입 필요, 항상 새로운 객체를 반환하므로 메서드 체이닝이 가능하다.

 

시간 비교

isAfter() - 이후 날짜 인지 비교

isBefore() - 이전 날짜 인지 비교

isEqual() - 동일 날짜 인지 비교

 

LocalDate, LocalTime < - > LocalDateTime

LocalDate, LocalTime -> LocalDateTime 

* of(LocalDate, LocalTime)

LocalDate, LocalTime <- LocalDateTime

* toLocalDate()

* toLocalTime()

 

 

Period, Duration,ChronoUnit

Period - 년, 달, 일

Duration - 시, 분, 초, 나노초

ChronoUnit - 전체시간을 기준으로 차이를 리턴

 

between()을 사용하여 두 시간을 비교한다.

반환 시간은 get...()으로 확인한다.

 


 

형식화 클래스

 

DecimalFormat

✔ 일정한 형식에 맞게 표현할 수 있는 방법을 객체지향적으로 표준화

new DecimalFormat("패턴")

format(입력)

✔ 포맷을 되돌리는 것도 가능하다.

parse(패턴에 맞게 표기된 형태)

 

 

패턴

 

입력:12345.6789

 

✔ 0 - 값이 없을때도 0을 표기

0 -> 12345

0.0 -> 12345.6789

000000.00000 -> 012345.67890

 

 

✔ # - 값이 없을때는 표시안함

# -> 12345

#.# -> 12345.6789

######.##### -> 12345.6789

 

 

✔ E - 지수기호

#E0 -> .1E5 

* #과 E를 같이쓰면 소수점 첫째자리를 표기함.

#.#E0 -> 1.2E4

##.#E0 -> 1.2E4

* #.#과 E를 같이쓰면 정수는 한자리수만 표기함

 

0E0 -> 1E4

* 0과 E를 같이쓰면 소수점을 표기하지 않음.

0.0E0 -> 1.2E4

00.0E0 -> 12.3E3

* #과 다르게 0은 정수 자리수를 패턴에 맞게 맞춤

 

 

 

SimpleDateFormat

✔ 날짜를 출력할 때 사용한다. 사용방법이 간단하다.

new SimpleDateFormat("형식")

format(Date)

* Date 클래스를 인수로 받는다.

 

 

 

 

 

 

 

 

 

 

 

 

 


 

반응형
반응형

본 글은 책 자바의 정석을 ref 하여 요약한 글입니다.


 

컴파일 에러 - 컴파일할 때 발생하는 에러

런타임 에러 - 프로그램 실행 중 발생하는 에러

논리적 에러 - 논리적으로 발생한 에러

 

런타임 에러시 발생

에러 - 프로그램 중지를 막을 수 없다.

예외 - 예외로 프로그램이 중지될 수 있지만 미리 예방 코드를 작성해두었다면 중지되지 않는다.

코드를 통한 처리의 주된 관심사는 예외이다.

 

Exception 하위 (외부의 영향으로 발생하는 예외) ⁕⁕ checked 예외(예외 처리가 반드시 필요하다)

RuntimeException 하위 (프로그래머의 실수로 발생하는 예외) ⁕⁕ unchecked 예외(예외처리는 선택사항)

* checked보다 unchecked를 이용하는 것이 더 코드를 깔끔하게 만들 수 있으므로

* Exception보다 RuntimeException을 상속받고 unchecked를 사용하는 쪽으로 변화 중

 

try - catch

예외가 발생하면 예외에 해당되는 인스턴스가 생성

인스턴스로 catch블록의 타입을 이용하여 검사한다.

(발생한 예외 객체) instanceof (catch블록 타입)

 

finally

예외 발생여부와 관계없이 반드시 실행

 

try - with - resources

try(따로 close를 호출하지 않아도 try 블럭을 벗어나는 순간 close()호출 ){

    내부작업

}catch(Exception e){

}

 


 

예외 발생시키기

예외가 발생하면 예외 객체를 생성한다. 예외가 발생하지 않아도 프로그래머가 예외 객체를 직접 생성해줄 수 있다.

생성된 예외를 throw를 이용하여 예외를 발생시킬 수 있다.

 

메서드에 예외 선언(호출부에 예외 처리 전가)

메서드 선언부에 throws (메서드 내부에서 발생 가능성 있는 예외를 호출부에 알려주는 역할)

* checked 예외만 적어둔다.

내부에서 처리하지 않고, 호출부에서의 에러처리를 강요한다. 

 

사용자 정의 예외

Exception을 상속받아서 생성자에 msg

 

예외 되던지기

예외를 처리해준 후 catch문에서 다시 throw 한다.

 

연결된 예외

예외를 생성한 이후 initCause 메서드에 원인 예외를 등록한다.

- 여러가지 예외를 하나로 묶어서 처리해줄 수 있다. (사용부에서 하나의 예외만 처리해주면 되니 간편해짐)

- checked 예외를 unchecked로 만들 수 있다.

** 예외가 발생하면 원인 예외도 log를 볼 수 있다.

 

 


java.lang 패키지

import 없이 사용, 기본이 되는 클래스들을 포함(Object, System, String, Math ..)

 

Object클래스

equals - 오버라이딩하지 않으면 참조값 비교, 오버라이딩 후 프로그래머가 원하는 값으로 비교

hashCode - 객체 자신의 hashCode반환, equals를 오버라이딩하면 hashCode도 해야한다. (HashSet, HashMap에서 이용한다.)

toString - 인스턴스 정보의 문자열

clone - 단순히 인스턴스 값을 복사. 인스턴스가 참조값이라면 참조값도 복사하기때문에 원본에 영향

getClass - 클래스 객체를 반환. 객체의 모든 정보를 담고 있다. 

* Reflection

* 클래스 객체를 이용하면 객체 생성, 메소드 호출 등이 가능하다. 클래스당 1개만 존재

 

String클래스

변경 불가능. +연산자를 이용해서 결합하는 경우 변경되는 것이 아니라 새로 생성하는 것. 메모리에 악영향

문자가 이미 저장되어있다면 재사용

(Heap - String Constant Pool)

* constant pool - 클래스파일이 클래스 로더에 의해 메모리에 올라갈 때 문자열 리터럴들이 constant pool에 올라간다.

equals를 이용하여 비교해야한다.

 

StringBuffer, StringBuilder

내부적으로 버퍼를 갖고 크기를 변경한다.

변경할 땐 배열과 마찬가지로 버퍼를 키운 후 배열에 문자를 복사한다.

equals가 오버라이딩 되어있지 않다.

StringBuffer는 쓰레드 환경에서 안전하다.

 

Math클래스

abs - 절대값을 반환

ceil - 올림하여 반환

floor - 버림하고 반환

max, min - 두값을 비교 

round - 소수점 첫째자리를 반올림한다.

 

wrapper 클래스

기본형을 객체로 다룰 때 사용한다.

전부 equals가 값의 비교로 오버라이딩 되있다.

* 내부적으로 객체를 사용하는 컬렉션프레임워크를 사용하면 자동으로 객체로 오토박싱

* 기본형 타입에 대입하면 자동으로 언박싱

 

 


 

java.util.패키지

유용한 클래스들의 모음(컬렉션 프레임워크, Objects, Random, regex, Scanner, StringTokenizer ...)

대부분의 메서드가 static

 

Objects

isnull(Object) 널 체크

hash(values...) 해시코드를 만든 후 반환

 

regex

정규표현식 - 패턴을 지정하고 같은 패턴을 찾는다.

 

Scanner

nextLine 외에도 nextInt, nextLong으로 입력을 받을 수 있어서 추가적인 작업이 덜 필요하다.

 

StringTokenizer

문자열을 자르는데 사용한다. 구분자를 지정할 수 있고, 구분자를 버리거나 사용할 수 있다.

 

BigInteger

값의 표현을 기본형보다 많이 할 수 있다.

add, subtract, multiply, divide, remainder

 

BigDecimal

정확한 실수형을 다룰 때 사용한다. 생성자는 0.1보다는 "0.1" 로 표현하는것이 오차가 발생하지 않는다.

 

 

 


 

 

 

 

 

 

반응형
반응형

본 글은 책 자바의 정석을 ref 하여 요약한 글입니다.


 

책의 내용은 아니지만 가장 먼저 절차적 프로그래밍과 객체지향 프로그래밍의 차이를 비교하고자 한다.

절차적 프로그래밍의 경우 공유 데이터 하나를 여러 함수를 통해서 조작하게 된다.

객체지향 프로그래밍에서는 객체는 자신의 데이터(상태)를 갖고 있고 이를 메서드를 통해 다른 객체와 상호작용한다.

데이터를 어떻게 다루냐에 있어서 차이가 있다.

 

절차적 프로그래밍 - 데이터, 함수가 분리

객체지향 프로그래밍 - 데이터, 함수가 결합

 


 

클래스와 객체

클래스 - 설계도, 데이터와 함수의 결합

객체 - 설계도에 따라 heap 영역에 인스턴스가 생성된 상태

* 자신을 참조하는 참조 변수가 없는 경우 인스턴스는 garbage collector에 의해 메모리에서 제거된다.

 

구성요소

속성 - 객체의 상태 값

기능 - 메서드

 

변수

클래스 변수 - 클래스가 메모리에 올라갈 때 생성

인스턴스 변수 - 인스턴스가 생성되면 생성

지역 변수 - 메서드가 호출되면 생성되었다가 메서드가 종료되면 소멸

 

메서드 

중복된 코드를 재사용하며 구조화

인자로 주거나 결괏값을 받을 때 자동 형 변환이 되는 type으로 지정, 안된다면 형 변환 후 넘긴다.

 

JVM 메모리 구조

메서드 영역 - 클래스 변수, 클래스 정보

힙 영역 - 생성된 인스턴스 

스택 영역 - 메서드(stack frame) 스택에 생성되고 처리 후 비운다.

 

기본형 매개변수와 참조형 매개변수

자바는 call by reference가 없다. 전부 call by value이며, 참조형 매개변수는 메모리의 주소가 아닌 객체 참조값을 넘긴다.

 

클래스(static) 메서드

인스턴스를 생성하지 않아도 사용 가능

클래스 메서드에는 인스턴스 변수를 사용할 수 없다. (클래스 메서드가 먼저 메모리에 올라감)

 

오버 로딩

같은 이름의 메서드명으로 인자의 type, 개수를 다르게 하여 여러 개의 메서드를 정의(리턴 타입은 영향 없다)

 

오버 라이딩

부모에게 상속받은 메서드를 재정의하여 사용한다.

이름, 매개변수, 리턴 타입이 같아야 한다.

 

생성자

객체의 인스턴스 변수를 초기화한다.

클래스의 이름과 같아야 한다.

기본 생성자는 컴파일러가 추가한다. 생성자를 하나라도 정의했다면 개발자가 기본 생성자를 작성해주어야 한다.

this() - 생성자 내부에서 다른 생성자를 호출한다. 가장 첫 줄에 작성한다.

 


 

상속

부모의 생성자, 초기화 블록을 제외한 멤버(속성, 기능)를 물려받는다.

** private로 선언된 멤버는 상속되지 않는다.  (super로 접근하여 사용한다.)

** 부모 자식 클래스가 다른 패키지라면 default로 선언된 멤버는 상속되지 않는다.

** 자식 클래스 내부 - super.getter, super.setter || 외부 - getter, setter 

자바에서는 단일 상속만을 허용한다.

 

클래스 간의 관계

포함관계 (has) - 상속하여 사용하지 않고, 속성에 다른 객체를 포함하여 해당 객체의 멤버를 사용한다.

상속관계 (is) - 상속관계라고 하지만 소속 관계라고 이해하고 있다.

 

super

부모, 자식과의 변수명이 같을 때 super, this를 이용해서 구분해줄 수 있다.

변수뿐만 아니라 오버 라이딩한 메서드의 구분도 가능하다.

super() - 부모 생성자를 호출하여 상속받은 부모 속성을 초기화할 수 있다. this()와 마찬가지로 가장 첫 줄에 위치한다. 

 


 

패키지

클래스들의 묶음

클래스의 실제 이름은 패키지명을 포함

클래스 파일을 압축한 것이 jar

 

import

패키지가 다른 클래스를 사용할 때 패키 지명이 포함된 클래스를 작성하는 것이 불편해서 import를 이용한다.

import를 하게 되면 클래스명 만으로 사용 가능하다.

 

제어자

static - 클래스가 메서드 영역에 로드될 때 같이 로드된다. (속성, 메서드)

final - 변경될 수 없다는 의미 (클래스, 메서드, 변수)

abstract - 미완성의 의미 (클래스, 메서드)

 

접근제어자

public - 제한 없음

protected - 다른 패키지여도 상속한다면 사용이 가능하다. (클래스가 public 이어야 상속 후 protected 멤버 사용 가능)

default - 같은 패키지

private - 같은 클래스

 


 

다형성

하나의 참조타입로 여러 타입의 인스턴스를 사용 (클래스, 추상 클래스, 인터페이스)

업 캐스팅시 자식의 멤버는 사용할 수 없다. 오버 라이딩된 메서드는 사용 가능

참조 타입이 바뀌더라도 인스턴스는 바뀌지 않는다. (멤버 사용 범위가 달라질 뿐)

instanceof - 인스턴스를 이용해서 참조 타입으로 변환할 수 있는지 확인한다.

ex) 참조 변수(인스턴스) instanceof 참조 타입

 

다형성의 주의점

** 메서드를 오버 라이딩했다면 항상 자손의 오버 라이딩 메서드를 사용한다.

** 부모 메서드의 접근 제한자보다 오버 라이딩한 자식 메서드를 더 강한 접근 제한자를 설정할 수 없다.

** 오버 라이딩 메서드 내부에서 자신의 속성을 사용할 수 있다. (this)

** 같은 이름의 속성은 참조 타입에 의존한다.

 


 

추상 클래스

클래스들의 공통부분을 추상화해놓는다.

추상 클래스는 추상 메서드를 갖는다.

생성자를 가질 수 있다.

인스턴스를 생성할 수 없다.

* 동작이 동일한 부분은 일반 메서드로 구현해놓는다.

* 공통 부분이지만 인스턴스에 따라 달라지는 메서드는 추상 메서드로 선언한다.

 

인터페이스

추상 메서드와 상수만을 가질 수 있다. (static, default 메서드를 가질 수 있지만 복잡성을 줄이기 위해 일단 이렇게 이해)

 


 

** 추상 클래스와 인터페이스의 차이

추상 클래스는 클래스의 상속(소속) 관점 - (공통 기능을 구현해줄 수 있다.)

인터페이스는 단순히 기능 관점 - (필요 기능을 명시해줄 수 있다.)

 

추상 클래스는 재사용성의 관점에서 유용

인터페이스는 교체의 관점 유용

 

(추상클래스) 동물 - 사자, 독수리  소속 관점

(인터페이스) 독수리와 벌의 flyable  기능 관점(소속이 달라도 기능이 같다.)

 

추상 클래스는 상태 변수 필드를 갖고 있다.

인터페이스는 상태 값을 갖지 못하고 상수만 갖고 있다.

 

 

** 인터페이스의 이해

사용부(클라이언트 코드)에서는 내부를 알 필요가 없다. 메서드만 알면 된다.

인스턴스가 변경되더라도 메서드명은 같다. 유지보수가 편하다.

 


 

내부 클래스

가장 먼저 외부 클래스는 프로그램이 실행되면 메서드 영역에 올라간다는 점을 알면 이해하기 편하다.

* static이 인스턴스보다 먼저 로드된다.

 

인스턴스 클래스 - 외부 클래스 인스턴스가 생성되어야 사용 가능, 외부 클래스의 private 멤버도 접근 가능

스태틱 클래스 - 외부 클래스 인스턴스가 생성되지 않아도 사용 가능, 인스턴스 멤버에 접근 불가(static은 먼저 로드되기 때문)

지역 클래스 - 메서드가 종료되면 메서드 내부 지역변수지역 클래스가 알 수 없으므로 상수만 사용 가능하다. (지역 변수는 소멸될 가능성)

 

익명 클래스

하나의 객체만을 생성하는 일회용 클래스, 생성된 객체는 계속 사용할 수 있다. 설계도가 1회성

클래스를 상속받거나 인터페이스를 구현하여 사용한다.

람다식에 유용하게 사용된다.

 

 


 

 

 

 

 

 

 

 

 

반응형
반응형

본 글은 책 자바의 정석을 ref 하여 요약한 내용입니다.


연산자와 피연산자

연산자에 따라 피연산자의 필요 개수가 달라진다.

* 부호 연산자인 - 경우 피연산자가 1개 필요

* 뺄셈 연산자인 - 경우 피연산자가 2개 필요

 

연산자의 종류

산술 - 사칙연산과 나머지 연산자

비교 - 크기 비교 연산자 

논리 - true, false 결과가 나오는 연산자

대입 - 대입 연산자

기타 - 삼항 연산자

 

연산자 우선순위

우선순위는 산술, 비교, 논리, 대입 순서로 연산된다.

우선순위는 외우는 것 보다는 자연스럽게 생각해도 되며, 필요하다면 괄호를 사용한다.

단항 연산자는 우선순위가 가장 높다는 것을 기억하고 있으면 좋다.

단항, 대입을 제외한 나머지는 연산 순서가 왼쪽에서 오른쪽

 

산술 변환

이항 연산자에서 두 타입이 다르면 타입을 큰 타입으로 일치시킨다.

단, short + byte 같은 정수 연산의 경우 int 연산이 JVM 스택 연산에 가장 효율적이므로 int로 변환된다.

 


 

단항 연산자

전위형(++i), 후위형(i++) 이 있으며, 후위형은 세미콜론; 을 기준으로 실행이 된 이후에 증가시킨다고 생각

부호 표시 연산자

 

산술 연산자

기본적인 사칙연산 순서를 따르며, 나누기를 할 때 0으로 나누는 것을 주의

계산 후 오버플로우가 예상되면 미리 한쪽을 큰 타입으로 형 변환 후 연산한다.

 

비교 연산자

이항 연산자이므로 타입이 맞지 않을 경우 큰 타입으로 변환시킨다.

등가 연산자는 참조 변수를 비교할 경우 객체의 참조값을 비교한다.

 

논리 연산자

&& 가 || 보다 우선순위가 높다.

논리 연산자는 효율적인 연산을 한다. && 라면 좌측만 보고도 false라면 false로 취급한다.

 

대입 연산자

lvalue는 변수처럼 값을 변경할 수 있는 것이어야 한다. rvalue는 변수, 식, 상수 전부 가능하다.

복합 대입 연산자가 가능하다 *=, -= ...

 

 


 

if

조건식의 결과는 반드시 true, false 여야 한다.

* if문을 종료조건으로 사용하면 중첩 블록을 유지하지 않아도 되기 때문에 코드를 깔끔하게 짤 수 있다.

 

switch

조건식, case, break

case에 해당되지 않으면 default

break가 없으면 아래 case도 실행

* case - 변수, 실수 사용 불가능

 

for

초기화, 조건식, 증감식

 

향상된 for문

(타입 변수 : 배열 or 컬렉션)

 

while

조건식이 true이면 계속 실행

* 조건식을 생략할 수 없다.

 

do while

do 블럭을 무조건 1번 실행, 이후 조건문을 확인

 

break

자신이 포함된 가까운 반복문을 멈춘다

 

continue

아래 코드는 실행하지 않은 채 다음 반복으로 진행한다.

 

이름있는 반복문

loop1: for...

* break loop1, continue loop1 

 

 


 

배열

같은 타입의 묶음

저장공간이 연속적으로 배치

index는 0부터 length-1 까지

배열의 크기를 넘어서면 ArrayIndexOutOfBoundException 예외 발생

한번 지정된 배열의 크기는 변경할 수 없다. 새로운 배열을 생성 후 값을 복사해줘야한다.

참조형 배열일 경우 각 요소에 저장되는 값은 참조값이다.

 

다차원 배열

new int[row][col]

row는 수직, col은 수평으로 생각하면 이해하기 쉽다.

각 row는 col[배열]의 참조값을 갖고 있다.

 

 


 

 

 

반응형

+ Recent posts