새벽 3시에 자버렸다…. ㅎㅎ;;
고로 현재는 너무나도 졸린상태…

커피를 쏟아부어서 열심히 공부를 시작해보자!
어제는 Git에 대해서 찍먹을 해보았다.
Git의 동작원리라던가 명령어 사용법등 유익한 시간이었고
오늘은 드디어 JAVA언어를 시작해보는 시간을 가진다.


자바란?

1996년 1월에 세상에 나온 객체지향 프로그래밍(Object Oriented Programming, OOP)언어 이다.
운영체제에 독립적으로 실행이 가능하다. 그러므로 다양한 운영체제가 공존하는 웹 환경에 적합한 언어로
현재까지도 전 세계에서 많이 쓰이는 인기 있는 언어이다.

나보다 1살어린 자바
그치만 나보다 똑똑한 것 같구나..


특징

  1. 운영체제에 독립적
  2. 객체지향 언어
  3. 함수형 프로그래밍 지원
  4. 자동 메모리 관리


JVM (Java Virtual Machine)

자바가 운영체제에 독립적인 것은 JVM이 있기 때문에 가능한 것이다.
JVM은 자바 코드로 작성한 프로그램을 해석해 실행하는 별도의 프로그램 이다.
즉, 프로그램을 실행하는 프로그램이다!

자바코드를 중간에 JVM이 해석해 각각 운영체재에따라 보내줄 수 있는 모습이다.
JVM의 경우 JDK나 JRE를 설치하면 자동으로 설치된다.
아무래도 자바는 JVM을 거치기 때문에 C나 C++에 비해 속도가 느린 편이라고 한다.
기본 구조가 [프로그램-OS-CPU]라고 가정하면
그사이에 [프로그램-JVM-OS-CPU]으로 JVM이 끼워져있는 느낌.


JDK (Java Development Kit)

JRE (Java Runtime Environment) : JVM + 표준 클래스 라이브러리
JDK (Java Development Kit) : JRE + 개발에 필요한 도구


변수와 타입

변수 (Variable)

값이 변할 수 있는 데이터를 임시적으로 저장하기 위한 수단
값을 저장 할 수 있는 메모리 공간에 사람이 식별할 수 있는 이름을 붙인 것!

int num; 변수선언
num = 0; 변수할당
자바에서는 변수명을 일반적으로 camelCase를 사용한다.
ex) int getNumber;


상수 (Constant)

변하지 말아야 할 데이터를 임시적으로 저장하기 위한 수단
재할당이 금지된 변수.
ex) final double PI = 3.14; PI라는 값은 3.14로 지정되어 재할당이 금지!

상수를 쓰는 이유?
1). 프로그램 실행되면서 값이 변하면 안될 경우 (프로그래머의 실수를 방지함)
2). 코드의 가독성을 높일 경우 (상수를 쓰면 값의 쓰임새가 명확해짐)
3). 코드 유지관리를 쉽게 하고자 하는 경우 (위의 PI라는 값을 여러군대 사용할 경우 하나만 변경하면된다)


타입

값이 차지하는 메모리 공간의 크기와, 값이 저장되는 방식

기본타입

-. 값을 저장할때, 데이터의 실제 값이 저장됨
-. 정수타입, 실수타입, 문자타입, 논리타입이 포합됨
ex) int a = 1;

a는 실제 값을 저장하고있기에 기본타입 변수이다.


참조타입

-. 값을 저장할때, 저장된 곳을 나타내는 주소값이 저장됨
-. 정수타입, 실수타입, 문자타입, 논리타입을 제외한 나머지 타입
ex) Babo you = new Babo();

예를들어 바보라는 Class의 객체를 you라는 변수에 할당했을 경우
you는 참조타입 변수가 된다.


리터럴 (Literal)

문자가 가리키는 값 그 자체를 의미한다.
ex) int a;
a=1;

이라고 가정했을 경우 1이 리터럴에 해당한다. 이럴경우 정수형 리터럴 1을 a에 할당했다고한다.


정수타입

정수타입은 총 4개의 타입으로 분류된다. (byte,short,int,long)
각각 차지하는 메모리의 크기가 다르며, 그에 따라 나타낼 수 있는 숫자의 범위가 다르다.

타입 메모리 표현 범위
byte 1byte -128 ~ 127
short 2byte -32,768 ~ 32,767
int 3byte ~2,147,483,648 ~ 2,147,483,647
long 4byte -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807


실수타입

실수는 소수점을 가지는 값을 의미하고, 총 2개의 타입으로 분류된다 (float,double)

타입 메모리 표현 범위 정밀도
float 4byte 음수 : -3.4 * 10³⁸ ~ -1.4 * 10⁻⁴⁵
양수 : 1.4 * 10⁻⁴⁵ ~ 3.4 * 10³⁸
7자리
double 8byte 음수 : -1.8 * 10³⁰⁸ ~ -4.9 * 10⁻³²⁴
양수 : 4.9 * 10⁻³²⁴ ~ 1.8 * 10³⁰⁸
15자리


논리타입

논리타입의 종류는 하나이고 boolean형 한가지만 가지게된다.
이 값은 오직 true, false값으로 나눠지고
1bit만 있으면 되지만, JVM이 다루는 데이터 최소단위가 1byte이기 때문에
boolean형은 1bye의 크기를 가집니다.
ex) boolean isAdult = ture;


문자타입

문자타입은 2byte크기의 char형 하나만 있다.
리터럴 작성시 작은 따옴표(‘‘)를 사용해아함.
ex) char babo = 'y';


자동 타입 변환

  1. 바이트 크기가 작은 타입에서 큰타입으로 (byer -> int)
  2. 덜 정밀한 타입에서 더 정밀한 타입으로 (정수-> 실수)
byte(1) -> short(2)/char(2) -> int(4) -> long(8) -> float(4) -> double(8)

예를 들어

byte a = 10;
int b = a;

라고할떄 자동 타입 변환이되어지기 때문에 따로 지정할 필요가 없다!

수동 타입 반환

차지하는 메모리 용량이 더큰타입에서 작은 타입으로는 자동으로 타입이 반환되어지지 않는다.
그래서 수동으로 타입 변환해주어야한다. 이를 캐스팅(Casting)이라고 합니다.

int a = 128;
byte b = (byte)a;

출력 : -128


문자열 (String)

선언방법

// 문자열 리터럴 Taxi를 String 타입의 변수 transfer1에 할당
String transfer1 = "Taxi";

// String 클래스의 인스턴스를 생성하는 방법
String transfer2 = new String("Taxi");

첫번째 선언 방법은 “문자열 리터럴을 직접 할당하는 방식”이고
두번째 선언 방법은 “String 클래스의 인서튼스를 생성하여 할당하는 방식”이다.
두개는 공통점과 차이점이 있는데
공통점은 참조 타입의 변수에 할당된다는 점이다.
즉, transfer1, transfer2는 실제 문자열 내용을 값으로 가지고 있는게 아니라, 문자열의
존재하는 메모리 공간 상의 주소값을 저장하고 있다.

참조변수인데 출력은 문자열이?

System.out.print(transfer1); // "taxi"
System.out.print(transfer2); // "taxi"

두 개의 문자를 출력했을 때, taxi로 출력되어진다.
이유는 String 타입의 변수를 참조하면 String 클래스의 매서드인 toString()이
자동으로 호출되어서 변수가 저장하고 있는 주소값에 위치한 인스턴스의 내용을
문자열로 변환해주기 때문.


참조변수 비교 방법은?

String transfer1 = "taxi";
String transfer2 = "taxi";
String transfer3 = new String("taxi");
String transfer4 = new String("taxi");

boolean comparison1 = transfer1 == "taxi";         // true
boolean comparison2 = transfer1 == transfer2;      // true
boolean comparison3 = transfer1 == transfer3;      // false
boolean comparison4 = transfer3 == transfer4;      // false
boolean comparison5 = transfer1.equals("taxi");    // true
boolean comparison6 = transfer1.equals(transfer3); // true
boolean comparison7 = transfer3.equals(transfer4); // true

위의 예시를 통해 알아보자.
우선 기본타입을 제외한 선언방식이므로 ‘참조 타입’이다.
즉, 주소값을 저장한다는 말이다.
== 는 주소값을 비교하는 구문이고 equals는 주소값의 내용을 비교한다.
transfer1, transfer2는 동일한 참조변수를 할당하였기에 주소값이 같다.
고로 transfer1과 transfer2를 == 으로 비교할 경우 true로 반환되어지는 것이다.
반대로, transfer3과 transfer4는 String 클래스의 새로운 인스턴스를
각개로 찍어낸 것이기 때문에 문자열 내용은 같더라도 참조값이 다르기때문에 false로 나타난다.
하지만 equals로 비교를할 경우 문자열 그대로 비교하는 것이기에
전부 true로 반환하는 모습을 볼 수 있다.


String 클래스의 여러가지 매소드를 이용하는 방법을 알아보자
*자세한 사용법은 Java 카테고리에서 포스팅할 예정이다.

.charAt(); : 문자열의 특정 위치의 값을 꺼낼 수 있다.
.compareTo(); :문자열을 비교후 정수로반환
.concat(); :문자열끼리 이어붙여서 반환, + 와 동일한 역활
.indexOf(); : 지정한 문자로 문자열의 첫번째 위치를 찾아 정수로 반환
.trim(); .strip(); : 공백을 제거해서 반환
.toUpperCase(); .toLowerCase(); : 대,소문자로 변환해서 반환

etc..


StringTokenizer

StringTokenizer 클래스는 문자열을 쪼개주는 클래스이다.
그렇게 쪼개어진 문자열을 토큰(token)이라고 한다.

import java.util.StringTokenizer;

public static void main(String[] args){
	String str = "This is a string example using StringTokenizer";
	StringTokenizer tokenizer = new StringTokenizer(str);
	System.out.println(str);
	System.out.println();
		
	System.out.println("total tokens:"+tokenizer.countTokens());
	// 아래의 while 코드는 반복문의 한 종류인데 어떻게 작동하는지 추후 반복문 챕터에서 공부할 예정이니 걱정하지 않으셔도 됩니다.
	while(tokenizer.hasMoreTokens()){
		System.out.println(tokenizer.nextToken());
	}
	System.out.println("total tokens:"+tokenizer.countTokens());
}

int countToken();
-. 남아 있는 토큰개수를 반환함

boolean hasMoreElements(); , boolean hasMoreTokens();
-. 두 메서드의 성능차이는 없고  boolean 타입으로 반환한다. 문자열에서 하나 이상의 토큰을
사용할경우 true, 그렇지 않으면 false.

Object nextElement();, String nextToken();
-. 토큰을 반환한다. nextElement는 객체를 반환하고, nextToken은 String을 반환한다.


StringBuilder

매번 인스턴스를 만들어서 문자열을 더하기에는 매우 비효울적이다.
StringBulider로 다양한 매서드를 이용해 String을 빌딩?이 가능하다.

public class Main {
    public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("문자열 ").append("연결");
        String str = stringBuilder.toString();
        System.out.println(stringBuilder);
        System.out.println(str);
    }
}

예제로 stringBulider라는 인스턴스를 만들어 이용해보자


StringBuffer

String 클래스의 인스턴스는 한 번 생성되면 그 값을 읽기만 할 수 있고, 변경은 불가능하다.
하지만 StringBuffer 클래스의 인스턴스는 그 값을 변경할 수도있고, 추가할 수도 있다.
StringBuffer 버퍼크기의 기본값은 16개의 문자를 저장할 수 있는 크기이며, 생성자를 통해
그 크기를 별도로 설정가능하다.

덧샘(+) 연산자를 통해 보통 String 인스턴스의 문자열을 결합하면, 내용이 합쳐진 새로운
String 인스턴스를 생성한다. 따라서 문자열을 많이 결합할수록 공간이 낭비될 뿐만 아니라 속도도 느려진다.
하지만 StringBuffer 인스턴스를 사용하면 문자열을 바로 추가할 수 있고, 공간의 낭비도 없으며
속도도 매우 빨라진다.

StringBuffer str = new StringBuffer("Java");

위와 같이 str이라는 인스턴스를 만들어 아래의 매서드를 사용해보자
.append(); : 해당 문자열의 마지막에 문자를 연결해준다.
.capacity(); : 메서드의 StringBuffer 인스턴스의 크기를 반환한다.
.delete(); : 메서드의 위치를 정해 문자르 삭제하여 반환한다.
.insert(); : append와 비슷한 역활로 원하는 위치에 지정한 문자열을 삽입한다.


연산자 (Operator)

산술 연산자는 사칙연산, 나머지 연산자가 포함된다.
(+, -, *, /, %)

증감 연산자
num1 = num1 + 1;
num2 = num2 - 1;
num1++ 은 전위형 증감연산자로 연산을 먼저 수행후 결과값 적용
++num1 은 후위형 증감연산자로 기존값을 먼저 적용시키고 다음에 연산을 적용 

복합 대입 연산자
num1 += num1;
num2 -= num2;
비교 연산자는 >, >=, <, <=, ==, != 가 있다.

초과,이상,미만,이하,같다,다르다 이렇게 비교를할 수 있고 boolean 타입으로 반환한다.
논리 연산자는 &&, || 가 있고
AND연산자, OR연산자라고 한다.
기본적으로 연산자들은 우선선위가 있다.

우선순위 연산자 내용
1 (),[] 괄호,대괄호
2 !,~,++,– 부정/증감 연산자
3 *,/,% 곱셈,나눗셈 연산자
4 <, <=, >, >= 대소 비교 연산
5 && AND 연산자
6 ıı OR 연산자
7 ?: 조건 연산자
8 =,+=,-=,/=,%= 대입,할당 연산자

마치며…

오늘은 기본적인 변수와 타입에 관련해서 공부했고
더 나아가 문자열과 연산자들을 알아보았다.
사실 여러 언어를 해보았지만
모든 언어는 처음에 배우는게 같은 것 같다.
이렇게 언어에 익숙해지고 사용하다보면
어느순간엔 편하게 코드를 작성할 때가 오겠지..?
오늘 공부는 여기서 끝!!


오늘의 커피량: ☕️ ☕️ ☕️ ☕️
오늘의 점심: 김밥, 라면