풀스택과정

풀스택 과정 2주차 - Scanner | 가비지컬렉션 | Short Circuit

바닷가쟤 2025. 4. 14. 17:27

1일차, 2일차로 하기엔.. 주말때문에 날짜 계산이 어려울 것 같다..

2주차 -> 1개월 1주차 뭐 이런식으로 해야 하나..? 


💡 2025.04. 14 수업 이슈

1. Review
2. Scanner 사용법

 

오늘은 ... 나는 자바다 책으로 지난주에 배운 내용을 복습했다.

개념을 완벽히 익히고 넘어가는 것을 중요시 하는 것 같다.

나도 대충 알고 나중에 까먹는 것보단 확실히 잡고 넘어가는게 좋은 것 같다.


Scanner

지금까지 테스트 파일에서는 객체를 생성할 때 인자값으로 실제값을 바로 입력했다.

즉, 컴파일 시점에서 실제값이 입력되었다.

프로그램은 실행할 때마다 서로 다른 값을 받아들일 수 있는 통로를 가져야 한다.

실행 시점에서 값을 받아들이기 위해서는 Scanner를사용할 수 있어야 한다.

우리는 실행할 때 키보드를 통해서 원하는 값을 읽어 들이는 Scanner를 사용할 것이다.

  1. Scanner 객체 생성 = Scanner의 필드와 메소드(멤버)가 메모리에 올라간다.
  2. Scanner의 메소드 사용(호출)
package com.edu.constructor.test;

import java.util.Scanner;

import com.edu.constructor.Shirt;

public class ShirtTest2 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("원하는 셔츠 정보를 키보드로 입력받으세요.");
		System.out.println("셔츠 메이커 입력 ==>");
		String maker = sc.nextLine();
		System.out.println("셔츠 사이즈 입력 ==>");
		int size= sc.nextInt();
		System.out.println("셔츠 긴팔 여부 입력 ==>");
		boolean longSleeved = sc.nextBoolean();
		
		Shirt longT = new Shirt(maker, size , longSleeved);
			
		System.out.println(longT.getDetails());
		
		sc.close();
	}
}

이렇게 할 수 있다.

여기서 문자열은 nextLine(); 이다. (엔터를 기준으로 함)

package com.edu.constructor.test;

import java.util.Scanner;

import com.edu.constructor.Shirt;

public class ShirtTest2 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("원하는 셔츠 정보를 키보드로 입력받으세요.");
		System.out.println("셔츠 메이커, 사이즈, 긴팔여부 입력>>");
		
		String maker = sc.next();
		int size = sc.nextInt();
		boolean longSleeved = sc.nextBoolean();
		
		Shirt longT = new Shirt(maker, size , longSleeved);
			
		System.out.println(longT.getDetails());
		
		sc.close();
	}
}

공백을 기준으로 출력하려면 sc.next();를 써야 한다.

기본형 Primitive Data Type (소문자..예약어..키워드)

소문자라는 것은 클래스가 아니고 멤버(필드, 메서드)가 없다는 뜻이다.

그래서 자바에서 제공하는 Wrapper Class로 변경해줘야 한다.

int → Integer
boolean → Boolean
byte → Byte
short → Short
long → Long
float → Float
double → Double
char → Character

 

 

클래스 이름. 기능(); 빨간색S로되어있는 애들은 이미 메모리에 올라가 있어서 객체를 생성하지 않고 바로 사용할 수 있다.

(원래는 클래스 생성 시 new 클래스로 생성하는데, 이 과정 없이 바로 사용할 수 있다.)

package com.edu.operator.test;

public class OperatorTest {
	int size; // Field V
	// 메모리 힙에 올라감(기본값 있음)
	
	public static void main(String[] args) {
		// local V
		// 메모리 스택에 올라감
		int i;
		int j;
		
		i++; // 기본값을 안가지므로 초기화 하고 사용해야 함
	}
}

Field는 메모리 힙에 올라가고 기본값이 주어진다.

지역변수는 메모리 스택에 올라가서 기본값을 안 가지므로 초기화 하고 사용해야 한다.


Short Circuit

 

|&비트 연산자

true랑 false 모두 비교해서 true인지 false인지를 구별한다.

반면 || , &&논리 연산자

OR연산에서 앞이 true면 바로 true를 반환한다. (실행 속도 빨라짐)

package com.edu.operator.test;

public class OperatorTest {
	int size; // Field V
	// 메모리 힙에 올라감(기본값 있음)
	
	public static void main(String[] args) {
		// local V
		// 메모리 스택에 올라감
		int i = 6;
		int j = 3;
		
		i++;
		
		System.out.println("연산자 = : assign");
		System.out.println("연산자 % : " + i%j);
		System.out.println("연산자 / : " + i / j);
		
		int num = 98;
		
		System.out.println("십의 자리: " + num / 10);
		System.out.println("일의 자리: " + num % 10);
		
		int k = 10;
		System.out.println(++k); // 전위연산자
		System.out.println(k++); // 후위연산자
		System.out.println(k);
		
		// same object? another object ? //
		// o1, o2는 로컬변수, 참조변수이다
		Operator1 o1 = new Operator1();
		Operator1 o2 = new Operator1();
//		Operator1 o2 = null;
		
		System.out.println("Reference Value o1 => " + o1);
		System.out.println("Reference Value o2 => " + o2);
		
		System.out.println("Same Object ==> " + (o1 == o2)); // 다른 객체
		System.out.println("Another Object ==> " + (o1 != o2)); // 다른 객체
		// 주소값이 같으면 Heap에 올라가 있는 같은 객체를 가리킨다.
		// 주소값이 다르면 Heap에 올라가 있는 서로 다른 객체를 가리킨다.
		
		// Short Circuit //
		// 뒷 부분의 논리연산자를 진행시키지 않고 건너뛸 수 있다.
		// 뒷 부분 수행 시 발생할 수 있는 예외 상황을 건너뛸 수 있다.
		System.out.println(o1.test1() | o2.test2()); // true | false = true
		System.out.println(o1.test1() & o2.test2()); // true & false = false
		
		System.out.println("--------------------------");
		// 이게 short circuit이다.
		System.out.println(o1.test1() || o2.test2()); // true || false = true. 앞이 true면 뒷부분 볼 필요 없음
		System.out.println(o1.test2() && o2.test1()); // false && true = false. 앞이 false면 뒷부분 볼 필요 없음
		// 예외를 발생시킬 위험을 건너뛰기 해버림  
		 
		// == , equals //
		System.out.println(o1.equals(o2)); // false ... 주소값 비교하는 함수
		System.out.println(o1 == o2); // false.. 값 비교하는 연산자
		
		System.out.println("msg == " + (o1.msg == o2.msg));
		// String 데이터값을 비교할 때에는 반드시 equals()를 사용, == 연산자 사용하면 안 됨 !!
		System.out.println("msg equals() == " + (o1.msg.equals(o2.msg)));
		/*
		 자바에서 **문자열(String)**은 객체예요.
		== 연산자는 객체의 "참조(주소)"를 비교하고,
		equals()는 객체의 "값(내용)"을 비교합니다.
		 */
	} // main
} // class

class Operator1{
	String msg = "Hello";
	public boolean test1() {
		System.out.println("test1() calling...");
		return true;
	}
	
	public boolean test2() {
		System.out.println("test2() calling...");
		return false;
	}
}

class Operator2{	
	String msg = "Hello";
	public boolean test1() {
		System.out.println("test1() calling...");
		return true;
	}
	
	public boolean test2() {
		System.out.println("test2() calling...");
		return false;
	}
}

여기서 com.edu.constructor는 패키지고 .Programmer 까지 되어있는데,

클래스의 Full name이라고 한다.

FQCN(Full Qualified Class Name)이라고 한다.

@ : at 이라고 생각하면 되는데 그 뒤의 숫자와 문자가 혼합된 문자열은 문자열로 된 주소이다.


class Programmer {
	String name;
	int price;
	NoteBook noteBook;
}

p1 = new Programmer("A", 100);
p2 = new Programmer("B", 200);

 

이렇게 관계가 있는 클래스가 메모리에 올라가는 과정을 그림으로 그려볼 것이다.

String name = new String(”James”);힙에 올라감

String name = “James”;literal Pool(String Pool)에 올라감

 

기본형 타입의 공간 → 실제값이 들어감

클래스 타입의 공간 → 객체를 가리키는 주솟값이 들어감(참조, 참조변수)

 

s1 = s2와 같이 스택 영역으로부터 참조가 끊어지게 되면

기존 s1이 가리키던 객체는 가비지(쓰레기 객체)가 됨.

 

가비지가 많아지면 메모리 공간이 차고 느려진다.(퍼포먼스 , 성능 ⬇)

바로 사라지지는 않고 자동으로 JVM의 판단으로 가비지 컬렉션에 의해 지워짐.

Garbage Collection(GC) ➡ 쓰레드

이 놈이 제거해줌.

  1. 언제 제거할 지 모른다.
  2. 알아서 해준다.

쓰레드는 철저히 우선순위에 의해 동작한다.

static을 남용하면 안되는 이유.. GC의 우선순위에서 많이 밀려나기 때문!


 

오늘 코딩 과제를 하고 그 과제의 일부의 메모리 구조를 그려본 것이다.

728x90