일일 정리

240604 자바(1) - 프로그래밍 기초/자바/자바 개발환경구축/이클립스/변수/자료형/문자열/서식 지정자/escape 문자/Scanner

햠__ 2024. 6. 7. 15:34

프로그래밍 기초


프로그램

컴퓨터에게 특정 문제를 해결하기 위해 처리 방법과 순서를 기술해 놓은 작업지시서

 

프로그래밍

프로그램의 목적에 따라 기능별 순서와 처리 방법을 설계하고 구현하는 것

 

프로그래머

프로그램을 설계하고 코딩하는 사람

 

프로그래밍 언어

사람의 언어와 기계의 언어의 중간 다리 역할을 하는 언어

고급 언어와 저급 언어로 구분 (고급 언어일수록 사람이 이해하기 쉽고, 컴파일러라는 번역 도구가 필요)

프로그래밍 언어로 작성된 내용을 소스(Source)라고 부르고, 이 소스는 컴파일러(Compiler)라는 소프트웨어를 통해서 기계어로 변환된 후 컴퓨터에서 실행할 수 있게 된다.

 

자바(Java)


1. 자바의 특징

- 객체 지향 프로그래밍(Object-Oriented Programming, OOP) 언어이다.

프로그램을 개발하는 기법 중 하나로 객체들을 만들고 이러한 객체들을 연결해서 전체 프로그램을 완성하는 기법이다.

 

- 운영체제에 독립적

소스를 수정하지 않아도, 자바 실행 환경(JRE, Java Runtime Environment)이 설치되어 있는 모든 운영체제에서는 실행이 가능하다.

 

- 자동으로 메모리를 관리한다.

개발자가 직접 메모리에 접근할 수 없도록 설계되었으며, 메모리는 자바가 가비지 컬렉터(Garbage Collector, GC)를 활용하여 직접 관리한다.

 

-

 

2. JVM (Java Virtual Machine)

운영체제에서는 자바 프로그램을 직접 실행할 수 없으며 JVM을 통해 자바 프로그램을 실행할 수 있다.

JVM은 JDK(Java Development Kit) 또는 JRE(Java Runtime Environment)를 설치하면 자동으로 설치되는데 JDK와 JRE는 운영체제에 별로 제공되고 운영체제에 맞게 설치해야 한다.

 

윈도우 위에 JVM이 존재하고 그 위에서 코드가 돌아간다. JVM은 운영체제에 맞게 설치되어야 한다.

 

-

 

자바 프로그램의 실행 단계

확장자가 .java인 소스파일을 작성한다.

작성된 소스파일을 자바 컴파일러로 컴파일하여 확장자가 .class인 바이트코드(기계어)로 번역한다.

번역된 바이트코드(기계어)를 JVM에서 실행한다.

 

 

자바 개발 환경 구축


JDK(Java Development Kit)

JDK는 프로그램 개발에 필요한 JRE(JVM), 라이브러리 API, 컴파일러 등의 개발 도구가 포함되어 있다.

 

JRE(Java Runtime Environment)

자바 프로그램 실행에 필요한 JVM, 라이브러리 API만 포함되어 있다.

자바 프로그램을 개발하는 것이 아닌 프로그램을 실행만 한다면 JRE만 설치하면 된다.

 

(JDK에 JRE가 포함되어 있다. JVM은 JRE에 포함되어있다.)

 

JDK의 종류

Java SE 가장 기본적인 것

Java EE SE를 기본으로 해서 서버 쪽 개발을 위한 도구들이 있다.

Java ME 휴대폰, PDA, 셋톱박스 등에서 지원하는 것

 

-

 

JDK 설치

https://adoptium.net/ 링크에 접속 후 Temurin 21 (LTS)를 다운로드 및 설치한다.

 

JAVA 버전 확인

 

설치 완료되면 위와 같이 powershell에서 자바 버전을 확인할 수 있다.

 

메모장에 강제로 확장자를 .java로 하여 간단한 코드 하나를 써본 뒤, 

powershell에서 javac (파일이름.java) 하면 .class 파일로 변경된다.

javac가..java로 된 파일을 기계어로 번역하여 .class로 변경된다.

 

이렇게 메모장에 쓰고 번역하고 이런 행위가 너무 힘들기 때문에 우리는 IDE를 설치한다.

우리는 IDE로 이클립스를 설치한다.

 

https://www.eclipse.org/downloads/

위 링크를 통해서 최신 버전의 Eclipse IDE를 다운로드한다.

 

Eclipse Downloads | The Eclipse Foundation

The Eclipse Foundation - home to a global community, the Eclipse IDE, Jakarta EE and over 415 open source projects, including runtimes, tools and frameworks.

www.eclipse.org

 

Eclipse Installer에서 우리는 enterprise java and web developers로 받는다.

나중에 Spring 사용도 할 것이기 때문? 설치가 완료되었다면 Launch 하면 된다.

 

-

 

환경 설정을 마저 해보자.

 

이클립스 설치 이후 위 설정 부분 중 windows 부분에 preferences를 킨다.

왼쪽에서 java - compiler 선택해서 컴파일 레벨을 21로 수정한다. (원래 되어있다면 OK)

 

그리고 왼쪽에 조금 더 아래에 Installed JREs 선택하고 오른쪽에 ADD를 선택해서 

Standard VM 선택 후, 폴더에 Eclipse adoptium을 추가해 준다.

 

jdk 설정

 

위와 같이 설정되었다면 jdk 설정이 완료된 것이다.

 

또한 UTF-8 설정도 해야 한다.

아까와 동일한 preferences에서 general에 Workspace로 넘어간다.

 

UTF-8 설정

 

아래에 UTF-8로 설정되어 있는지 확인한다. 

 

또한, 아래에 CSS 파일, HTML 파일, JSP 파일도 다 UTF-8로 변경하여 준다.

이유는 모르겠으나.. 나는 모든 것이다 UTF-8로 설정되어 있었다. 

그럼 설정은 끝이다!


 

이제 실습을 진행해 보자! 프로젝트를 하나 생성한다.

생성 시에 아래에 Create Module은 지금은 체크를 해제해 준다.

그럼 프로젝트 하나가 생성된 것을 확인할 수 있다.

 

src 파일을 선택해서 클래스를 생성해보자.

패키지를 작성해야 하는데, 흔히 회사의 도메인으로 쓰는데 이것의 역순으로 적고 프로젝트 이름을 적어주는 게 일반적이라고 한다.

 

class 생성

 

그럼 자바 파일이 하나가 생성되었다.

 

클래스 이름과, 아래 생성한 class 이름이 동일해야 한다. (대소문자도 구분함)

파일의 이름과 동일하지 않아 오류가 발생

 

생성된 파일에 간단한 테스트를 진행해 보자.

 

예시

 

또한, 실행할 때에는 벌레 버튼을 눌려도 되고, 아니면 우클릭 후 Run As 선택해도 된다.

단축키로는 Ctrl + F11 도 가능하다.

 

변수(Variable)


변수

컴퓨터 메모리(RAM)에 값을 저장하기 위해 할당받는 공간

프로그램에 의해서 할당받은 공간의 값이 수시로 변경될 수 있기 때문에 변수라고 부른다. 

 

변수의 선언

변수를 사용하기 위해서는 먼저 변수를 선언해야 한다.

변수의 선언은 어떤 타입의 데이터를 저장할 것인지 그리고 변수의 이름이 무엇인지 기술해야 한다.

변수를 선언하는 구문은 자료형 변수명;이다.

 

변수의 명명 규칙

영어 대소문자가 구분되며 문자수의 제한이 없다.

숫자로 시작하면 안 된다.

특수문자는 '_'와 '$'만 허용한다.

여러 단어로 조합된 변수의 이름은 첫 시작 글자는 소문자로 하고 조합되는 단어의 첫 글자를 대문자로 하는 것이 관례이다.

의미 있는 이름을 지어주는 것이 좋다.

예약어를 사용하면 안 된다.

 

변수의 초기화

변수를 선언하고 처음 저장되는 값을 초기값, 변수에 초기값을 대입하는 것

지역 변수(메소드 안에 선언된 변수)를 사용하려면 반드시 초기화되어야 한다.

 

-

 

변수 관련 실습을 진행해 보자!

 

먼저 practice 패키지에 Application.java라는 클래스 파일을 생성해 주었다. 

이 파일에서 우리는 생성한 메소드를 실행할 것이다.

 

package com.beyond.variable;

//Ctrl + shift + o 하면 import 알아서 넣어줌
import com.beyond.variable.practice.A_Variable;
import com.beyond.variable.practice.B_ConsoleOutput;
import com.beyond.variable.practice.C_KeyBoardInput;

public class Application {
	public static void main(String[] args) {
		// 1) 실행할 메소드가 있는 클래스를 생성(new)한다.
		// 		[표현법]
		//		  클래스명 변수명 = new 클래스명();
		
		// 1-1) import 구문 사용X 클래스 생성
//		com.beyond.variable.practice.A_Variable variable = 
//				new com.beyond.variable.practice.A_Variable();
		
		// 1-2) import을 사용하여 클래스 생성
		A_Variable variable = new A_Variable();
		B_ConsoleOutput output = new B_ConsoleOutput();
		C_KeyBoardInput input = new C_KeyBoardInput();
		
		// 2) 생성한 클래스로 메소드 실행(호출)
		//		[표현법]
		//			변수명.메소드명();
		
		variable.variableTest();
		variable.autoCasting();
		variable.casting();
		variable.practice();
		
		output.valuePrint();
		
		input.inputByScanner();
	}
}

 

우리는 import 구문을 사용하여 클래스 생성을 해주었다. 

import 구문을 생성하지 않고 클래스를 생성할 시에는 조금 길어져서 읽는데 불편함이 있을 수 있다.

import 구문을 넣을 때에는 생성한 클래스 코드에 커서를 놓고 Ctrl + Shift + O 를 하면 자동으로 알아서 import 구문을 넣어준다!

 

이후 생성한 클래스를 통해서 메소드를 호출하면 된다.

그럼 자료형과 함께 다음 클래스를 생성한 파일들을 살펴보자.

 

자료형


자료형은 저장될 데이터의 타입을 뜻하며 저장하고자 하는 값의 종류에 맞게 기술해야 한다.

 

기본 타입

정수, 실수, 문자, 논리 타입 존재

기본 타입은 정해진 메모리 크기를 사용해 값을 저장하는데 바이트 크기가 클수록 표현하는 값의 범위가 크다.

 

논리형 boolean 1byte
문자형 char 2byte
정수형 byte 1byte
정수형 short 2byte
정수형 int 4byte
정수형 long 8byte
실수형 float 4byte
실수형 double 8byte

 

-

 

문자열

단어나 문장을 문자열이라고 한다.

문자열을 저장할 때는 String 타입을 사용하는데 String은 클래스 타입으로 String 타입의 변수는 참조 변수이다.

 

예를 들어, 다음과 같은 String 타입의 변수를 생성해보자.

String name = new String("홍길동");

 

그럼 이것은 주소값이 대입이 된다.

이게 무슨 말이냐 하면 Stack과 Heap이 있는데 

Heap의 해당 주소지에 "홍길동"이라는 값이 들어가고, Stack에는 Heap의 주소지가 들어간다.

그래서 즉, Stack에 있는 주소지가 Heap의 주소지 번째를 가리켜 값을 가져오는 것이다.

 

아래는 변수 + 자료형 실습 예제이다.

 

package com.beyond.variable.practice;

public class A_Variable {
	
	/*
	 * 변수의 선언
	 * 	[표현법]
	 * 		자료형 변수명;
	 */
	public void variableTest() {
		// 논리형 변수
		boolean isTrue;
		
		// 정수형
		byte bNum;
		short sNum;
		int iNum;
		long lNum;
		
		// 실수형
		float fNum;
		double dNum;
		
		// 문자형
		// char ch;
		// char ch = 'A';
		// char ch = 0;
		// char ch = '\u0000';
		// char ch = 35870;
		// char ch = -90; // 0 ~ 65,535 (유니코드)
		char ch = 'a';
		
		System.out.println("ch : " + ch);
		System.out.println();
		
		// 문자열
		// String name; // 문자열을 가리킬 수 있는 참조 변수를 선언
		// String name = ""; // 큰 따옴표 사용, 빈 문자열로 초기화
		// String name = "홍길동";
		// String name = new String("홍길동");
		String name = null;	// 참조형 변수에만 null 입력 가능
		
		System.out.println("name : " + name);
		System.out.println();
		
		// 지역 변수 생성 후 초기화가 되지 않은 경우 에러가 발생
//		System.out.println(isTrue);
		
		isTrue = false;	// 선언 후 초기화
		// isTrue = 1;	// 에러 발생
		
		System.out.println("isTure : " + isTrue);
		System.out.println();
		
		// bNum = 128; // 에러 발생
		bNum = 127;
		sNum = 32000;
		iNum = 234567991;
		lNum = 92233;
		// long 타입의 리터럴은 숫자 뒤에 L 또는 l을 입력해야 한다.
		// lNum = 922337203785477580; // 에러 발생
		lNum = 922337203785477580L;
		
		System.out.println("bNum : " + bNum);
		System.out.println("sNum : " + sNum);
		System.out.println("iNum : " + iNum);
		System.out.println("lNum : " + lNum);		
		System.out.println();
		
		// float 타입의 리터럴에서 숫자 뒤에 F 또는 f를 입력해야 한다.
		fNum = 3.141592F;
		// dNum = 3.14D; 생략 가능
		dNum = 3.14;
		
		System.out.println("fNum : " + fNum);
		System.out.println("dNum : " + dNum);
		System.out.println();
		
		// 변수의 명명 규칙
		// 1) 대소문자 구분
		int number;
		// String number;	// 자료형이 달라도 변수명이 같으면 에러 발생
		int NUMBER;
		int Number;
		
		// 2) 숫자로 시작하면 안된다.
		// int 1age;
		int age1;
		
		// 특수문자는 _, $만 사용이 가능하다.
		int _age;
		int a_ge_;
		int $age;
		int a$ge;
		// int a%ge;
		// int age*;
		
		// 4) 예약어는 사용할 수 없다.
		// int double;
		// int class;
	}
}

 

A_Varaible 변수 테스트

 

-

 

리터럴

소스 코드에서 프로그래머에 의해 직접 입력된 값

리터럴은 정수, 실수, 문자, 논리, 문자열 리터럴로 구분되며 리터럴들은 정해진 표기법대로 작성해야 한다.

 

-

 

형 변환(Type Casting)

데이터의 타입을 변환하는 것 (boolean 제외)

자료형의 값의 표현 범위 차이에 따라 자동 형 변환, 강제 형 변환으로 나뉜다.

 

자동 형 변환은 컴파일러가 자동으로 값의 범위가 작은 자료형을 값의 범위가 큰 자료형으로 변환한다.

> 데이터 손실 없음. 단, byte와 short 자료형의 계산 결과는 int로 처리한다.

 

강제 형 변환은 값의 표현 범위가 큰 자료형을 작은 자료형으로 강제로 변환한다. > 데이터 손실 발생

 

자동 형 변환, 강제 형 변환 실습을 진행해 보겠다.

	/*
	 *  자동 형 변환
	 *		- 데이터 표현 범위가 작은 자료형을 큰 자료형으로 변환한다.
	 */
	public void autoCasting() {
		byte bNum = 10;
		short sNum = 12;
		int iNum = sNum;	// short -> int 자동 형 변환된다.
		long lNum = iNum;	// int -> long 자동 형 변환된다.
		// float 타입이 long 타입보다 표현 가능한 수의 범위가 더 크기 때문에
		// 자동 형 변환이 가능하다.
		float fNum = lNum;
		double dNum = fNum; 
		
		System.out.println("bNum : " + bNum);
		System.out.println("sNum : " + sNum);
		System.out.println("iNum : " + iNum);
		System.out.println("lNum : " + lNum);
		System.out.println("fNum : " + fNum);
		System.out.println("dNum : " + dNum);
		System.out.println();
		
		char ch = '홍';
		iNum = ch; // 값의 변화가 더 큰 int로 변환됨
		
		System.out.println("ch : " + ch);
		System.out.println("iNum : " +iNum);
		System.out.println();
		
		double result = 12 + 3.3;	// 12.0 + 3.3 = 15.3
		// byte, short 타입의 데이터는 연산 시 무조건 int 타입으로 변환 후 처리된다.
		int result2 = bNum + sNum;
		long result3 = 03 + 30;		// 30 + 30 = 60 60, 60을 long 타입으로 변환 후 대입(60L)
		long result4 = 30 + 30L;	// 30L + 30L = 60L
		
		System.out.println("result : " + result);
		System.out.println("result2 : " + result2);
		System.out.println("result3 : " + result3);
		System.out.println("result4 : " + result4);
		
	}

 

자동 형 변환은 컴파일러가 자동으로 값의 범위가 작은 자료형을 값의 범위가 큰 자료형으로 변환한다.

이 경우에는 데이터 손실이 존재하지 않는다.

 

자동 형 변환 결과

 

아래는 강제 형 변환 예시이다.

 

/*
	 * 강제 형 변환
	 * 		[표현법]
	 * 			(자료향) 데이터;
	 */
	public void casting() {
		
		double dNum = 4.234567893456789;
		float fNum = (float)dNum;	// 자동 형변환이 되려면 d 타입이 f보다 커야함. 왜냐면 자동 형변황은 값이 손실 될 수도 있기 때문에
		int iNum = (int)fNum;
		
		System.out.println("dNum : " + dNum);
		System.out.println("fNum : " + fNum);			
		System.out.println("iNum : " + iNum);
		System.out.println((byte)290);	// 잘못 형 변환을 하면 예상치 못한 값이 나올 수도 있다.
		System.out.println();
		
		int sum = iNum + (int)dNum;
		// 또는 int sum = (int)(iNum + dNum); // 4.0 + 4.234567893456789 = 8
		
		System.out.println("sum : " + sum);
		System.out.println();
	}

 

강제 형 변환은 값의 표현 범위가 큰 자료형을 작은 자료형으로 강제로 변환한다.

이 경우에는 데이터 손실이 발생할 수도 있다.

 

강제 형 변환 결과


 

서식 지정자

%d : 정수형

%f : 실수형

%b : 논리형

%c : 문자형

%s : 문자열

 

escape 문자

\n : 줄 바꿈

\t : 수평 탭

\" : 큰따옴표 출력

\' : 작은따옴표 출력

\\ : 역슬래쉬 출력

 

서식 지정자를 사용하면 정해져 있는 서식에 맞춰서 그 서식에 맞는 값을 줄 바꿈 하지 않고 출력해준다.

아래는 출력 메소드, 서식 지정자, escape 문자에 대한 실습이다.

 

package com.beyond.variable.practice;

public class B_ConsoleOutput {
	public void valuePrint() {
		System.out.print("안녕하세요.");
		System.out.print(12345);
		System.out.print(false);
		
		System.out.println();
		
		// print 메소드와 동일하게 출력하는 메소드로 
		// 출력 후 자동으로 줄바꿈을 해주는 메소드이다.
		System.out.println("안녕하세요.");
		System.out.println(12345);
		System.out.println(false);
		
		System.out.printf("%d\n", 10);
		System.out.printf("%d + %d = %d\n", 10, 20, (10+20));
		System.out.printf("%f\t%f", 3.14, 4.12345555);	// 기본은 소수점 6자리 수까지만 표현됨
		System.out.printf("%.2f\t%.3f\n", 3.14, 4.12345555);
		System.out.printf("%c %s\n", 'a', "\"Hello\"");
	}
}

 

B_ConsoleOutput 결과

 

아래는 간단한 실습 문제이다.

	/* 실습문제
	 * 홍길동 국어 점수 60점, 영어 점수 70점, 수학 점수 66점을 받았다.
	 * 이 학생의 총점과 평균을 출력하세요.
	 * 
	 * 예시)
	 * 국어 점수 : 60점
	 * 영어 점수 : 70점
	 * 수학 점수 : 66점
	 * 
	 * 총점 : 196점
	 * 평균 : 65점
	 */
	
	public void practice() {
		// final int korean = 60; // final이 붙으면 한 번 초기화 된 이후에는 값을 변경할 수 없다.
		int korean = 60;
		int english = 70;
		int math = 66;
		int sum = korean + english + math;
		int ave = (int)(sum / 3);
		// double ave = sum / 3.0;
		
		System.out.println("국어 점수 : " + korean + "점");
		System.out.println("영어 점수 : " + english + "점");
		System.out.println("수학 점수 : " + math + "점");
		System.out.println();
		System.out.println("총점 : " + sum + "점");
		System.out.println("평균 : " + ave + "점");
		
		/*
		 * System.out.printf("국어 점수 : %d점\n", korean);
		 * System.out.pritnf("영어 점수 : %d점\n", english);
		 * System.out.printf("수학 점수 : %d점\n", math);
		 * System.out.printf("총점 : %d점\n", sum);
		 * System.out.printf("평균 : %d점\n", ave);
		 */	
	}

 

위 print문처럼 쓸 수도 있지만, 서식 지정자를 사용하여 코드를 간단하게 표현할 수도 있다.

실습 문제 결과


 

또한, Scanner 클래스를 이용하여 사용자로부터 값을 입력받아 처리하는 클래스도 있다.

Scanner 사용 시에는 java.util.Scanner 를 반드시 import 해주어야 사용이 가능하며,

이것 역시 Ctrl + Shift + O 로 편하게 삽입 가능하다.

 

package com.beyond.variable.practice;

import java.util.Scanner;

public class C_KeyBoardInput {
	public void inputByScanner() {
		// 초기화 
		int age = 0;
		String name = ""; // null도 가능
		float height = 0;
		char gender = '\u0000';
		
		Scanner scanner = new Scanner(System.in);
		
		System.out.println("당신의 이름은 무엇입니까?");
		name = scanner.nextLine();	// 입력한 값이 name으로 넘어감
		
		System.out.println("당신의 나이는 몇 살입니까?");
		age = scanner.nextInt();
		
		System.out.println("당신의 키는 몇 입니까? (소수점 첫 째 자리까지 입력하세요.)");
		height = scanner.nextFloat();
		
		System.out.println("당신의 성별은 무엇입니까? (남/여)");
		// 버퍼 비우기, 버퍼에 남아있는 '엔터'를 빼주기 위해서 scanner.nextLin() 메소드를 한 번 더 호출한다.
		scanner.nextLine();
		gender = scanner.nextLine().charAt(0); 

		System.out.printf("당신의 이름은 %s이고, 나이는 %d세, 키는 %.1fcm, 성별은 %c입니다.", name, age, height, gender);
		
	}
}

 

여기서 우리는 char 자료형으로 값을 받아오는데, nextLine()을 사용하게 되면

nextLine()은 한 글자든지 두 글자든지 String 자료형으로 값을 받아오기 때문에 에러가 발생한다.

 

그래서 우리는 뒤에 charAt(n)을 사용해서 입력한 문자열에서 n번째 문자열을 가져오도록 하여

char 문자형으로 받아온다.

 

만약 성별을 묻는 질문을 키 질문 밑에 놔뒀을 때는 어떻게 될까?

바로 에러가 발생한다.

 

왜냐하면 이유는 다음과 같다.

nextLine은 엔터를 입력하면 버퍼를 비워버린다.

nextInt나 nextFloat 같은 경우는 엔터를 빼고 비운다. (이게 무슨 말이지?)

 

아무튼 그 뒤로 nextLine을 받게 되면 그때 값을 보내버리는데,

엔터가 버퍼에 남아있는 상태라서 아무것도 입력받지 않고 그대로 빈 문자열을 보내버린다.

내용이 없는데 0번 인덱스를 출력하려고 해서 에러가 발생한다.

 

이런 경우에는 그냥 scanner.nextLine()을 한 줄 더 추가해 버퍼에 남아있는 엔터값을 빼준다.

 

Scanner 실습

 

결과를 보면 파란 부분은 다 사용자가 직접 입력한 부분이고,

성별을 '남자'라고 입력하였음에도 불구하고, 

마지막 결과로는 0번째 문자만 가져와서 '남'으로 출력되는 것을 확인할 수 있다.