1. 프로세스

1) 프로그램 실행 시

① 디스크에 저장된 프로그램을 커널이 메모리에 올린다.

② 메모리에 올라간 프로그램을 CPU가 실행한다.

 

2) 프로세스 

→ 메모리 위에 올라가서 실행 중인 프로그램, 각각 pid라는 고유 번호를 할당받아 관리

 

 

2. ps 명령어 

1) $ ps : 프로세스 조회

bash는 실행하자마자 열리고, ps는 ps를 입력하여 추가된 것으로 각각 고유의 PID가 배정되는 것을 확인할 수 있다.

위와 같이 특정 명령이 실행되면 프로세스로 전환되고, 실행이 끝나면 프로세스 목록에서 사라진다.

 

2) $ ps x : 백그라운드에서 돌아가는 프로세스 조회

※ 데몬 프로세스 : 터미널과 무관하게 돌아가는 프로세스 → 항상 켜져 있어야 하는 속성의 프로세스

 

3) $ ps a : 시스템의 모든 프로세스 조회

위와 같이 시스템 내부에서 동작 중인 모든 프로세스를 조회할 수 있고, 조회된 PID를 이용해 여러가지 작업을 할 수 있다.

 

4) ps 옵션 : "-"를 쓰지 않는다.

x 사용자의 프로세스 전체 출력
ux 사용자의 프로세스 상세히 출력
ax  모든 사용자의 프로세스 출력
aux 모든 사용자의 프로세스를 상세히 출력
auxww aux 결과가 화면에 잘리지 않도록 출력

 

5) $ ps ux | less : 모든 프로세스를 페이지별로 출력 (종료:q)

 

6) $ top : 메모리 구조 살펴보기

위와 같이 메모리 사용량 등을 실시간으로 보여준다.

 

※ 참고

- VIRT : 가상 할당량 → RES의 최대치

- RES : 실질 할당량

- SHR : 공유 메모리 영역

 

 

3. 잡

1) 잡 (job)

- 프로세스 : 커널 입장에서 실행

- 잡 : 셸에서 실행하고 있는 단위

위와 같이 man bash를 ctrl+z로 강제종료시켰을 때 job이 하나 생성된 것을 확인할 수 있다.

실행 중인 프로그램이 종료되면 프로세스 목록에서 사라지기 때문에 잡에서는 확인할 수 없다.

 

잡 목록에서 PID를 조회하고자 할 때 -l 옵션을 사용한다.

 

2) $ fg : 잡의 포그라운드 전환

foreground : 사용자의 입력을 받을 수 있는 상태

→ 정지 상태에 있는 bash 메뉴얼을 다시 확인하기 위해서는 포그라운드로 되돌려야 함

위와 같이 fg %번호 명령어를 이용하여 포그라운드로 전환할 수 있고, 잡이 하나인 경우에는 fg만 입력해도 된다.

 

3) $ bg : 잡의 백그라운드 전환

background : 잡을 종료하지 않은 채 셸로 전환

위와 같이 포그라운드 상태에서는 sleep이 끝날 때까지 아무것도 하지 못한다.

백그라운드 상태에서는 sleep이 끝나지 않고도 제어권을 되찾아오고, 잡은 백그라운드에서 60초를 수행할 때까지 돌아가는 병렬적인 작업을 수행하게 된다.

포그라운드와 마찬가지로 bg %번호 명령어를 이용하여 백그라운드로 전환할 수 있고, 잡이 하나인 경우에는 bg만 입력해도 된다.

 

4) 잡과 프로세스의 종료

① 잡의 종료 

- 포그라운드 : ctrl + c

- 백그라운드 : kill %잡번호

위와 같이 kill 명령어를 이용하여 백그라운드에 있는 잡을 종료시킬 수 있다.

 

② 프로세스의 종료 : kill PID번호

위와 같이 kill PID번호 명령어를 입력하여 프로세스를 종료할 수 있다.

프로세스는 현재 로그인중인 유저가 실행한 프로세스만 삭제할 수 있고, 루트 계정만 다른 사용자의 프로세스를 강제로 종료할 수 있다.

 

5) kill : 프로세스에 특정한 신호를 보내는 명령어

SIGHUP, 1 터미널 제어 시 또는 제어 프로세스 종료 시 감지
SIGUNT, 2 키보드에서 보내는 인터럽트 신호
SIGQUIT, 3  키보드에서 보낸 종료 신호
SIGABRT, 6 abort(3)로 받은 신호 무시
SIGKILL, 9 kill 신호
SIGTERM, 15 중단 신호
SIGCONT, 19, 18, 25 중지된 프로세스 재개
SIGSTOP, 17, 19, 23 프로세스 중지

 

ex) PID가 10023인 프로세스를 중지시킬 경우

$ kill 10023

$ kill -9 10023

$ kill -SIGKILL 10023

위와 같이 해당 프로세스가 잘 종료된 것을 확인할 수 있다.

 

6) killall : 프로세스명으로 종료시키는 명령어

$ killall -9 프로세스명

위와 같이 killall 명령어를 이용하면 특정 pid가 아닌 같은 이름을 가진 모든 프로세스를 동시에 종료할 수 있다.

'네트워크캠퍼스 > LINUX' 카테고리의 다른 글

Shell Script  (0) 2024.01.17
Devops와 SE를 위한 리눅스 커널 이야기  (0) 2024.01.17
텍스트에디터  (0) 2024.01.15
파일시스템  (0) 2024.01.11
프롬프트  (0) 2024.01.10

1. abstract 키워드

- 클래스와 메서드에 적용

- 추상 클래스는 실제 클래스들의 멤버변수와 메서드들의 이름을 통일할 목적으로 사용

- 추상 메서드가 있는 클래스는 반드시 추상 클래스여야 함

- 추상클래스에 반드시 추상 메서드만 선언할 필요는 없고 일반 메서드도 선언할 수 있음

 

- abstract 키워드를 사용하지 않았을 때 문제가 되는 예시

public class PopupStore {
	public void orderApple() {
		System.out.println("착즙 사과주스를 내줍니다.");
	}
	
	public void orderOrange() {
		System.out.println("착즙 오렌지주스를 내줍니다.");
	}
	
	public void orderGrape() {
		System.out.println("착즙 포도주스를 내줍니다.");
	}
}
public class Store extends PopupStore{
	
	@Override
	public void orderApple() {
		System.out.println("착즙 사과주스를 팝니다. 가격은 20000원");
	}
	
	@Override
	public void orderOrange() {
		System.out.println("착즙 오렌지주스를 팝니다. 가격은 24000원");
	}

	// 실수로 포도주스 가격 업데이트를 누락
}
public class MainClass {
	public static void main(String[] args) {
		// 2가지 문제점 체크
		// 1. 정식매장이 존재하는데 팝업스토어 생성 가능
		PopupStore ps = new PopupStore();
		
		// 2. 팝업스토어 클래스 내부에서 오버라이딩이 필수인 메서드가 누락될 수도 있음
		PopupStore s = new Store();
		s.orderApple();
		s.orderOrange();
		s.orderGrape();
	}
}

위 예시와 같이 abstract 키워드를 이용하지 않았을 때 위의 2가지 문제점이 발생할 수 있다.

포도주스를 오버라이딩 하지 않으면 경고를 띄우게 해야 하지 않을까? → 추상화 적용

PopupStore(부모타입)으로 Store(자식) 객체 형변환이 이루어짐

부모타입으로 선언한 객체에서도 자식이 오버라이딩했던 함수의 내용이 출력되는 것을 확인할 수 있다. (Promotion-자동형변환)

 

1) abstract class

- new 키워드를 이용하여 객체 생성 불가

- 오직 상속을 통해서 자식클래스로 구체화 시켜야 함

- new를 사용하여 직접 생성자를 호출할 수는 없지만 자식 객체가 생성될 때 super()를 호출하여 추상 클래스 객체를 생성하므로 추상 클래스도 생성자가 반드시 있어야 함

- 추상 메서드를 하나 이상 보유하고 있다면 해당 클래스는 추상 클래스 → 무조건 abstract 키워드를 붙여줘야 함

 

2) abstract method

- 추상 클래스 내에서만 선언 가능

- 추상 메서드는 메서드의 선언부만 있고, 메서드 실행 내용이 들어가는 중괄호 {}가 없는 메서드를 말함

- 추상 클래스 설계 시 자식 클래스가 반드시 실행 내용을 채우도록 강요하고 싶은 메서드가 있을 경우 해당 메서드를 추상 메서드로 선언

- 자식 클래스에서 반드시 부모 추상 클래스의 추상 메서드를 재정의하여 실행 내용을 작성해야 함

 

3) abstract 사용 예제

public abstract class PopupStore {
	// 1. 메서드에 abstract를 붙이면 해당 메서드는 추상메서드가 되고, 이 메서드는 반드시 오버라이딩 해야 함
	// 2. 추상메서드는 상속을 목적으로 선언한 메서드
	//    실행을 목적으로 선언된 메서드가 아니므로 메서드의 몸체({}) 부분이 없고 선언 마무리도 ;로 함
	// 3. 일반 클래스에는 추상 메서드 선언 불가
	//    추상메서드가 하나 이상 존재하면 무조건 추상클래스로 선언
	// 4. 추상클래스 내부에서는 추상메서드가 하나 이상 존재한다면 일반메서드 선언도 여전히 가능
	public abstract void orderApple();
	public abstract void orderOrange();
	public abstract void orderGrape();
	
	public void refund() {
		System.out.println("제품에 문제가 있어서 환불합니다.");
	}
}
public class Store extends PopupStore {
	@Override
	public void orderApple() {
		System.out.println("착즙 사과주스를 20000원에 팝니다.");
	}

	@Override
	public void orderOrange() {
		System.out.println("착즙 오렌지주스 24000원에 팝니다.");
	}

	@Override
	public void orderGrape() {
		System.out.println("가격은 못 정했습니다.");
	}
}
public class ConvenientStore extends PopupStore {
	@Override
	public void orderApple() {
		System.out.println("가당 사과주스 4000에 팝니다.");
	}

	@Override
	public void orderOrange() {
		System.out.println("가당 오렌지주스 5000에 팝니다.");
	}

	@Override
	public void orderGrape() {
		System.out.println("가당 포도주스 3500에 팝니다.");
	}
}
public class MainClass {

	public static void main(String[] args) {
		// PopupStore 클래스는 직접 객체 생성 불가능
		// PopupStore ps = new PopupStore();
		
		// PopupStore s = new Store();
		PopupStore s = new ConvenientStore();
		// 객체 종류에 따라 실행구문이 다르게 정의되었지만 명세는 같은 메서드
		s.orderApple();
		s.orderOrange();
		s.orderGrape();
		
		// 어떤 객체가 와도 공통적으로 실행되는 메서드
		s.refund();
	}
}

 

 

※ 템플릿 메서드 패턴 활용

public abstract class Lottery {
	// 템플릿 메서드 패턴은 큰 틀에서 호출구문은 구현메서드(실행문이 있는 메서드)로 정의해놓고
	// 구현메서드가 호출하는 추상메서드들은 상속 후에 특징을 정하도록 만들어서
	// 호출 순서는 그대로 가져갈 수 있도록 하되, 사용자가 특징만 정의하도록 하는 디자인 패턴
	
	// 구현메서드는 큰 틀은 같지만, 세부사항이 달라질 수 있는 내용을 먼저 작성
	public void lotteryCycle() {
		// 1. 어디서 사는가?
		buyLottery();
		// 2. 당첨 여부 확인
		checkWinLottery();
		// 3. 당첨 시 수령
		getLotteryMoney();
	}
	
	// 세부사항은 상속받은 주체가 무엇인지에 따라 다르게 정의할 수 있도록
	// 추상메서드만 정의해놓고, 추가적인 작업은 하지 않음
	abstract void buyLottery();
	abstract void checkWinLottery();
	abstract void getLotteryMoney();
}
public class KoreanLotto extends Lottery {
	@Override
	public void buyLottery() {
		System.out.println("한 게임에 천원짜리 로또를 삽니다.");
	}

	@Override
	public void checkWinLottery() {
		System.out.println("45C6의 확률을 뚫고 1등에 당첨되었습니다.");
	}

	@Override
	public void getLotteryMoney() {
		System.out.println("1등 상금으로 대략 수십억을 받았습니다.");
	}
}
public class StatesSuperball extends Lottery {
	@Override
	public void buyLottery() {
		System.out.println("미국 가서 슈퍼볼 복권을 삽니다.");
	}

	@Override
	public void checkWinLottery() {
		System.out.println("69C5 * 26C1 분의 1의 확률로 당첨되었습니다.");
	}

	@Override
	public void getLotteryMoney() {
		System.out.println("당첨 금액은 최소 수천억원입니다.");
	}
}
public class MainClass {
	public static void main(String[] args) {
		//Lottery lottery = new KoreanLotto();
		Lottery lottery = new StatesSuperball();
		lottery.lotteryCycle();
	}
}

'네트워크캠퍼스 > JAVA' 카테고리의 다른 글

예외처리  (0) 2024.01.17
인터페이스  (0) 2024.01.16
final  (0) 2024.01.15
싱글톤 패턴  (0) 2024.01.15
사용제한자  (0) 2024.01.12

1. final 키워드

- 클래스, 메서드, 변수에 적용

- abstract와 동시에 사용 불가

- 상속 및 재정의 불가, 즉 서브클래스를 가질 수 없음

- final 변수 값 변경 불가

 

1) final class

- 클래스 선언 시 final을 사용하면 그 클래스는 상속 불가능

- 자식클래스를 가질 수 없고, 오직 외부에서 객체 생성을 통해서만 사용 가능

- final 클래스의 대표적인 예가 String 클래스

  → 사용자가 임의로 String 클래스를 상속받아 메서드를 재정의하는 것을 방지하기 위함

위와 같이 final 키워드를 가진 클래스는 상속이 불가하다는 것을 확인할 수 있다.

 

2) final method

- 메서드 선언 시 final을 사용하면 그 메서드는 상속 시 오버라이딩 불가

- 원본 메서드를 변형할 수 없도록 하기 위함

- 호출은 가능

위와 같이 상속은 가능하지만 final 키워드가 붙은 method2는 자식 측에서 재정의할 수 없는 것을 확인할 수 있다.

 

3) final 변수

- 한 번 값을 할당하면 그 값을 변경할 수 없음

- 선언 시 초기화하는 방법과 생성자를 통하여 초기화하는 방법이 있는데, 초기화하지 않고 남겨두면 컴파일 에러 발생

public class Person {
	// final 변수는 단 한 번 초기화될 수 있고 이후에는 변경이 불가능함
	// 선언 시에 아예 직접 초기화를 해주거나 생성자에서 초기화를 해줘야 함
	public final String nationality = "대한민국"; // 선언부 초기화
	public final String name; // 이렇게 선언부에서 초기화를 안하면 생성자 초기화
	public int age; // final이 안 붙은 멤버변수는 초기화 의무 X
	
	public Person(String name) {
		this.name = name;
	}
}
public class MainClass {

	public static void main(String[] args) {
		Person kim = new Person("김자바");
		//kim.nationality = "일본"; // final 변수 변경 불가
		//kim.name = "채자바";       // final 변수 변경 불가
		kim.age = 25;
		
		System.out.println("국적: " + kim.nationality); // public이므로 호출 가능
		System.out.println("이름: " + kim.name); // public이므로 호출 가능
		System.out.println("나이: " + kim.age); // public이므로 호출 가능
	}
}

위와 같이 final 키워드로 가장 처음 생성했던 값이 출력되는 것을 확인할 수 있다.

즉, final 키워드를 이용하여 변수를 생성하면 변수의 값은 변경할 수 없지만 호출하는 것에는 문제가 없다.

 

- final 배열 예시

public class Collector {
	// 참조형 변수를 가진 경우 변수 자체의 주는 final이지만,
	// 참조형 변수의 내부자료까지 바뀌지 않음을 보장하지 않음
	public final String[] stickers = {"피카츄", "꼬부기", "미뇽"};
}
import java.util.Arrays;

public class MainClass2 {
	public static void main(String[] args) {
		Collector c1 = new Collector();
		System.out.println(Arrays.toString(c1.stickers));
		
		c1.stickers[0] = "파이리";
		System.out.println(Arrays.toString(c1.stickers));
	}
}

final 키워드로 생성한 c1 객체는 해당 배열이 있는 주소를 변경하는 것이 불가능할 뿐이고,

해당 배열이 가리키고 있는 참조형 변수의 내부자료까지는 변경 방지를 보장해주지 않는다.

따라서 위와 같이 배열 내부 요소가 변경된 값이 오류 없이 출력되는 것을 확인할 수 있다.

 

4) 상수(static final)

- 상수 : 불변의 값을 저장하는 필드

- 상수는 객체마다 저장할 필요가 없는 공용성을 가져야 하고,

  여러가지 값으로 초기화될 수 없기 때문에 static과 final 제한자를 동시에 붙여 선언해야 함

- 상수 이름은 모두 대문자로 작성하는 것이 관례, 연결된 단어라면 "_"로 연결

// 상수를 선언할 때는 상수 집합을 만드는 목적으로 아래와 같이 클래스 선언
public class CountrySizes {
	// 상수는 보통 public으로 풀고 사용 (값 변경이 불가능하고, 공용성을 띔)
	public final static int KOREA_SIZE = 100431;
	public final static int STATES_SIZE = 9833519;
	public final static int THAILAND_SIZE = 513120;
}
public class MainClass {
	public static void main(String[] args) {
		// 상수만 모아둔 클래스 특성 상 클래스명이 곧 집합을 대표하는 이름이 됨
		System.out.println(CountrySizes.KOREA_SIZE);
		System.out.println(CountrySizes.STATES_SIZE);
		System.out.println(CountrySizes.THAILAND_SIZE);
	
		// 이를 잘 사용하는 예시는 자바의 Math 클래스가 있음
		System.out.println(Math.PI);
		System.out.println(Math.E);
	}
}

위와 같이 잘 출력되는 것을 확인할 수 있다.

'네트워크캠퍼스 > JAVA' 카테고리의 다른 글

인터페이스  (0) 2024.01.16
추상화  (0) 2024.01.15
싱글톤 패턴  (0) 2024.01.15
사용제한자  (0) 2024.01.12
매개변수의 다형성  (0) 2024.01.11

1. 싱글톤 패턴(Singleton Pattern)

- 어떤 클래스의 객체는 오직 하나임을 보장 → 전역의 개념으로 객체 사용

- 객체의 생성을 제한하기 위해 사용

 

public class Singleton {
	// 싱글턴 패턴 - 객체를 1개만 만들어 유지하기 위한 디자인 패턴
	// 1. 외부에서 생성자를 사용할 수 없도록 생성자에 private을 붙임
	private Singleton() {}
	
	// 2. 자신의 클래스 내부에서 스스로의 객체 1개 생성
	// 이때 멤버변수는 힙에 할당된 객체 없이 쓸 수 있도록 static
	private static Singleton instance;
	
	static {
		instance = new Singleton();
	}
	
	// 3. 외부에서 이 클래스의 객체를 필요로 하는 경우
	// 2번에서 static으로 생성된 객체의 주소를 return
	public static Singleton getInstance() {
		if(instance == null) {
			instance = new Singleton();
		}
		return instance;
	}
}

private 접근 제한자는 외부에서 접근할 수 없어 원래는 new 키워드를 이용한 객체 생성이 불가능하다.

이 때 위와 같이 static 키워드를 이용하여 singleton 타입의 객체를 생성할 수 있다.

public class MainClass {
	public static void main(String[] args) {
		// Singleton 객체는 생성자가 private이므로 인스턴스 생성 불가
		// new 키워드로 객체 생성 및 조회가 불가능
		// Singleton s1 = new Singleton();

		Singleton s1 = Singleton.getInstance();
		System.out.println("s1의 레퍼런스 : " + s1);
		
		Singleton s2 = Singleton.getInstance();
		System.out.println("s2의 레퍼런스 : " + s2);
	}
}

위와 같이 Singleton 타입을 이용하여 객체를 생성할 수 있고, s1과 s2 모두 같은 주소를 참조하고 있는 것을 확인할 수 있다.

위와 같이 단 하나의 객체만을 생성해야 할 필요가 있을 때 Singleton 패턴을 이용한다.

'네트워크캠퍼스 > JAVA' 카테고리의 다른 글

추상화  (0) 2024.01.15
final  (0) 2024.01.15
사용제한자  (0) 2024.01.12
매개변수의 다형성  (0) 2024.01.11
배열의 다형성  (0) 2024.01.10

1. vim 에디터

1) 파일 열기 및 신규 파일 작성과 저장

$ vim [파일명] → :w 저장

$ vim 한 경우 → :w [파일명]으로 저장

:wq or ZZ → 저장 및 종료

:wq! → 강제 저장 후 종료

 

2) 파일 편집

① 커서 이동 : 왼쪽(h), 위(k), 오른쪽(l), 아래(j)

② 문자 삭제 : x

③ 입력모드 : i, a

④ 커서의 빠른 이동

- 단어 단위로 이동

w 다음 단어의 첫 글자로 이동
b 이전 단어로 이동

 

- 왼쪽, 오른쪽 끝으로 이동

0 가장 왼쪽으로 이동
$ 가장 오른쪽으로 이동

 

- 행 번호로 이동

[숫자]G 숫자번째 줄로 이동
gg 문서의 첫 번째 줄로 이동
G 문서의 마지막 줄로 이동

 

- 페이지 넘기기

ctrl + f 한 번에 한 페이지 넘기기
ctrl + b 한 번에 이전 페이지로 넘기기
ctrl + d 한 번에 1.5페이지씩 넘기기
ctrl + u 한 번에 이전 1.5페이지로 넘기기

 

- 삭제 : x, d

dd 해당 줄 삭제
d$ 해당 줄 내의 문자만 삭제
d0 현재 행부터 시작지점까지 삭제
x, dl 문자 하나 삭제
dw 단어 하나 삭제
dgg 현재 위치에서 시작지점까지 삭제
dG 현재 위치에서 마지막 지점까지 삭제

 

- 붙여넣기 : p

d로 직전에 지운 텍스트는 p를 눌러 다시 붙여넣을 수 있음

 

- 복사 : y

yy 해당 줄 복사
y$ 해당 줄 내의 문자만 복사
y0 현재 행부터 시작지점까지 복사
y, yl 문자 하나 복사
yw 단어 하나 복사
ydgg 현재 위치에서 시작지점까지 복사
yG 현재 위치에서 마지막 지점까지 복사

 

- 이외 조작방법

J 개행문자 삭제
U 이전 동작 취소 (ctrl + z 기능)
ctrl + r 취소 동작 복구

 

- 검색 

/ 내용 enter 아래 방향으로 검색
? 내용 enter 위 방향으로 검색
다음 내용으로 이동
N 이전 내용으로 이동

 

- 치환 : :%s/찾을문자/바꿀문자/g (모두 찾아바꾸기 기능)

 

- 공식문서 찾아보기

$ vimtutor : 튜토리얼 이용해 기본동작 연습

:help : 도움말 확인

'네트워크캠퍼스 > LINUX' 카테고리의 다른 글

Devops와 SE를 위한 리눅스 커널 이야기  (0) 2024.01.17
프로세스  (0) 2024.01.16
파일시스템  (0) 2024.01.11
프롬프트  (0) 2024.01.10
Shell  (0) 2024.01.09

1. .gitingore 파일

→ git으로 저장소를 관리할 때 필요 없는 파일들(개인적 설정을 위한 파일 등)에 대해 업로드를 원천적으로 막도록 세팅하는 파일

 

먼저, .gitignore.txt 파일을 생성해준다.

 

위와 같이 metadata를 추가해주고 txt 확장자를 없애준다.

 

add와 commit을 진행하면 .gitignore에 작성된 파일명이나 폴더명에 해당하는 것들은 대상에서 제외된다.

즉, .metadata 폴더를 제외한 내용들만 안전하게 업로드할 수 있게 된다.

 

 

'네트워크캠퍼스 > GIT, GITHUB' 카테고리의 다른 글

풀 리퀘스트  (0) 2024.02.20
Github CLI  (0) 2024.01.31
  (0) 2024.01.12
클론  (0) 2024.01.11
로컬 저장소 내역 깃허브 업로드  (0) 2024.01.10

1. pull

→ 원격 저장소의 버전이 로컬 저장소의 버전보다 앞서는 경우 원격 저장소의 갱신 내역을 로컬 저장소에 반영해주는 것

 

1) 소스트리에서 pull

 

먼저, 해당 경로에 파일을 생성한다.

 

다운받고자 하는 주소 복사

 

위와 같이 클론해주면 커밋 내역까지 잘 불러온 것을 확인할 수 있다.

 

해당 파일 생성해주고

 

add와 commit을 진행해준다.

 

위와 같이 푸시해준 후

 

깃허브 확인 시 위와 같이 잘 추가된 것을 확인할 수 있다.

 

git_sourcetree 로컬 저장소에서 원격저장소(깃허브)를 이용하여 pull을 진행한다.

 

해당 폴더를 확인해보면 위와 같이 회사에서 작업한 코드가 추가된 것을 확인할 수 있다.

 

※ 즉, clone은 최초 한 번만 실행해준 후 pull을 이용하여 여러 PC에서 같은 버전의 코드를 유지할 수 있다.

 

2) CLI에서 pull

마찬가지로 먼저 pc2_git_cli 폴더를 생성해준다.

 

깃허브에서 클론할 주소 복사 후

 

위와 같이 클론을 진행한다. (주소 뒤에 . 붙여주는 거 잊지 말기!)

 

이와 같이 잘 추가되어 있는 것을 확인할 수 있다.

 

새로운 파일 생성 후

 

이와 같이 add, commit, push를 차례대로 수행해주면

 

깃허브에도 해당 파일이 잘 추가되어 있는 것을 확인할 수 있다.

 

다시 git_cli 저장소에서 pull 명령어를 수행해주면

 

마찬가지로 해당 파일이 추가된 것을 볼 수 있고, 두 대의 PC가 같은 환경이 되었다고 할 수 있다.

'네트워크캠퍼스 > GIT, GITHUB' 카테고리의 다른 글

Github CLI  (0) 2024.01.31
.gitignore 파일의 필요성  (0) 2024.01.12
클론  (0) 2024.01.11
로컬 저장소 내역 깃허브 업로드  (0) 2024.01.10
병합  (0) 2024.01.05

1. 사용제한자(Usage Level modifier)

1) static

- 변수, 메서드에 적용되는 자바의 키워드

- 해당 클래스의 객체 없이도 참조 가능

- static 블록 안에는 static 변수만 사용해야 하고, static 메서드만 호출가능

- 지정된 변수와 메서드를 객체와 무관하게 만들어주기 때문에 this를 가질 수 없음

- non-static 메서드로 재정의될 수 엇음

- 대표적인 static 메서드는 main() 메서드

- static에 단순히 블록({})을 사용한 경우에는 정적 초기화자라고 부름

  → static 변수를 초기화하는 역할을 가지고 클래스가 로딩될 때 main() 메서드가 있더라도 앞서 딱 한 번 실행

 

2) 정적 변수 (static field)

- 모든 객체들이 공유하는 공유 변수

- 객체 생성 없이 클래스 이름만으로 참조 가능

- 객체를 만들어 참조할 수도 있지만 객체를 만들지 않고도 참조가 가능하기 때문에 이를 클래스 변수라고도 부름

public class Asean {
	// 출석 20, 발표 30, 기말 50
	public String name; 
	private int attendanceScore; // 출결점수
	private int finalTermScore;   // 기말점수

	public static int presentationScore; // 29
	
	public Asean(String name, int attendanceScore, int finalTermScore) {
		this.name = name;
		this.attendanceScore = attendanceScore;
		this.finalTermScore = finalTermScore;
	}
	
	// static 블록 내부 코드는 프로그램 시작 시 즉시 자동으로 한 번 호출
	static {
			presentationScore = 29;
	}
	
	public void showStudentScore() {
		System.out.println("학생명 : " + this.name);
		System.out.println("출결점수 : " + this.attendanceScore);
		System.out.println("발표점수 : " + presentationScore);
		System.out.println("기말점수 : " + this.finalTermScore);
		System.out.println("최종점수 : " + (this.attendanceScore + presentationScore + this.finalTermScore));
		System.out.println("===========================================");
	}
}
public class MainClass {
	public static void main(String[] args) {
		// 인스턴스생성 전부터 이미 조회 가능한 팀점수
		System.out.println(Asean.presentationScore);
	
		// 학생 4명 생성
		Asean a1 = new Asean("가", 20, 43);
		Asean a2 = new Asean("나", 15, 30);
		Asean a3 = new Asean("다", 10, 35);
		Asean a4 = new Asean("라", 18, 40);
	
		a1.showStudentScore();
		a2.showStudentScore();
		a3.showStudentScore();
		a4.showStudentScore();
	
		// 어떤 인스턴스를 활용해도 팀 점수 조회 가능
		System.out.println(a1.presentationScore);
		System.out.println(a2.presentationScore);
		System.out.println(a3.presentationScore);
		System.out.println(a4.presentationScore);
	}
}

위 그림과 같이 static 변수로 지정하면 main() 함수보다 앞서 실행되고, 해당 변수는 객체들이 전체적으로 공유하는 값으로 호출이 가능하다.

즉, 해당 변수는 힙 영역에 있는 것이 아니므로 this 키워드는 사용 불가하다.

위 코드에서 presentationScore가 public으로 선언되어 있으므로 어떤 인스턴스를 활용하더라도 호출이 가능하다.

 

2) 정적 메서드 (static method)

- 해당 클래스의 객체 생성 없이도 참조 가능

- static 메서드 안에서는 non-static 멤버를 객체 생성 없이 직접 참조 불가

- static 메서드 안에서는 static 변수를 선언할 수 없음

public class Asean {
	// 출석 20, 발표 30, 기말 50
	public String name; 
	private int attendanceScore; // 출결점수
	private int finalTermScore;   // 기말점수

	private static int presentationScore; // 29
	
	public Asean(String name, int attendanceScore, int finalTermScore) {
		this.name = name;
		this.attendanceScore = attendanceScore;
		this.finalTermScore = finalTermScore;
	}
	
	// static 블록 내부 코드는 프로그램 시작 시 즉시 자동으로 한 번 호출
	static {
			presentationScore = 29;
	}
	
	// 스태틱 메서드도 객체 없이 바로 호출 가능
	public static void showPresentationScore() {
		System.out.println(presentationScore);
	}
}

위 코드에서 presentationScore이 private으로 지정되어 있으므로 객체를 생성하지 않고서는 호출이 불가하다.

→ 스태틱 메서드를 활용하면 호출 가능

public class MainClass {

	public static void main(String[] args) {
		// 인스턴스생성 전부터 이미 조회 가능한 팀점수
		// System.out.println(Asean.presentationScore); // private이므로 호출 불가
		// 스태틱 메서드도 스태틱 변수처럼 호출 가능
		Asean.showPresentationScore(); 
		}
}

위와 같이 static 메서드를 활용하여 접근 가능하고 private 변수로 선언되어 있어 외부에서 변수의 값 자체를 변경할 수 없다는 장점이 있다.

'네트워크캠퍼스 > JAVA' 카테고리의 다른 글

final  (0) 2024.01.15
싱글톤 패턴  (0) 2024.01.15
매개변수의 다형성  (0) 2024.01.11
배열의 다형성  (0) 2024.01.10
클래스의 다형성  (0) 2024.01.09

+ Recent posts