Post

Bitcamp

컴파일

1
javac -d build/classes/java/main(목적폴더-컴파일한 파일을 둘 곳) src/main/java/com/eomcs/*.java(소스 위치)

-다른 클래스를 사용하는 소스파일을 컴파일 할때
목적 폴더 명령어와 소스 위치 명령어 사이에 -cp build/classes/java/main 를 넣어준다

실행

1
java -cp(classpath) build/classes/java/main(cp는 패키지가 있는 목적디렉토리까지만) com.eomcs.E1(class 파일 위치, 실행할 떄 반드시 패키지 명을 지정)

패키지명

com.* or org.* 등등 도메인 명이다. ex)com.facebook com.microsoft 등 개발자나 회사 간 이름 충돌 방지
역순으로 되어있는 이유는 상위에서 하위로 분류해 쉽게
다른 패키지에 있는 클래스 불러올시 패키지명 작성 필요 ex)com.eomcs.F1 v1;

패키지명 작성 관례

com.도메인.제품명.역할명 순으로 작성

패키지 멤버 클래스(패키지 클래스) - 패키지에 소속된 클래스

public 클래스

공개 클래스 소스파일을 찾기 쉽도록 하기 위해 반드시 소스파일명과 일치해야한다

main() 메소드

프로그램 entry point (입구)

classpath (cp)

.class파일의 위치를 알려주는 명령어

javadoc html 문서 만들기

1
javadoc -encoding UTF-8 -charset UTF-8 -d javadoc -sourcepath src/main/java/ com.eomcs.lang.ex02\

javadoc 디렉토리가 만들어지고 index.html 파일에 들아가면 열람가능
코드 위에 \

1
2
3
4
5
6
/**
 * 클래스에 대한 설명
 * @author eomjinyoung
 *
 */
public class Exam0200 {}

이런식으로 작성하면 해당 코드에 대한 설명으로 출력된다
javadoc 나오기 전 소스 코드를 바꾸면 문서도 수정해야하는데 개발자들이 귀찮아서 수정하지 않는 것이 현실 ->
javadoc으로 소스와 문서를 결합하고 문서 생성을 자동화해 해결

@Annotation 어노테이션 주석

  • 일반 주석과 다르게 컴파일과 실행할 때 영향, 다른 문서를 생성할 때 사용
  • 자바에서 사용될 때의 어노테이션은 코드 사이에 주석처럼 쓰여서 특별한 의미, 기능을 수행하도록 하는 기술이다.
    즉, 프로그램에게 추가적인 정보를 제공해주는 메타데이터(meta data: 데이터를 위한 데이터)라고 볼 수 있다.

    메타 데이터?

  • 데이터를 위한 속성정보이다. 데이터를 위한 데이터로서 하위 레벨 데이터를 설명 및 기술하는 데이터라고 보면 된다.
  • 도서관을 예시로 들어보자면 표제, 저자, 주제명, 분류기호 등이 포함되어 있는 목록이 메타데이터에 속한다.

어노테이션?

  • 프로그램 실행 관점에서 보면 프로그램이 처리할 메인 데이터가 아니라 실행과정에서 데이터를 어떻게 처리할 것인지 알려주는 서브 데이터라고 볼 수 있다.

어노테이션의 용도

  • 컴파일러에게 코드 작성 문법 에러를 체크하도록 정보를 제공

  • 소프트웨어 개발툴이 빌드나 배치 시 코드를 자동으로 생성할 수 있도록 정보 제공

  • 실행 시(런타임 시) 특정 기능을 실행하도록 정보를 제공

    어노테이션을 사용하는 순서

  • 어노테이션의 정의

  • 클래스에 어노테이션을 배치

  • 코드가 실행되는 중에 Reflection을 이용하여 추가 정보를 획득하여 기능 실시

참조) https://lala9663.tistory.com/99

gradle 프로젝트 생성방법

프로젝트 디렉토리 생성 후 해당 폴더에서 gradle init
application - java - groovy 선택 나머지는 디폴트
소스 패키지 com.eomcs
build.gradle 수정
-plugin 수정,자바 소스 옵션,프로젝트 이름 수정
gradle eclipse 명령어 실행 - 이클립스 파일 생성
import - general - existing~~ 로 임포트
plugin에서 application을 수정한 경우 application task를 지워준다 지우지 않으면 gradle eclipse 오류뜸

램에 숫자를 저장할 때는 이진수로 변환 후 저장 그때 사용하는 방식이 2의 보수를 사용

보수란 무엇인가? 

  • 컴퓨터는 1과 0으로 수를 표현한다. 
  • 컴퓨터는 오로지 덧셈만을 이용하여 연산을 처리한다. 
  • 이 과정에서 음수를 표현하거나, 음수 연산할 때 보수라는 개념을 사용한다. 
  • 이를 위해서 보수에는 여러가지 개념들과 기능이 있다. 같이 알아보자.  출처: https://devraphy.tistory.com/279 [개발자를 향하여:티스토리]

    2의 보수

    1의 보수의 문제를 해결하기 위해 나옴, 2진수로 음수를 나타내기 위해 사용
    1의 보수인 경우 2진법으로 변환 후 계산 했을 때 원하는 값보다 1이 작은 결과가 출력
    그래서 1번째 방법 - 미리 음수에 1을 더하는 방식으로 해결
    2번쨰 - 오른쪽에서부터 1을 찾고 첫번째로 찾은 1을 제외한 나머지를 반대 값으로 바꿈
    3번째 - *
    이 방법으로 1의 음수에는 존재하던 음수 0 값이 사라짐 , 음수 0이 사라짐으로 인해 -128까지 가능
    다양한 데이터들의 범위가 양수보다 음수가 한자리 더 큰 이유 (int, long 등)

참조) https://life-with-coding.tistory.com/298

비트 크기와 저장할 수 있는 값의 범위

8bit = -128 ~ 127
16bit = -32768 ~ 32767
32bit = -21억 ~ 21억
64bit = -약922경 ~ 922경
메모리 기본 단위 = 8bit(1byte)
크기 분류
8bit(1byte) = byte
16bit(2byte) = short
32bit(4byte) = int
64bit(1byte) = long
자바에서 int와 long 을 알아보는 방법은 정수 뒤에 L을 붙임

부동소수점(float)

소수점 아래 있는 수를 2진수로 변환하는 방법은 값에 2를 곱한 후 소숫 점 위에 값을 차레로 넣어준다.
ex) 0.375 의 경우
0.375 * 2 = 0.75 -> 0
0.75 * 2 = 1.5 -> 1
0.5 * 2 = 1.0 -> 1
그래서 0.375의 2진수 변환 값은 0.011 이 된다

부동소수점 표기법

3.14
=31.4 * 10의 -1 승 = 31.4E-1
=314 * 10의 -2 승 = 314E-2
=0.314 * 10의 1 승 = 0.314E1
=0.0314 * 10의 2 승 = 0.314E2

정규화 후 부동소수점을 32bit로 2진수로 표현

12.375를 이진수로 변환하면
1100.011 -정규화-> 1.100011*2의 3승
정규화란
소수점의 위치를 조정하여 가수부와 지수부로 분리
-왼쪽 1만 남기고 모두 소수점 아래로 보낸다.
-남은 1은 무조건 1이기떄문에 날린다
결론
-0.100011 * 2의3승
정규화한 위 값의 소숫점 아래 수 100011을 가수부 영역에 저장한다.
지수부에는 위의 값에서 2의 3승을 2진수로 표현한다. 위에 값에서는 3승이니
3+(bias) 공식을 따름 -> 3+(2의 (8-1)승 - 1) -> 3+(128-1) -> 130이 나온다
위의 나온 130을 이진수로 변환한 값은
1000 0010이 나온다 이걸 지수부에 저장
[0]    [10000010]      [100011 나머지는 0]
부호    지수부       가수부(유효숫자를 뜻)
1비트 8비트 23비트
-> 0100 0001 0100 0110 0000 0000 0000 0000
16진수로
-> 0x41460000
이 가공된 값이 RAM이나 HDD에 저장된다
이때 소수점 아래의 값이 클수록 가수부의 길이도 길어지는데 그 값이 선언한 파라미터인 float이나 double의 자리수를 넘어선다면 뒷부분은 짤리게 된다.(191줄 참조)
이때 5가지 정책으로 짤린 부분을 처리한다
부동 소수점의 반올림 모드 5가지
-짝수로 반올림 (round to nearest, ties to even)
-큰 절대값으로 반올림 (round to nearest, ties away from zero)
-올림 (round toward +∞)
-버림 (round toward -∞)
-절삭 (round toward zero)
참고 - https://devocean.sk.com/blog/techBoardDetail.do?ID=165270

2진수와 16진수

10진수의 0~15를 2진수로
->0000 0001 0010 0011 ~~
10진수의 0~15를 16진수로
->0123456789abcdef
2진수 4bit를 16진수의 1자리로 변환가능
2진수를 간결하게 표기할 수 있고 변환이 용이해 16진수를 많이 사용

캐리지 리턴, 라인 피드

윈도우 상에선 줄바꿈 할 때 2byte가 삽입(unix = \n(1byte))
\r\n 으로 표기됨
\n = cr 캐리지 리턴이며 맨 앞으로 이동하라는 뜻
\n = lf 라인피드 new line을 뜻함

[Character set]

문자를 2진수로 변환하는 규칙(문자집합)

1. ASCII

7bit
영어만을 위한 문자
다른 언어 지원이 필요해 나온 것이 ANSI

2. ISO-8859-1

8bit = ASCII + 유럽문자

3. EUR-KR

16bit = ISO-8859-1 + 한글
한글문자에 대한 코드 정의
똠 등 정의가 되어있지 않은 글자가 있음
그런 글자들은 또 + ㅁ 으로 처리함
코드 상으로 B7C7 A4B1으로 처리

조합형(아래한글)

한글(1) + 초성(5) + 중성(5) + 종성(5) 총 16bit로 처리
각각 32자로 한글의 모든 조합 처리가능
국제 표준 X

4. MS949

EUC-KR + 나머지 한글(지원 안되던) = 11172자 지원 (16bit)
EUC-KR에 지원 안되던 글자들은 새로운 코드(8C63)로 적용해 EUC-KR로 만든 문서들에 영향이 안 가도록 함
그 때문에 코드의 숫자 순으로 정렬했을 떄 코드의 순서가 한글의 순서와 맞지않아 정렬이 안됨(가 보다 똠 같은 코드를 새로 적용한 글자가 더 위에서 정렬됨)
국제 표준 X (다른 OS에서 못 읽음)

5. unicode(UTF-16 BE)

2~4byte(언어마다 바뀜) A -> 0x0041 = 2byte 사용 -> 1바이트로 충분함에도 불구하고 2바이트 사용으로 메모리가 낭비 -> 이걸 보완하기 위해 UTF-8이 등장
EUC-KR 과 다르게 코드를 새로 정의해 코드 순서대로 정렬 가능
Java는 문자를 다룰 때 unicode(UTF-16 BE) 사용
참조 - https://lordofkangs.tistory.com/86

LE    vs     BE

가 : 00AC         AC00
A : 4100         0041
바이트 위치가 반대

6. UTF-8

unicode를 번형한 것이 UTF-8
unicode의 4바이트 중 3바이트까지만 씀(거의)
A : 0x0041 -> 0x41
UTF-*

[리터널]

정수

32bit = 4byte = int = 0x00000000;
64bit = 8byte = long = 0x0000000000000000;

문자

char = 2byte = 0~65535 유니코드(UTF-16)

부동소수점 주의할 점 (소수점 출력할 떄 자리수를 정확히 처리해줘야하는 이유)

유효자릿수가 넘어가는 경우 에러가 아니라 값이 잘리거나 변형이 된 값이 저장된다
float(4byte = 7자리)에 7자리 넘는 부동소수점 값을 넣으면 안됨
또 부동소수점은 100프로가 아님, 조금 다른 값이 출력될 수 있음
그렇기 때문에 부동소수점을 활용할 땐 필요한 자리수를 정확히 계산해서 그만큼만 출력해야한다
그래서 보통 **float = 6자리 double = 15자리**까지는 오차없이 출력 가능하기 떄문에 조심할 것

자바에서 유니코드 쓰는 경우

파이 기호, 한자, 시그마 기호 등 직접 적기 힘든 부분은 유니코드를 사용해서 작성
\u 뒤에 코드를 작성

1
sysout(\u03c0) = π ;

폰트

-Raster 폰트 (bitmap)/ 크기를 늘리면 계단 형상 발생/ 출력 속도가 빠름 -Vector 폰트 (truetype)/ 최근에 많이 사용/ 깔끔하게 출력/ 속도가 상대적으로 느리지만 cpu의 발전으로 단점이 없어짐

ANSI 코드

1
System.out.print(\033[1;32m String \033[0m\);

위 같은 형식
1m = bold , 32m = red color, 0m = reset 등등
이러한 형식으로 사용할 수 있음

변수

값을 담을 메모리
변수 선언
값을 담을 메모리를 준비시키는 명령문 = JVM가 관리하는 메모리 중 메모리 할당(?)
만들 메모리 종류 = data type(int, string 등)
메모리 이름 = variable\

1
int(data type) x(varialbe) = 0;

문자열

메모리에 저장시 크기는 JVM에 따라 다르고 메모리의 주소를 저장한다 = 레퍼런스(reference)
ABC의경우
[0041 0042 0043] [글자개수] [문자열에 대한 정보]
코드(6byte)     3     크기 알 수 없음

변수명

  1. 일반 변수 -> camel 표기법
    첫번쨰 알파벳은 소문자, 각 단어의 시작은 대문자
  2. 상수(constants)
    상수는 값을 한번만 저장 가능, 대문자로 표기, 단어 사이에 밑줄 삽입
    1
    2
    
    final int PI = 3.14f;  //변수 앞에 final 을 넣어서 선언
    FIRST_NUMBER = 3; 
    

객체와 클래스 그리고 인스턴스

인스턴스
참조) https://velog.io/@k7nsuy/%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4%EB%9E%80

  1. 클래스(Class) 란
    • 개념
      객체를 만들어 내기 위한 설계도 혹은 틀
      연관되어 있는 변수와 메서드의 집합
  2. 객체(Object) 란
    • 개념 소프트웨어 세계에 구현할 대상
      클래스에 선언된 모양 그대로 생성된 실체
    • 특징 ‘클래스의 인스턴스(instance)’ 라고도 부른다.
      객체는 모든 인스턴스를 대표하는 포괄적인 의미를 갖는다.
      oop의 관점에서 클래스의 타입으로 선언되었을 때 ‘객체’라고 부른다.
  3. 인스턴스(Instance) 란
    • 개념
      설계도를 바탕으로 소프트웨어 세계에 구현된 구체적인 실체
      즉, 객체를 소프트웨어에 실체화 하면 그것을 ‘인스턴스’라고 부른다. 실체화된 인스턴스는 메모리에 할당된다.
    • 특징
      인스턴스는 객체에 포함된다고 볼 수 있다.
      oop의 관점에서 객체가 메모리에 할당되어 실제 사용될 때 ‘인스턴스’라고 부른다.
      추상적인 개념(또는 명세)과 구체적인 객체 사이의 관계 에 초점을 맞출 경우에 사용한다.
      ‘~의 인스턴스’ 의 형태로 사용된다.
      객체는 클래스의 인스턴스다.
      객체 간의 링크는 클래스 간의 연관 관계의 인스턴스다.
      실행 프로세스는 프로그램의 인스턴스다.
      즉, 인스턴스라는 용어는 반드시 클래스와 객체 사이의 관계로 한정지어서 사용할 필요는 없다.
      인스턴스는 어떤 원본(추상적인 개념)으로부터 ‘생성된 복제본’을 의미한다.\
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* 클래스 */
public class Animal {
  ...
}
/* 객체와 인스턴스 */
public class Main {
  public static void main(String[] args) {
    Animal cat, dog; // '객체'

    // 인스턴스화
    cat = new Animal(); // cat은 Animal 클래스의 '인스턴스'(객체를 메모리에 할당)
    dog = new Animal(); // dog은 Animal 클래스의 '인스턴스'(객체를 메모리에 할당)
  }
}
//변수 명
public class test {

	int iv; // 인스턴스 변수
	static int cv; // 클래스 변수
	
	void method() {
		int lv; // 지역 변수
	}
}

참조) https://gmlwjd9405.github.io/2018/09/17/class-object-instance.html

클래스 vs 객체, 객체 vs 인스턴스

  • 클래스(Class) VS 객체(Object)
    클래스는 ‘설계도’, 객체는 ‘설계도로 구현한 모든 대상’을 의미한다.
  • 객체(Object) VS 인스턴스(Instance)
    클래스의 타입으로 선언되었을 때 객체라고 부르고, 그 객체가 메모리에 할당되어 실제 사용될 때 인스턴스라고 부른다.
    객체는 현실 세계에 가깝고, 인스턴스는 소프트웨어 세계에 가깝다.
    객체는 ‘실체’, 인스턴스는 ‘관계’에 초점을 맞춘다.
    객체를 ‘클래스의 인스턴스’라고도 부른다.
    ‘방금 인스턴스화하여 레퍼런스를 할당한’ 객체를 인스턴스라고 말하지만, 이는 원본(추상적인 개념)으로부터 생성되었다는 것에 의미를 부여하는 것일 뿐 엄격하게 객체와 인스턴스를 나누긴 어렵다.

레퍼런스

메모리의 주소를 뜻함
byte, short, int, long, float, double, boolean, char를 제외하고 모두 레퍼런스로 보면 됨

가비지(garbage)

주소를 잃어버려 사용하지 못하는 인스턴스

1
2
int[] a = new int[3];
a = new int[2];

이러한 경우 위에 선언했떤 arr[3] 크기의 배열은 주소값이 덮어씌어져서 사용하지 못함

가바지 컬렉터 실행

메모리가 부족해지면 JVM은 OS에 메모리를 추가로 요청하기 전에 가비지 컬렉터를 실행해 가비지를 제거하여 메모리를 확보
가비지 컬렉터가 실행되기 전에는 가비지는 계속 존재해 메모리 낭비가 발생

static type binding vs dynamic type binding

Java의 경우 static type binding으로 변수의 타입이 선언할 때 고정됨
JavaScript의 경우 dynamic type binding으로

1
2
3
4
var a;
a = 123;
a = "abc";
a = true;

와 같이 할당 할 때 타입이 결정(동적 타입)

명시적 형변환

큰 메모리 값을 작은 메모리 값에 넣을 떄 강제적으로 넣는 방법

1
int a = (long)b; //

만약 메모리의 크기를 벗어나는 큰 수의 값을 넣으려한다면 -> 뒤의 바이트부터 저장

1
2
3
short temp = 200;
b2 = (byte)temp;
sysout(b2); //-56

연산자

연산의 프로세스는 연산하는 변수의 타입에 의해 결정된다
자바에서는 연산할 때 변수 타입에 맞는 메모리를 할당시켜 그 메모리에서 연산을 한다
연산의 기본 메모리 단위는 int 이며, long = long, float = float, double = double 이다.
하지만 int보다 작은 short,byte 의 경우에는 int보다 작아 변수를 사용한 연산이 되지 않는다.
그렇기 때문에 형변환이 필요하다.
형변환은 변수를 long 으로 바꾸라는 것이아니라, x 변수에 들어있는 값을 long 임시 변수(메모리)를 만들어 저장하라는 뜻

1
2
3
4
5
6
7
8
9
10
11
int x = 1;
int y = 2;
int sum = x + y; // 문제없음

int x = 21;
int y = 21;
int sum = x + y; // 오버플로우
long sum2 = x + y; 
// int 타입의 두 변수를 더하는 경우라 연산 메모리도 int라 똑같이 오버플로우
long sum3 = (long)x + (long)y; 
// long 으로 형변환하면 해결 unsigned int 의 경우 자바에서 존재하지 않음 무조건 long으로 처리

암시적 형변환

byte,short -> int -> long -> float -> double
연산할 두 변수의 타입이 다르면 연산이 불가 그래서 화살표 순으로 메모리가 큰 타입으로 자동변환하여 연산

1
2
byte + int -> byte가 int로 형변환
int + long -> int가 long으로 형변환

비트연산자

비트연산
& : Mask 연산 = 두 개의 비트가 모두 1일 때 1 반환
| : 두 개의 비트 중 하나라도 1이면 1 반환
^ : 두 개의 비트가 서로 다른 경우 1 반환
~ : 0에서 1로, 1에서 0으로 반환
num1 « num2 : num1의 비트 열을 num2칸씩 왼쪽으로 이동(빈자리는 0으로 채움)
num1 » num2 : num1의 비트 열을 num2칸씩 오른쪽으로 이동(빈자리는 최상위 부호비트와 같은 값으로 채워짐 음수=1, 양수=0)
num1 »> num2 : »와 기본적으론 값음. 다른점은, 3비트 이동, 빈자리를 부호비트와 상관없이 양수 = 0 으로 채움
참조 - https://coding-factory.tistory.com/521

비트연산자를 활용한 계산

비트연산자를 이용해 연산한다면 일반 연산자를 이용한 것보다 속도가 빠름
단, 2의 거듭제곱만 가능

1
2
3
54 & 2 == 54 % 2; // &는 나머지를 계산하는데 사용
num << 2 == num * 2; // <<는 곱하기를 계산하는데 사용 
num >> 2 == num / 2 // >>는 나누기를 계산하는데 사용

비트연산을 통해 boolean값을 저장해 메모리 절약가능
참조)Exam0450

조건연산자

1
변수 = 조건 ? 표현식1 : 표현식2 ;

조건이 참일 때 표현식1 실행, 거짓일 때 표현식2 실행

표현식

expression = 값을 리턴하는 statement(문장)
ex) sysout은 리턴값이 없어 안됨

파라미터와 아규먼트

1
2
3
4
void test(String value){ <= 파라미터
    sysout(value);
}
test(1); <= 아규먼트

test()라는 명령블록(메소드 = 함수) 전달하는 값 “아규먼트”
전달 받은 값 “파라미터”

증감 연산자

++변수, –변수 = 전위연산자(prefic operator)
변수++, 변수– = 후위연산자(postfix operator) -> 후위 연산자의 경우 조심해야할 것
항상 r-value를 먼저 실행(연산) 후에 할당(연산자 우선수위 참조)
그렇기 떄문에 후위 연산자의 경우

1
2
3
4
5
6
int a = 1;
int b = a++;
--------------컴파일시
int temp = a;
a = a + 1;
b = temp;

이런 식으로 임시 변수에 a를 저장하고 연산 후 마지막에 b에 할당한다

1
2
3
4
5
6
7
int a = 1;
a = a++;
-----------컴파일시
temp = a
a = a + 1
a = temp
a = 1이 된다

그렇기 때문에 위 식에서 a에 할당을 제일 나중에 하기 때문에 a = 100이 된다(a++과 a = a++이 다른 이유)
!주의할 점 - 전위, 후위 연산자는 변수에만 적용가능 리터럴에 적용 X

if문

if ~ else~ 문은 한 문장으로 처리
if ~ else if ~ 는 없는 문법 if ~ else ~ 를 여러번 하는 것일 뿐
else 는 가장 가까운 if문을 따라감

1
2
3
if //1
    if //2
else

일 때 else는 2번 if에 연결되어있는 것

enum

상수를 좀 더 조직적으로 관리하는 방법

라벨

라벨명:
break 라벨명;
이러면 라벨이 묶인 반복문 탈출

for문과 배열을 이용해 모든 값 꺼내기

1
2
3
4
5
6
7
8
9
int[] arr = {1, 2, 3, 4, 5};

for(int num : arr) // 변수 선언 밖에서 불가능, for문 조건 안에서만 가능
    sysout(num);
----------------------------컴파일시
for (int i=0; i<5; i++) {
    int num = arr[i];
    sysout[num];
}

Array VS ArrayList

배열차이

메소드

클래스객체.메소드(아규먼트(가변정보)); –클래스로 정보 전달-> 해당 클래스의 메소드(파라미터(받아온 정보));

표준 스트림

표준 스트림
STDIN (Standard input, 0, 입력을 위한 스트림)

  • 표준 입력은 프로그램으로 들어가는 입력값의 데이터 스트림이여, 줄여서 stdin 으로 표현함. 리눅스 쉘에서는 표준 설정이 키보드로 되어 있다. 모든 프로그램이 입력을 요구하지 않는다. 표준인 키보드 뿐만 아니라 다른 프로그램과 연결 등 다양한 방법이 있다.

STDOUT (Standard Output, 1, 출력을 위한 스트림)

  • 표준 출력은 프로그램이 출력 데이터를 기록하는 스트림으로, 줄여서 stdout 으로 표현함. 대부분 텍스트 터미널에서 이루어지며 표준 입력과 마찬가지로 모든 프로그램이 출력을 요구하지 않는다. 표준인 터미널 뿐만 아니라 입력과 마찬가지로 다른 프로그램과 연결 등 다양한 방법이 있다.

STDERR (Standard Error, 2, 오류 메시지를 출력하기 위한 스트림)

  • 표준 오류는 오류 메시지나 진단을 출력하기 위해 일반적으로 쓰이며, 또다른 출력 스트림이다. 줄여서 stderr로 표현함

참조) https://shoark7.github.io/programming/knowledge/what-is-standard-stream

표준 스트림이 아닌 방식

소켓(Socket)

표준 스트림 중 프로그램에서 외부 네트워크로 데이터를 주고 받기 위해 별도의 입/출구를 뚫는 것을 소켓 프로그램이라 한다.

File I/O 스트림

표준 스트림 중 외부 파일로 데이터를 읽고/쓰기 위해 별도의 입/출구를 뚫는 것을 File I/O 스트림이라고 한다.

오버로딩과 오버라이딩

  • 오버로딩 같은 이름의 메소드를 여러개 가지면서 받는 매개변수의 유형과 갯수를 달리하는 것
  • 오버라이딩 상속 관계에 있는 부모 클래스에서 이미 정의된 메소드를 자식 클래스에서 같은 시그니쳐를 갖는 메소드로 다시 정의하는 것
    자바에서 자식 클래스는 부모 클래스의 private 멤버를 제외한 모든 메소드를 상속받습니다.
    이렇게 상속받은 메소드는 그대로 사용해도 되고, 필요한 동작을 위해 재정의하여 사용할 수도 있습니다.
    즉, 메소드 오버라이딩이란 상속받은 부모 클래스의 메소드를 재정의하여 사용하는 것을 의미합니다. 참조) https://tcpschool.com/java/java_inheritance_overriding

객체 지향 프로그래밍

객체 지향 프로그래밍의 4가지 특성

추상화, 상속, 다형성, 캡슐화

상속(inheritance)이란?

상속(inheritance)이란 기존의 클래스에 기능을 추가하거나 재정의하여 새로운 클래스를 정의하는 것을 의미합니다.\

이러한 상속은 캡슐화, 추상화와 더불어 객체 지향 프로그래밍을 구성하는 중요한 특징 중 하나입니다.\

  • 상속을 이용하면 기존에 정의되어 있는 클래스의 모든 필드와 메소드를 물려받아, 새로운 클래스를 생성할 수 있습니다.
    이때 기존에 정의되어 있던 클래스를 부모 클래스(parent class) 또는 상위 클래스(super class), 기초 클래스(base class)라고도합니다.
    그리고 상속을 통해 새롭게 작성되는 클래스를 자식 클래스(child class) 또는 하위 클래스(sub class), 파생 클래스(derived class)라고도 합니다.
    상속

이처럼 부모 클래스는 자식 클래스에 포함된 것으로 볼 수 있습니다.
따라서 부모 클래스에 새로운 필드를 하나 추가하면, 자식 클래스에도 자동으로 해당 필드가 추가된 것처럼 동작합니다.
자식 클래스에는 부모 클래스의 필드와 메소드만이 상속되며, 생성자와 초기화 블록은 상속되지 않습니다.
또한, 부모 클래스의 접근 제어가 private이나 default로 설정된 멤버는 자식 클래스에서 상속받지만 접근할 수는 없습니다.

Object 클래스

자바에서 Object 클래스는 모든 클래스의 부모 클래스가 되는 클래스입니다.
따라서 자바의 모든 클래스는 자동으로 Object 클래스의 모든 필드와 메소드를 상속받게 됩니다.

즉, 자바의 모든 클래스는 별도로 extends 키워드를 사용하여 Object 클래스의 상속을 명시하지 않아도 Object 클래스의 모든 멤버를 자유롭게 사용할 수 있습니다.

자바의 모든 객체에서 toString()이나 clone()과 같은 메소드를 바로 사용할 수 있는 이유가 해당 메소드들이 Object 클래스의 메소드이기 때문입니다.

동적변수와 정적변수

기본적인 변수는 동적(dynamic) 변수로써 변수 선언과 동시에 메모리에 할당되며 변수 사용이 모두 끝남과 동시에 메모리가 해제된다.

하지만 정적(static) 변수는 전역변수와 동일하게 컴파일시 메모리에 할당되며, 프로그램 종료시 메모리가 해제된다.

따라서 정적 변수는 전역변수처럼 변수의 범위를 벗어나는 경우에도 값을 유지하는 속성을 가지고 있다.

static(정적 변수)란

static이 붙은 변수나 메소드는 어떤 객체에 소속된 것이 아니라, 클래스에 고정되어있는 변수나 메소드라는 뜻.

static의 특징

  1. 메모리에 고정적으로 할당된다.

  2. 객체 생성 없이 사용할 수 있다. ```java public class Main {

    public void print(){ System.out.print(“이게 실행될까요”); }

    public static void main(String[] args){ print(); } } —————————————위의 경우 실행 x public class Main {

    public void print(){ System.out.print(“이게 실행될까요”); }

    public static void main(String[] args){ Main main = new Main(); print(); } —————————————이와 같이 new로 선언했을 땐 실행 가능 public class Main {

    public static void print(){ System.out.print(“이게 실행될까요”); }

    public static void main(String[] args){ print(); } } —————————————하지만 static을 사용시 같은 클래스 안에 있다면 따로 선언하지 않고 사용 가능 }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
3. 프로그램이 시작되면 메모리의 static 영역에 적재되고, 프로그램이 종료될 때 해제된다.

static이 붙은 메소드나 변수의 경우 프로그램 시작할 때 클래스와 같이 **자동으로 메모리의 static 영역에 생성**. 자동으로 메모리에 올라가기 때문에 객체를 생성할 필요 없이 사용이 가능한 것입니다. 또한 자동으로 메모리에 올라가기 때문에 main함수를 static으로 구현하여 바로 실행할 수 있도록 만들어 주는 것입니다.

**일반적인 메서드**는 객체를 생성하면 메모리의 **Heap** 영역에 올라가게 됩니다. 메모리의 이 Heap 영역은 Garbage Collector에 의해 자동으로 관리되게 됩니다. 즉 사용하지 않는 객체의 경우 알아서 삭제시킴으로써 메모리를 관리해줍니다.

반면 **static 메서드**는 static 영역에 존재하기 때문에 이러한 관리를 받지 못합니다. 따라서 **프로그램이 종료될 때 메모리를 해제**하게 되는데, 이 때문에 과도하게 많은 static을 선언할 경우 메모리에 과부하가 올 수 있습니다.

그렇기에 무분별한 static 사용은 조심해야한다.

4. Static 메서드 내에서는 인스턴스 변수를 사용할 수 없다.

Static 메서드는 프로그램 실행과 동시에 메모리에 올라가기 때문에 인스턴스 변수는 사용할 수 없습니다. 인스턴스 변수는 객체를 생성해야만 사용이 가능하기 때문에 객체를 생성하기 전에 먼저 메모리에 올라가는 static 메서드에서는 사용할 수 없는 것입니다. 그래서 메서드에 static을 붙여주고 싶다면, 해당 메서드 내부에 인스턴스 변수나 인스턴스 메서드를 사용하는 부분이 있는지 먼저 확인해주어야 합니다.

# this 키워드
개념

- this는 인스턴스의 자기자신을 의미한다.
- 인스턴스화 되었을 때 자기자신의 메모리 주소를 담고있는 키워드이다.

this 키워드의 세 가지 역할

- 자기 자신의 메모리를 가르킨다.
- 생성자에서 다른 생성자를 호출할 경우 사용한다.
- 인스턴스 자신의 주소를 반환할 때 사용한다.

getter와  setter에 사용된다.
### 인스턴스의 자기자신을 의미한다의 예

public class FruitTest { public static void main(String[] args) { EX1_Fruit getFruit = new EX1_Fruit();

1
2
3
4
5
6
	getFruit.setFruitNo(1001);
	getFruit.setFruitName("사과");
	
	System.out.println(getFruit.fruitNo);
	System.out.println(getFruit.fruitName);
} }

class EX1_Fruit { public int fruitNo; // 과일 고유번호 public String fruitName; // 과일 이름

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void setFruitNo(int fruitNo) {
	this.fruitNo = fruitNo;
}

public void setFruitName(String fruitName) {
	this.fruitName = fruitName;
} } 결과 : 1001 사과 -----------------------------------------------------this를 사용하지 않는 경우 class EX1_Fruit {
public int fruitNo; // 과일 고유번호
public String fruitName; // 과일 이름

// this를 사용하지 않으면?
public void setFruitNo(int fruitNo) {
	fruitNo = fruitNo;
}

public void setFruitName(String fruitName) {
	fruitName = fruitName;
} } 결과 : 0 null ------------------------------------------------------매개변수의 이름과 대입하는 이름이 같아 값이 입력 x, 만약 매개변수와 대입하는 변수의 이름이 다르다면 this사용하지 않아도 됨 ``` 계산기 프로그램을 구현하는 것도 예로 들 수 있다. 계산기의 경우 계산 후 값을 가지고 있으면서 다른 계산도 지속적으로 해야되기 때문에 this를 사용해 인스턴스 변수에 값을 저장 후 그 값을 다시 계산하는 방식을 사용

생성자에서 다른 생성자를 호출할 경우 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class EX2_Fruit {
	public int fruitNo; // 과일 고유번호
	public String fruitName; // 과일 이름
	
	public EX2_Fruit() {
		this(1002, "오렌지");
	}

	public EX2_Fruit(int fruitNo, String fruitName) {
		this.fruitNo = fruitNo;
		this.fruitName = fruitName;
	}
	
	public void showInfo() {
		System.out.println("과일 고유번호 : " + fruitNo);
		System.out.println("과일 이름 : " + fruitName);
	}
}
-------------------------------------------------------위의 클래스를 메인문에서 실행시키면
public class FruitTest {
	public static void main(String[] args) {
		EX2_Fruit getFruit = new EX2_Fruit();
		getFruit.showInfo();
	}
}
결과 : 1002 오렌지
--------------------------------------------------------이렇듯 값을 대입하지 않은 경우 자동으로 생성자에서 대입된 값을 출력
public class FruitTest {
	public static void main(String[] args) {
		EX2_Fruit getFruit = new EX2_Fruit();
		getFruit.showInfo(1003, 사과);
	}
}
결과 : 1003 사과
-------------------------------------------------------- 값을 매개변수로 보낼 경우 그 값이 출력
class EX2_Fruit {
	public int fruitNo; // 과일 고유번호
	public String fruitName; // 과일 이름
	
	public EX2_Fruit() {
		fruitNo = 1003;
		this(1004, "낑깡"); // 첫번째 구문이여야 함!
	}

	public EX2_Fruit(int fruitNo, String fruitName) {
		this.fruitNo = fruitNo;
		this.fruitName = fruitName;
	}
	
	public void showInfo() {
		System.out.println("과일 고유번호 : " + fruitNo);
		System.out.println("과일 이름 : " + fruitName);
	}
}
에러!!
-------------------------------------------------------매개 변수가 없는 생성자에서 this를 사용하여 다른 생성자를 호출할 경우 해당 구문이 첫번째 구문이 되어야 한다.

인스턴스 자신의 주소를 반환할 때 사용

EX3_Fruit 클래스에서 반환 타입을 EX3_Fruit로 설정한 getSelf 메서드에서 반환 시 this를 반환한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class EX3_Fruit {
	public int fruitNo; // 과일 고유번호
	public String fruitName; // 과일 이름
	
	public EX3_Fruit(int fruitNo, String fruitName) {
		this.fruitNo = fruitNo;
		this.fruitName = fruitName;
	}
	
	public EX3_Fruit getSelf() {
		return this;
	}
}
----------------------------------------------------------------------메인 함수에서 EX3_Fruit 객체를 생성하고 해당 객체 정보 출력 및 test 객체를 하나 더 만들어서 해당 객체에 이전에 생성한 객체의 this 반환 값을 대입한다.

public class FruitTest {
	public static void main(String[] args) {
		
		EX3_Fruit getFruit_3 = new EX3_Fruit(1005, "수박");
		System.out.println(getFruit_3);
		
		EX3_Fruit test = getFruit_3.getSelf();
		System.out.println(test);
		
	}
}
출력 : this 가 가르키는 위치와 생성된 객체가 가르키는 위치가 같음

힙과 스택(메모리 구조)

메모리 구조

  • data 영역 전역변수, static variable들이 저장됨. 숫자나 문자열 값인 리터널(소스 코드의 고정된 값 ex) int i = 1; 의 1을 의미)도 저장
  • text(코드) 영역 code sagment라고 불림. 프로그램 코드가 저장되고 절대 변경되지 않음
  • steak 함수 호출에 쓰이는 지역변수, 매겨변수가 저장됨. 함수호출에 대한 활성 레코드들이 들어감. 또한 return address가 있어 함수가 종료될 때 다시 메모리 반환. 크기는 os나 컴파일러에 의해 정해짐. 공간은 cpu에 의해 효율적으로 관리되고, 메모리는 단편화 되지 않음(스택 특성)

공부해야될 목록- 참조사이트 https://www.codestates.com/blog/content/%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%8A%B9%EC%A7%95 https://tcpschool.com/java/java_polymorphism_abstract https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EA%B7%B8%EB%A6%BC%EC%9C%BC%EB%A1%9C-%EB%B3%B4%EB%8A%94-%EC%9E%90%EB%B0%94-%EC%BD%94%EB%93%9C%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%98%81%EC%97%AD%EC%8A%A4%ED%83%9D-%ED%9E%99

클래스 메서드 vs 인스턴스 메서드

클래스.메서드();

  • 작업 결과를 개별로 관리하지 않을 때
  • 파라미터 값만으로 작업을 수행할 때

레퍼런스.메서드();

  • 작업결과를 개별적으로 관리하는 경우
  • 파라미터를 사용해서 작업을 수행한 후 그 결과를 내부적으로 보관할 때

인스턴스 메서드를 사용하는 이유는 더 편리함.

객체지향 solid 원칙

클래스 용도 - 데이터 타입 정의

데이터를 저장할 메모리를 새로 정의

  • ‘사용자 정의 데이터 타입’이라 부름
  • 여러 개로 이루어진 데이터를 한 묶음으로 다루면 관리하기가 쉽다

코딩시

남의 클래스의 변수 직접 접근하지 말자 privite 으로 감싸 그 변수를 다루는 로직은 한 클래스에 묶어서 캡슐화 [ex) ObjectRepostory]

가져와야하는 변수의 값이 있다면 메소드를 만들자

file i/0

This post is licensed under CC BY 4.0 by the author.