반응형

 

 

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[배열]의 참조값을 갖고 있다.

 

 


 

 

 

반응형
반응형

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


 

✔ 자바는 객체지향 언어이다. (상속, 추상화, 캡슐화, 다형성)

✔ 풍부한 JAVA API 라이브러리를 제공한다.

✔ 자바 app은 JVM과 상호작용한다. 

 

JVM

소프트웨어로 구현된 하드웨어

자바가 실행되기 위해선 JVM이 필수적

운영체제에 종속적이다. (Write once, Run everywhere)

 

JRE(java runtime environment)

JVM + 자바 프로그램을 실행하는 도구들

* JRE가 설치되어 있다면 어떤 환경에서든지 자바 소스 파일을 실행할 수 있다.

* 개발이 필요없는 단계라면 JRE만으로 프로그램을 실행할 수 있다.

 

JDK(java devlopment kit)

JRE(java runtime environment) + JAVA API + 컴파일러.. (개발에 필요한 도구)

 

자바 프로그램 실행 과정

자바 app은 실행할 때 main 메서드를 시작점으로 한다.

Sample.java -> (javac.exe)(컴파일러) -> Sample.class -> (java.exe)(인터프리터) -> 프로그램 실행

 

 


 

변수

메모리 공간에 이름을 붙여주는 것

변수 타입에 맞게 메모리를 확보

 

변수의 초기화

이전에 사용했던 garbage value가 남아 있을 수 있어서 사용하기 이전에 초기화해주는 것이 바람직

* 전역 변수는 초기화 생략 가능

* 지역 변수는 반드시 초기화

 

변수의 종류

기본형 - boolean, byte, short, int, long, float, double, char

참조형 - 배열, 열거, 클래스, 인터페이스

* boolean을 제외한 나머지 7개의 기본형 타입은 서로 변환이 가능

* char 은 유니코드 체계를 위해 2byte (유니코드 정수 값이 저장된다)

* char과 shrot는 같은 2byte이지만 범위가 다르다.

* JVM 스택 연산에 4byte를 사용하므로 byte, short보다 int 형이 유리하다.

* 정수형 타입 크기를 벗어나면 overflow가 발생한다.

* 실수형 타입 float - 정밀도 7자리, double - 15자리

 

String 결합

한쪽이 String 이고, 연산자가 + 로 연결되어있다면 다른 한쪽도 String으로 만든 후 결합

 

printf

%5d  -  5칸 오른쪽정렬

%-5d  -  5칸 왼쪽 정렬

%14.10f  -  14칸. 소수점 이하 10칸

 

word

cpu가 한 번에 처리할 수 있는 데이터의 크기 32bit, 64bit

 

2진법, 8진법, 16진법

2진법 - 컴퓨터는 전기가 흐르면 1 흐르지 않으면 0

2진법을 이용하여 10진법, 8진법, 16진법 변환

 

실수의 진법 변환

소수부에 2를 계속 곱하여 0이 될 때까지 반복, 결과의 정수부 나열

 

2의 보수

N의 보수: 자릿수를 한자리 증가시키는, 더해서 0으로 만드는 수

ex) 숫자 73의 10의 보수 = 37 (73과 37은 보수관계)

 

✔ 보수에서는 자릿수가 중요하다.

만약 10진수가 2자리를 표현한다면 73과 37은 보수관계가 맞다. (73+37 = 100) "1"00 표현 불가

하지만 10진수가 3자리를 표현한다면 73과 937이 보수관계이다. (73+937 = 1000) "1"000 표현 불가

 

2의 보수에서는 MSB가 0이면 양수, 1이면 음수로 구분한다.

4자리 이진수에서는 0011의 2의 보수는 1101 (0011과 1101은 보수관계)

4자리 2의 보수 체계에서 1101은 십진수 -3의 역할을 한다.

십진수로 3인 0011의 반대 값은 -3인 1101

 

-3일 때 3의 보수(1101)를 구하고 더하면 -3의 효과를 낸다.

* 2의 보수 구하기 = 1의 보수 +1

 

오버플로우

4 자릿수의 bit체계에서 0111과 0001을 더하면 1000이 된다. MSB가 1이므로 음수다. 1000은 -8이다.

7+1의 결과는 8인데, 결과가 -8이 나왔다. 이를 표현 숫자 범위를 벗어난 오버플로우라고 한다.

 

인코딩과 디코딩

인코딩 - 문자를 숫자(지정된 바이트)로 

디코딩 - 숫자(지정된  바이트)를 문자로

디코딩을 하기 위해선 어떻게 인코딩했는지 알아야 한다.

 

UTF-8 UTF-16

UTF-8 -> 가변크기 1~4 byte 표현 (웹문서에서 유리, 아스키 코드와 호환됨, 대부분 프로그램의 Default)

* 110XXXXX 10XXXXXX 10XXXXXX

* 한 문자를 표현할 때 3Byte를 써야하는 경우 -> 110을 시작으로하고, 나머지 Byte는 10으로 시작.

* 110으로 문자 시작을 알림

UTF-16 -> 고정크기 2byte 표현 (자바에서 사용)

 

형 변환

기본형과 참조형 간의 형 변환은 불가능

더 큰 타입으로 대입될 때는 묵시적 형 변환, 작은 타입으로 대입될 때는 값이 손실되며 명시적 형 변환

 

정수형 -> 실수형 : 정밀도 제한으로 오차 발생 

실수형 -> 정수형 : 정수부만 저장

* byte < short < int < long < float < double

 

 


 

 

 

 

반응형
반응형

 

intellij는 eclipse에서의 workspace가 없다.

workspace는 관련 없는 프로젝트들도 하나의 eclipse창만 띄우고 전부 볼 수 있었다.

 

intellij에서는 이 방식을 권장하지 않는다.

기본적으로 하나의 프로젝트에는 하나의 모듈을 권장한다.

 

연관있는 모듈일때만 프로젝트를 생성해서 멀티모듈로 구성한다.

 

 

 


 

 

 

New Project, New Module 화면

차이를 보면 New Project가 Empty Project를 제공해준다는 점만 빼면 똑같다.

 

 

 

 

 

 


 

 

 

멀티 모듈 설정

프로젝트를 gradle 프로젝트로 생성

각 모듈은 gradle 모듈로 생성

 

DSAL /

     DSAL_Algorithm

     DSAL_DataStructure

 

 

settings.gradle

rootProject.name = 'DSAL'
include 'DSAL_Algorithm'
include 'DSAL_DataStructure'

 

 

 

build.gradle

 

buildscript{ }: gradle 빌드전에 실행

allproject{ }: 모든 모듈에 적용

subproject{ }: 서브 모듈에만 적용

 

 

buildscript {
    apply plugin: 'java'

    ext{

    }

    repositories {
        mavenCentral()
    }

    dependencies {

    }

}

allprojects {
    apply plugin: 'java'

    group 'org.example'
    version '1.0-SNAPSHOT'
}

subprojects {
    repositories {
        mavenCentral()
    }

    dependencies {
        // 서브 모듈에 모두 추가할 라이브러리 설정

        testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
        testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
    }

    test {
        useJUnitPlatform()
    }
}

// 각 모듈별 라이브러리 설정
project(':DSAL_Algorithm'){
    dependencies {
        compileOnly 'org.projectlombok:lombok:1.18.12'
        annotationProcessor 'org.projectlombok:lombok:1.18.12'
    }
}

project(':DSAL_DataStructure'){
    dependencies {
    }
}

 

DSAL_Algorithm에 lombok은 테스트용도로 넣어둠

 

 


 

 

서브 모듈 build.gradle

dependencies {
    compileOnly 'org.projectlombok:lombok:1.18.12'
    annotationProcessor 'org.projectlombok:lombok:1.18.12'
}

 

프로젝트 build.gradle의 project(':subModule'){ } 로 사용하지 않고,

서브 모듈에 존재하는 build.gradle에 dependencies{ } 에 추가해도 동작한다.

 

 

 

프로젝트 build.gradle 한곳에서 관리해주는 것이 편리하니 project(':subModule'){} 를 사용하자.

 

 

 


 

 

참고

 

 

https://jojoldu.tistory.com/334

 

Eclipse의 Workspace와 IntelliJ의 Project

최근 인프런에 강의 영상을 올리고 여러 질문을 받았습니다. 그 중에서 자주 접하는 질문이 바로 Eclipse의 Workspace가 IntelliJ의 Project가 맞는건지에 대한 질문이였습니다. (질문) 그래서 이 부분에

jojoldu.tistory.com

 

반응형

' > intellij' 카테고리의 다른 글

[intellij] gradle를 이용해서 local jar 생성, 추가  (0) 2022.07.27
반응형

 

intellij

하나의 project안에서 여러개의 module로 프로젝트를 구성

 

 


 

gradle을 이용하여 jar파일 생성, 추가

 

 

jar 만드는 방법

 

gradle -> jar

build/libs에 jar파일이 만들어진다.

 


 

jar 파일 사용

 

 

다른방법


dependencies {
    implementation fileTree('libs')
}

 

반응형

' > intellij' 카테고리의 다른 글

intellij 구조 (프로젝트, 모듈, 멀티 모듈)  (0) 2022.07.27
반응형

 

Git 기본 사용법 및 명령어

 


 

git을 다운로드하여 프로그램을 설치한 후 $git --version 명령어로 git이 제대로 데스크톱에 설치되었나 확인한다.

git을 이용할 폴더에 들어가서 폴더 배경에서 오른쪽 클릭 - git bash here을 누르면 git이 사용 가능하다.

$git init하게 되면서 (.git)폴더가 생성된다.

 


Git의 특징

 

분산 버전관리 시스템

중앙 저장소뿐만 아니라 로컬 저장소에서도 history를 갖고 있다.

 

Git의 원리

변경이 일어날 때 마다 기존 파일들은 실제로 복사해서 갖고 있는 것이 아니라 기존 내역들을 참조하고 있다. , 해시코드 값을 참조

 

git init: 작업 영역 생성

git add: [새로 생성된 파일]을 등록한다. 기존 내역은 [기존 파일 참조(해시값)]

git commit: [새로 생성된 파일] + [기존 파일 참조] = 해시 코드 생성

 

 


기본 명령어

 

git 명령어 --help 도움말 보기

git log -> q 나가기

touch sample.txt 테스트할 때 빈 파일 만들기

 

 

$git config --global user.email 사용하는 이메일 commit 시 작성자로 등록됨

$git config --global user.name 사용하는 이름

github사이트에서 이용하는 이메일과 이름 [내 정보]를 등록하는 명령어이다.

 

$git init git 저장소 생성, 현재 폴더를 버전관리하겠다고 선언

$git status 폴더 안 파일들의 상태를 확인 [새로 만든 파일(untracked), 변경된 파일(modified)] 

$git add commit을 수행할 파일을 staging area에 추가한다. [새로 만든 파일(untracked), 변경된 파일(modified)]  둘다 add를 해줘야한다.

이전에 add로 추적을 시켰다 하더라도, 수정시에 새로 add를 해줘야한다.

add는 단순히 추적이 아닌 staging area에 올리는 것이다.

2가지 기능이 있다고 생각

(1) 새로운 파일을 staging area에 올린다.

(2) 변경된 파일을 staging area에 올린다.

 

$git commit -m "설명" 커밋할 때 구체적인 설명을 같이 입력한다. commit 명령어는 기록을 남긴다.

$git commit -am "설명" 모든 file을 자동으로 add하며 커밋도 진행한다. (단, untracked file은 커밋하지 않는다.)

staging area 에 올라온 file들을 기록시킨다.

 

$git log 커밋 기록을 보는 명령어이다.

$git diff 커밋번호..커밋번호 커밋간의 차이를 본다.

log화면에서 q를 누르면 나간다.

 

$git reset 커밋번호 커밋번호에 해당되는 버전으로 돌린다.

로컬 저장소일때만 사용 추천

 


gitignore 

 

gitignore 파일안에 git이 추적하지 않을 파일명을 등록하여 추적되지않게 할 수 있다.

"git add ." 해도 staging area에 등록되지 않는다.

 

$vim .gitignore gitignore 을 만든다.

*.파일형식 파일 유형 전체를 추적하지 않을경우 

 

주의점. 한번 추적된 파일은 gitignore에 등록해도 추적을 피할 수 없다. 

$git rm --cached 파일명 해당 명령어로 git cash를 지워주면 gitignore가 정상적으로 가능하다.

 

 


Git Branch

 

브랜치를 만드는 경우

  • 테스트 기능을 만들어야하고, 결과적으로 원격저장소에는 올리지 않는 경우
  • 기능이 사용될 가능성이 적은 경우
  • 메인 프로젝트는 유지하며 커스텀 프로젝트를 만들 경우

 

이전 시점으로 돌아가서 브랜치를 만들지 않고  commit진행하고, 다른 브랜치로 이동하려고하면 불가능하다.

작업한 커밋에 대한 브랜치를 만들어줘야 다른 브랜치로 이동할 수 있다.

 

$git branch 현재 branch정보들을 볼 수 있다. (현재 check인 branch는 * 표시)

$git branch 브랜치 새로운 branch를 만든다.

$git branch -d 브랜치 branch를 삭제한다.

$git branch -D 브랜치 branch를 강제 삭제한다.

$git checkout 브랜치 현재 사용중인 branch를 checkout하고, 브랜치명 branch로 시점을 이동한다.

$git checkout -b 브랜치 브랜치를 만들면서 체크아웃도 진행

$git checkout 커밋 해시값 N자리

checkout 명령어는 HEAD 이동 명령어다. 커밋 번호가 존재하며 커밋번호 앞 N자리를 이용하여 시점을 이동한다.

 

$git log --branches --decorate --graph log들을 시각적으로 표현해서 보여준다.

$git diff 브랜치1..브랜치2 branch들 간의 차이를 본다. (윗 라인이 브랜치1, 아랫 라인이 브랜치2 / 브랜치2가 기준)

 

$git merge 브랜치2

현재 시점이 브랜치1인 상태라 가정한다.

merge하면 브랜치1로 브랜치2의 커밋들을 가져온다.

충돌이 없었다면 브랜치2의 커밋 내용이 브랜치1에 전부 merge되어 브랜치2는 삭제가 가능하다.

* 브랜치를 합치는게 아니라 해당 브랜치가 갖고 있는 커밋들을 합치는 것이다.

 


 

fast-forward

 

새로운 브랜치로 nb에서 commit을 진행하고 master에서 nb 커밋들을 이용하고자 할 때

(master는 commit진행을 하지않은 상황)

$git checkout master 

$git merge nb

master로 시점을 옮기고, nb를 merge하면 fast-forward가 진행된다.

 

 

 

 

 

3way-merge

 

 

 

[1 라인] 수정이 일어나지 않았으면 그대로 반영 (A A A) -> A

[2, 3 라인] 변경부분은 변경부분으로 반영 (H B B) -> H

[4 라인] 같은부분의 변경은 충돌을 직접 해결해줘야함 (H D T) -> 충돌 해결 필요

 

 

 

$git checkout master 

$git merge nb

master로 nb 커밋을 가져와서 merge완료함.

 

 

 

 

 

merge 충돌 해결

 

충돌이 일어나면 (브랜치|MERGING) 로 바뀐다

충돌이 일어난 파일을 수정해주고 commit을 해주면 된다.

 

 


 

 

$git stash 임시 저장을 만든다.

$git stash apply 임시 저장을 다시 불러와 적용한다.

 


원격 저장소 생성, fork, clone

 

로컬저장소 생성 후 원격 저장소(github) 생성

원격저장소 생성 - readme.md없이 만들어야 원격저장소 브랜치가 생성되지 않음

$git remote add origin 원격저장소주소 원격 저장소와 연결하며, origin이라는 명칭으로 사용하겠다.

$git push origin 브랜치명 브랜치 push

 

 

 

원격 저장소를 clone하여 가져오기

HTTPS 주소로 clone

$git clone HTTPS주소 [폴더명]

폴더명이 없다면 해당 폴더에, 있다면 추가로 폴더를 생성하고 그안에

 

원격 저장소에 대한 권한이 있다면 로컬 저장소 내역을 원격 저장소에 즉시 반영가능

브랜치 보호설정을 해놨다면 관리자의 PR허가필요

 

clone하면 기본적으로 master만 연동되고, 다른 원격 브랜치는 갖고 있기만 한다.

master가 아닌 브랜치는 따로 로컬에서 생성해 연결해주어야 한다.

 

 

원격 저장소를 fork하여 가져오기

fork 하게 되면 내 원격저장소에 프로젝트가 생성된다.

fork이후 clone을 통해 사용하면 된다.

 

fork한 프로젝트는 PR를 통해 기여할 수 있다.

 

Pull Request - 협력자가 원본 저장소의 관리자에게 merge를 요청하는 과정으로 협력자가 관리자에게 승인을 허가하도록 요청하는 것이다.

최종 merge는 원본 저장소의 관리자가 요청을 승인해야 merge 된다.

 

PR 방법

base: fork한 기존 프로젝트 / branch   <-----  head: fork한 내 저장소 프로젝트 / branch

 

브랜치를 새로 생성 후 commit 정리하고 PR요청

PR요청 전에  rebase dev 까지 해서 정리하고 PR. 바로 merge되도록.

요청하는쪽에서 정리하는 것이 바람직

PR이 허가되면 Main 브랜치에 merge된다.

 

 


원격 저장소 push & pull

 

$git ls-remote, git branch -r

원격저장소 branch를 보여준다.

 

 

Download

$git fetch --all
원격 저장소 모든 branch 다운로드

새로운 원격 branch가 있다면 알려준다.

 

$git fetch origin {원격브랜치}

원격 저장소 브랜치 하나만 다운로드

fetch한 branch로 checkout하고, 내용을 확인할 수 있다.

 

$ git merge {origin/원격브랜치}

다운로드한 브랜치와 merge한다.

 

$git pull origin {원격브랜치}

하나의 원격브랜치만 다운로드 & merge 하고자 할 때 사용한다.

기존 브랜치와 동기화를 해놨다면 merge된다.

* 주의: HEAD branch와 merge되므로 원하는 branch로 checkout한 후 진행해야 한다.

 

$git checkout {로컬브랜치} {origin/원격브랜치}

최초 동기화로 로컬 브랜치를 생성해서 원격 브랜치를 동기화

== git switch 원격브랜치

원격 저장소에 새로운 브랜치가 있을 때 로컬에도 새로운 브랜치를 만들어 동기화하여 사용하는 것이 정석

 


Upload

$git push origin {로컬브랜치 }

로컬 브랜치를 원격 저장소에 브랜치로 업로드

원격 저장소에 브랜치가 있다면 반영, 없다면 생성

 

$git push origin {로컬브랜치:원격브랜치}

브랜치이름이 다를 경우

 

$git push --all 

모든 브랜치를 원격 저장소에 올린다.

 

$git push origin --delete {원격브랜치}

원격 브랜치를 삭제한다.

 

$git push -f origin {브랜치}

로컬 브랜치에 맞게 원격 브랜치를 강제 수정할 때

 

 


 

 

 


 

 

리눅스 명령어

 

https://dora-guide.com/linux-commands/

 

리눅스 명령어 모음 BEST 50 초보자 및 전문가용 - 도라가이드

리눅스 명령어 모음 입니다. 오늘날 배울 수있는 가장 유용한 리눅스 명령어들이며, 리눅스 기본 명령어와 함께 정기적으로 사용할 50가지 최고의 Linux 명령어를 간략하게 요약하여 이 안내서를

dora-guide.com

 

 

 


 

반응형

+ Recent posts