Java/기초 Java

[기초 자바] 자료형과 함수

호두빵 2021. 4. 6. 20:24

<순서에 익숙해지자!>

1. 프로젝트 생성 -> 유형(Java Project, 콘솔환경)

 - 문자 기반의 실행 환경을 만드는 것

 

2. 패키지 설정

 - 디렉토리 생성(구조)

 - 상위폴더. 하위폴더. 그보다 더 하위폴더 and it goes on and on 하면 안 되고 적당히 만드는 것이 중요합니다. 

 

3. 소스 파일 생성

.java ( class를 생성한다는 뜻으로 .을 쓰고 뒤에 파일명을 붙여줍니다. 

** 앞에 점이 붙은 파일은 함부로 건드리지 말고 삭제도 하지 말 것

클래스의 첫 글자는 반드시 대문자로 작성해야 합니다.

숫자는 되도록이면 아예 안 쓰는 것이 좋지만 써야한다면 제일 마지막에 쓰도록합니다. 

 

4. 코드 작성

 

5. 실행 Run As -> Java Application(아무것도 안 줘놓고 실행하라고 하면 이게 무슨? main 함수가 포함되지 않으면 실행이 되지 않습니다. 그래서 우리가 자주 본 public static void main(String[]args)가 있는 것이죠. 또 신기한게 main은 지독하게 잘 알아먹어서 main01, main02는 취급하지 않습니다. 고로 순정 main 함수만 인식합니다.

 - 유형에 따라서 실행 방법에도 차이가 있음

 

Entry point

==엔트리포인트란? 제어가 운영체제에서 컴퓨터 프로그램으로 이동하는 것을 말합니다. 즉 여기서부터는 내가 할게~ 하고 컴퓨터 프로그램이 등장하는 것. 초기 엔트리는 프로그램의 한 부분이 아니라 런타임 라이브러리의 한 부분.(런타임 라이브러리가 프로그램을 초기화하고 프로그램에 진입하는 것) - 프로그램 실행은 프로그래밍 언어나 운영체제 등에 의해 정의된 관용명을 통한 지정된 이름으로 시작될 수 있는데 따라서 엔트리포인트는 main함수라고 불립니다.

**프로그램은 오직 한 개의 엔트리 포인트를 갖습니다. 즉 main 함수는 엔트리포인트이자 프로그램이 실행을 시작하는 곳이라고 할 수 있습니다(위키피디아 참조하였음)

 

<자바 소스를 작성하는 기본 형식>

1. 패키지 정보

패키지 이름은 사이트 이름을 뒤집은 것처럼 표현합니다. 예를 들면 com.naver.www처럼 180도 돌려주는 것이죠.

이는 폴더에 계층구조를 만드는 것으로 패키지 자체가 디렉토리를 만들어 놓은 것이라고 할 수 있습니다. 

 

2. class의 정의

소스 하나에 클래스 하나를 정의합니다(사실 여러개도 가능하지만 원칙적적으로는 하나씩만 정의할 수 있다)

class 중괄호 안에 작성되는 것을 member라고 부릅니다. 

 

**코딩할 때 모든 실행 내용은 class{}안에 적습니다. 

변수 : field (변수의 선언)

함수 : method(함수의 정의)

 

3. public class : 예약어(keyword, 명령하는 것), 임의로 사용할 수 없습니다. 

 

무언가를 출력한다는 것은? 출력하기 -> 기능 -> 함수 찾기 -> 어디로, 무엇을 출력한다...

우리는 모니터로 확인을 하여야하기 때문에 화면에 나타내기 위해서는 System.out.을 씁니다. 

무엇을 어디로 보내야 할까?(참고로 화면에는 문자열만 출력이 가능하다. 사진이나 이런 것은 올릴 수 없음)

만약 내가 "2021 Korea"라는 단어를 띄우고 싶다면 System안에 out이라는 출력장치가 있는데 그 안에 또 println이라는 함수가 있습니다. 앞서 배운바를 토대로 해본다면 System.out.println("2021 Korea"); 를 입력하면 내가 원하는 문구를 출력할 수 있습니다. 앞에 오는 것은 함수명이고 ( ) 안에 들어가는 것은 그 함수에게 줄 값이라고 생각하면 됩니다.

 

여기서 잠깐! 함수를 실행시킬 때 외우고 있어야 하는 것

같은 소스(클래스) 안에 정의되어 있는 함수를 호출(실행)할때는 이름만 적으면 됩니다. 그러나 같은 클래스 안에 있는 함수가 아니라면 호출해온 위치를 적어줘야합니다.(른 클래스 또는 다른 곳에 있는 함수를 호출할 경우)

 

JVM, JRE, JDK는 무슨 뜻일까?

모두 다 J로 시작한다는 공통점이 있지만 Java Virtual Machine, Java Runtime Environment, Java Development Kits로 각각 의미가 다르다(당연하게도). 각자 하는 역할도 다릅니다. 

편집 > 변환>실행의 순서로 이뤄지는데 

HelloWorld.java 소스파일 -> javac.exe -> HelloWorld.class 바이트코드파일 -> java.exe -> Process(JVM)

                                       =compile, 사람이 읽을 수 있는 글로써 작성된 *.java file을

                                         컴파일러를 통해 컴퓨터가 읽을 수 있는 기계어 코드 *.class file로 변환한다.

변환된 *class file은 binary, byte code, class file 등으로 불린다.  

 

<변수선언(); create method>

 

변수 : 값을 저장하는 메모리의 일부분입니다. 변수를 만든다는 것은 변수를 선언한다는 것입니다. ex int num;

기본형 = 소문자로 표현한다(값을 의미함)

char a = 'A' (문자) / int b = 10;(숫자) / double c = 12.34; 소숫점이 있는 실수 

 

byte v2; // 1byte 정수를 쓸 때 사용, 범위가 좁다.
short v3;// 2bytes 거의 쓸 일이 많지는 않다.
int v4;// 4bytes 가장 많이 쓰이는 것 10진수 유효한 최대 자리수가 9자리
long v5;//8bytes 이것도 꽤 많이 쓰임

 

<실수형> 둘 중에 double을 우선해서 사용합니다.
float v6;// 4bytes
double v7; //8bytes

 

무치형 : void

boolean v1; // true, false

 

String s = "string";(문자열)

앞서 나온 것들은 다 소문자로 시작했는데 왜 String만 대문자로 시작하는걸까?

그건 왜냐하면 String 역시 class로 인식하기 때문입니다. 그리고 class는 무조건 뭘로 시작한다고? 대문자!

 

참조형(Reference)

String 하나만 딸랑 참조형인게 아닙니다. String에게는 다른 친구들이 있는데 이들 역시 첫 글자를 대문자로 시작합니다. 그러므로 대문자로 적혀있다면 참조 자료형으로 봅니다. 참조형은 메모리의 주소로 실제적으로 처리할 대상의 정보를 지니고 있습니다. 사실상 기본형을 제외한 나머지 모두가 참조형에 속합니다. 

 

문자처리();

문자와 정수간의 관계를 알아보자!

참고로 아스키코드에서는 문자 하나를 1byte로 보고 유니코드에서는 문자 하나를 2byte 이상으로 봅니다. 

 

System.out.println('A'); -> A
System.out.println(65); -> 65
System.out.println(97); -> 97

 

컴퓨터에게 자료형을 지정해준다면?(변환한다는 뜻임)
System.out.println((int)'A'); -> 65
System.out.println((char)65); -> A
System.out.println((char)97); -> a

 

$영문자는 아스키타입으로 저장할 수 있지만 한국어나 일본어는 char 타입으로 저장해야함
ex. byte ascii = '한';으로 하면 한 밑에 빨간줄이 뜸.
but char unicode = '한'; 이것은 가능함.

 

접두접미();

prefix 접두 - 진법(10진법, 2진법 하는 그 진법이요), suffix 접미 - 자료형(위에 적어놓은 기본 자료형을 다시 살펴보아요)

 

여기서 개인적으로 헷갈렸던 부분

 

int a=10;
int b=10;
int c=10;


System.out.println(a + "," + b + "," + c);  나오는 값은 30이 아니라 10 + 10 + 10이다. 10을 세 번 더했으니까

그러나 순간의 착오로 System.out.println(a + ',' + b + ',' +c)를 하게 되면 갑자기 118이라는 숫자가 등장해 당혹스럽게 만든다. 이것은 왜 그런걸까? 그냥 " " 쓰면 되잖아요 하고 넘어갈수도 있겠으나 또 궁금한 것은 못 참기 때문에 구글링을 해봤습니다. 아스키코드표에서 , 이것은 44라는 숫자를 가집다. 즉 후자로 입력을 하면 10 + 44+ 10 +44 + 10 = 118 나왔네요~^^ 가 되어버리는 것이죠. 여기까지만 읽었을 때 아 왜 그러는지 알겠다 싶은 사람은 나보다 머리가 좋은 것으로 판단이 됩니다. 하지만 나는 그것을 읽고도 충분하게 이해하지 못했기 때문에 왜 이렇게 되는 것인지 알아내기 위해 구글에 검색했고 나와 비슷한 의문을 가진 외국인 학생이 질문을 남겨놓은 것을 확인할 수 있었습니다. 

 

char char1;

char1 = 'a';

1번@System.out.println(char1); // print 1  ->a 

2번@System.out.println(char1 + 1); // print 2 ->98

3번@char1 += 1; System.out.println(char1); // print 3 ->b 

 

1번은 왜 a가 나오는지 나도 이해했습니다. char1를 넣었으니 위에서 정의한대로 a가 뿅 하고 나타나는 것이죠. 그러나 두번째에서 똑같은 이유로 막히게 됩니다. 대체 이 98이라는 숫자는 왜 튀어나온걸까. 2번에서 작성자는 integer addition을 했다고 합니다. 즉 정수를 더한 것이죠. 자바에서 char는 유니코드 character로서 유니코드표에서 a는 97을 나타냅니다. (아스키코드에서도 마찬가지이다.) 그런데 주목해야 할 점은 2번의 괄호 안에 (char1 +1)은 서로 자료형이 다른 것입니다. 잘 모르는 눈치로 봐도 왠지 두 개가 같아야만 할 것 같은데... 이런 경우엔 자바가 눈치껏 알아서 mismatched type임을 파악하고 더 작은 값의 유형을 큰 값의 유형으로 올려줍니다. 뭔 말인지 확실하게 말하기는 어렵지만 어쨌든 문자형인 char는 2bytes이고 int는 4bytes입니다. 여기서 char는 스스로 2bytes 밖에 갖지 못 한 것을 인정하고 알아서 int의 유형으로 붙어들어가야합니다. int 유형으로 바뀌는 것은 performed되기전에 서둘러서 바뀝니다. 그러므로 1번에서는 너무나 자연스럽게  a였던 것이 2번에서는 97 +1 로 바뀌면서 98이라는 값이 출력되게 되는 것이죠.

 

그래 2번까지 어찌어찌 이해했더니 갑자기 3번에서는 b가 튀어나옵니다. 앞서 98이 튀어나왔던 것을 기억하시나요? char1+=1은 풀어쓰면 char1+1=?가 뭘까요 하고 물어보는 것이나 마찬가지입니다. 근데 2번에서 우리는 이미 char1+1이 98임을 눈으로 확인할 수 있었습니다. 근데 마지막 3번에서 (char1)은 98이 되긴 했지만 문자형 char로 인식되기 때문에 98에 대응하는 b가 나오는 것입니다. 

 

누군가의 고민을 통해 내 고민 또한 해결할 수 있었는데 내가 궁금했던 System.out.println(a + ',' + b + ',' +c) 이건 왜 안 되는 걸까요 의 고민이 a,b,c 가 int 유형의 자료형이기 때문에 같이 있던 ','들도 덩달아 신분상승해서 int로 인식이 되게 되는 것입니다. 따라서 118이라는 숫자가 나오는 것이고. 그러나 ","로 적어준다면 String은 적어도 char보다는 사이즈가 크기 때문에 int에게 밀리지 않는 것이고 그래서 모습을 온전히 유지할 수 있어 10,10,10이라는 결과값을 보여줍니다. String의 사이즈를 계산하는 것은 20+(2*length)라고 합니다. 2 bytes per character이므로 2bytes니까 char랑 쌤쌤 아니야 하지만 최소 20을 더해져서 char와 String에는 큰 차이가 있다고 볼 수 있겠네요.

 

int a =10; //10진법
int b=010; //8진법
int c =0x10; //16진법
=> 결과값은 10,8,16(화면에 출력할때는 10진법으로 나온다.)

 

>진법을 있는 고대로 보여주고 싶을 때에는? - 출력하는 대상이 바뀌는 것
각 진법 표현으로 출력하기

System.out.println(b);
-> System.out.println(Integer.toOctalString(b));

앞에 to가 붙어있는 것은 대부분 변환하는 함수임. ex. Integer.toOctalString(b)

 

접미 -> long number = 100l;
float number = 10.12f;

 

연산자 : 명령을 의미하는 기호

구분 결과
산술 값(정수, 실수)
관계 논리 값간의 크기 비교 ~이면
논리 논리 논리(boolean)간의 조합
비트 정수 출력(10진 정수)
복합대입 대입연산자 다른 연산자와 합쳐서 사용한다.


증감연산
조건연산

 

표현식 -> 하나 이상의 연산자를 사용한 문장
문 -> 식을 여러 개로 묶음{ }
함수 -> 문으로 구성된 실행 단위
프로그램 -> 함수들로 구성된 실행 파일

 

항(operand) 
단항 > 다항(단항이 다항보다 우선한다.)

 

산술연산{}

연산의 결과 값을 나타내는 것입니다. (+-*/%)

 

%로 나누고 남은 R%m의 결과는 무조건 m보다 작은 값이 나오게 됩니다. 

따라서 낮은 자리를 없애고 싶을 때에는 System.out.println(123/10);을 하지만 반대로 높은 자리를 없애고 싶을 때에는 System.out.println(123%10);을 하면 됩니다. 

*산술연산자를 잘 활용하면 범위를 조절할 수 있어서 잘 알아두는 것이 좋다. 

 

관계연산{}

결과는 논리형으로 나옵니다.

ex. System.out.println(3<=5? true : false) [=이거는 항상 부등호의 오른쪽에 적어준다)

 

연산자들간의 우선순위가 있음. (산관논)
산술연산자가 짱이고 그 다음이 관계연산자 그리고 마지막이 논리연산자입니다.

(@@관계연산자, 논리연산자의 결과는 boolean이다)

 

$$ 안에 괄호 하나 더 씌우는 건 상관없는데 자료형이 달라질 경우 에러나니까 자료형을 잘 맞춰줘야합니다.
ex. System.out.println((3<5)-7); 이런거는 안된다.

$$ 일정하게 수가 증감될때 연속된다고 한다. 33333이런 식으로 같은 숫자가 계속 나오는 것은 나열임

 

논리연산{}

 

A라는 조건과 B라는 조건이 있을 때 (조건이 나온다? boolean) 4가지의 결과가 나올 수 있습니다.

A B @@NOT(B) AND OR XOR
T T           F       T    T     F
F F           T       F    F     F
T F                   F    T     T
F T                   F    T     T

 

**XOR 연산자는 비트연산자고 나머지는 논리연산자에 해당됩니다.
3개의 조건이 주어진다. 서로 다르다는게 성립하는가 -> @@성립하지 않는다. 3개 이상일 경우 반드시 같은 것이 있을수밖에 없음

 

ex. boolean isOpen = true;
boolean isLock = true;
System.out.println(isOpen&&isLock);  =>true
System.out.println(isOpen||isLock);  =>true
System.out.println(!isOpen); => false

 

random숫자();
숫자? '0'~'9' 임의로 하나를 골라 출력하세요


char letter;
letter = '0' + r; 왜 0을 더해줄까요?
System.out.println(letter);

char letter;
double r = Math.random();
int n = (int)((r*10)+48); //'0' == 48
System.out.println(n); // r*10 값이 0에서 9까지로 정해지기 때문에 48~57까지 범위에 해당하는 숫자를 뽑아낼 수 있음.
int n = (int)((r*10) + '0');

 

화면에 문자를 출력하기
score 변수에 저장된 값이 50이상이면 "Up" 반대라면 "Down"
int score = 70;
조건에 따라서 둘 중에 하나를 선택하는 연산자를 활용한다 : 조건연산자
(score >=50)? "Up" : "Down");

-----------------------------------

학점 출력하기 : 조건연산자 연습하기

 

int score = 47;
char grade =
(score>=90) ? 'A':
(score>=70) ? 'B' :
(score>=60) ? 'C' :
(score>=50) ? 'D' : 'F';
System.out.println(grade);

 

하나의 정수를 각 자리로 쪼개기(3자리의 정수)

int number = 123;
int 백 = number/100;
int 십 = number/10%10; @@
int 일 = number%10;
System.out.println(일);

 

123을 231로 만들기
number = (십*100)+(일*10)+백;
System.out.println(number);

 

위에서 곱하고 더하고 지지고 볶고 하지 않고 함수를 이용해서 만들어보면 어떨까? 

 

함수를 이용하기 : 라이브러리 외워두기


1. 정수를 숫자열로 바꾼다. 문자열 속에 문자들을 번호로 지정할 수 있습니다.
[0]번부터 차례대로 번호가 지정됩니다.

int num = 123;
String str = "" + num;//앞에 ""을 더해주면 문자열로 바뀌기 때문에 "123"이 되는데 각각의 문자에  0번부터 1번 2번 배정이 됩니다. 즉 0번은 1이고 1번은 2, 마지막 2번은 3입니다.  

String s = ""+str.charAt(1)//2
+str.charAt(2)//3
+str.charAt(0);//1
num = Integer.parseInt(s); // 문자열을 다시 정수로 바꿔줍니다.
System.out.println(num);

 

----------------------------

각자리에 중복이 없는 3자리의 임의 정수를 하나 출력합니다. ex. 333(안돼~!)

 

내가 얼렁뚱땅했던것

/**
* double s = Math.random();
* int n = (int)(s*1000);
System.out.println(n);
String str = "" + n;
System.out.println(n);
str = (str.charAt(0)!=str.charAt(1))?
*/


선생님이 알려준 버전
int min = 100;
int max = 999;
int num = (int)(Math.random()*10000);
num = num %(max+1-min);
System.out.println(num);//0~899
num = num %(900)+min;
System.out.println(num);//100~999

int 백 = num/100;
int 십 = num%100/10; //백의 자리를 버리고 십의 자리값을 먹는다
int 일 = num%10;
boolean duplicate = 백!=십 && 십!=일 && 백!=일;
System.out.println((duplicate)? num : "");