24일차 내용 정리

채공부·2025년 6월 26일

Git

🔴 VS Code 작업 환경 구성

VS Code 창 2개 열기
1. 학원 : git_test\test12
2. 집 : 다른Com\git_repo\test12

🔴 GitHub에서 README.md 파일 생성

GitHub 해당 저장소에서 README.md 파일 생성
Add a README ➜ "#test 예시 Git 테스트중" 제목 추가
commit changes click : 저장소에 README.md 파일 생성 완료

🔴 원격 저장소의 변경사항 로컬로 반영 (학원에서)

git fetch origin main : 최신 커밋을 받아왔지만 워킹 트리에 표시되지 않은 상태

Graph 확인
origin/main 브랜치 Create README.md 커밋 확인 가능

🔺README.md 파일을 워킹 트리에 반영하려면?
git checkout origin/main : README.md 파일이 워킹트리에 표시

git checkout main : main 브랜치로 이동 ➜ README.md 파일이 워킹트리에서 사라짐

🔺main 브랜치에 반영하려면?
git merge origin/main : 병합
➜ README.md 파일이 워킹트리에 표시되고 main 브랜치가 최신 상태로 업데이트

🔴 집에서 변경사항 반영

git pull origin main : fetch + merge 동시에 수행
➜ README.md 파일을 로컬 워킹트리에 반영

🔴 학원과 집에서 각각 commit

🔺학원
acorn.html 파일 추가
"acorn.html 추가함" 이라는 commit 메세지 작성 후 ✔Commit click

🔺집
home.html 파일 추가
"home.html 추가함" 이라는 commit 메세지 작성 후 ✔Commit click

🔺GitHub
현재 README.md 파일이 있는 상태

🔴 학원에서 push

git push origin main : origin에 main 브랜치 이력 내려받기
➜ Graph에서 원격 저장소 이력이 한 칸 내려온 걸 확인 가능
➜ 에러 없이 원격 저장소에 반영 완료

⚠️ 집에서 push ➜ error 발생

git push origin main ➜ rejected error 발생

🔺원인
원격 저장소 이력이 더 앞 선다 (학원에서 먼저 push)

🔺해결 방법
git pull origin main : 충돌없이 자동 merge
➜ 작업 내용이 겹치지 않기에 충돌이 없다
:wq 입력하여 종료하면 push 성공

🔗 학원, 집, GitHub 커밋 이력 동기화

git pull origin main ➜ 모두 동기화 완료

⚠️ 협업 시 주의사항

1. 항상 push 전 pull 먼저 하기
2. 충돌 발생 시 파일 내용 정리 후 add commit
3. 워킹트리가 clean 상태인지 확인하고 작업 진행

🔴 충돌 발생

🔺학원
index.html 파일에 p 요소 추가
"p3 추가함" 이라는 commit 메세지 작성 후 ✔Commit click

🔺집
index.html 파일에 div 요소 추가
"div1 추가함" 이라는 commit 메세지 작성 후 ✔Commit click
Sync Changes click : push 완료

🔺다시 학원
git pull origin main ➜ 충돌 발생‼️

🔴 충돌 해결

해결 순서 : fetch ➜ merge ➜ push

🔺학원
git fetch origin main
git merge origin/main ➜ 충돌 발생
index.html 열기 ➜ <<<<<, =====, >>>>> 기호로 구분된 충돌 지점 정리 ➜ 정리 완료
git add .
git commit -m "merged"

Graph 확인 : 병합 완료된 상태
Sync Changes click ➜ push 성공

🔴 집에서 다시 pull

git pull origin main ➜ 학원, 집, GitHub 모두 커밋 이력 동기화 완료

Eclipes

객체 생성 방식 비교

			  ↱ 생성한 객체의 참조값을 변수에 담고
int ran = new Random();
int a = ran.nextInt()
		 ↳ 변수에 담긴 값을 이용해서 여러 번 사용 가능

					vs

			↱ 객체를 생성해서 얻어낸 참조값을
int a = new Random().nextInt();
						↳ 한번만 사용 (1회용 객체)

익명 클래스 사용

new Weapon(){
	@Override
    pulic void attack(){ }
} ➜ 익명의 클래스로 생성한  Weapon type의 참조값
new Weapon(){
	@Override
    pulic void attack(){ }
}. attack();
	  ⤷ 참조값을 변수에 담지 않고 바로 사용 가능
  • 메소드 호출 흐름
// main 클래스

import test.mypac.Weapon;

public class MainClass07 {
	public static void main(String[] args) {

         Weapon w1 = new Weapon() {
			@Override
			public void attack() {
				System.out.println("공격중!");
			}
		};
		useWeapon(w1);
        
		useWeapon(new Weapon() {
			@Override
			public void attack() {
				System.out.println("공격중!");	
			}
		});
	}
	
	public static void useWeapon(Weapon w) {
		w.attack();
	}
}

인터페이스

only static filed : 필드는 오직 static 필드만 가능
➜ 수정이 불가능해 readonly = 항상 같은 값 = 상수
➜ static 예약어를 안 써도 static이 자동으로 붙는다

only abstract method : 메소드는 오직 추상 메소드만 가능
➜ 메소드 선언만 존재, 실제 구현X

// Remocon 인터페이스

public interface Remocon {
	public void up();
	public void down();
}
  • 변수나 필드의 data type 역할 가능
Remocon r1 = null;

r1.up();
r1.down();

➜ r1에 참조값이 없기에 NullPointerException error 발생

  • 객체 생성 불가 ➜ implements 키워드를 통해 구현 필요
// MyRemocon 클래스

public class MyRemocon implements Remocon {
	@Override
	public void up() {
		System.out.println("볼륨을 올려요!");
	}
	@Override
	public void down() {
		System.out.println("볼륨을 내려요!");
	}
}
  • 객체 생성
import test.mypac.MyRemocon;
import test.mypac.Remocon;

public class MainClass01 {
	public static void main(String[] args) {
		// 인터페이스는 data type의 역할도 할 수 있다
		Remocon r1 = null;
		
		// 인터페이스 단독으로 객체 생성 불가 (아예 생성자 조차도 존재하지 않는다)
		// Remocon r2 = new Remocon();
		
		// 인터페이스 type 의 참조값이 필요하면 해당 인터페이스를 implements 한 하위 클래스를 이용해서 얻어낸다
		Remocon r2 = new MyRemocon();
		
		r2.up();
		r2.down();
	}
}
  • 인터페이스 상수(static final)
// Remocon 인터페이스

public interface Remocon {

	public String COMPANY = "LG"; // static final 상수는 관례상 필드명을 모두 대문자로
	
	public void up();
	public void down();
}
  • 인터페이스명에 . 찍어서 참조 가능
// main 클래스

String a = Remocon.COMPANY; // LG
  • 다형성 & 형변환(Casting)
// main 클래스

import test.mypac.MyRemocon;
import test.mypac.Remocon;

public class MainClass02 {
	public static void main(String[] args) {
		// 다형성 확인
		Object r1 = new MyRemocon();
		Remocon r2 = new MyRemocon();
		MyRemocon r3 = new MyRemocon();
		
		useRemocon(r3);
		useRemocon(r2);
		useRemocon((Remocon)r1);
	}
	
	public static void useRemocon(Remocon r) {
		r.up();
		r.down();
	}
}
  • 인터페이스와 익명 클래스 패턴
import test.mypac.Remocon;

public class MainClass04 {
	public static void main(String[] args) {
		// 인터페이스도 익명의 InnerClass 를 이용해서 구현 객체를 만들 수 있다
		Remocon r1 = new Remocon() {
			
			@Override
			public void up() {
				System.out.println("채널을 올려요!");
			}
			
			@Override
			public void down() {
				System.out.println("채널을 내려요!");
			}
		};
		
		// 지역변수 r1 에 있는 참조값을 전달하면서 메소드 호출
		useRemocon(r1);
		
		// 메소드 호출하면서 즉석에서 객체 들어서 호출
		useRemocon(new Remocon() {
	
			@Override
			public void up() {
				System.out.println("머리를 올려요!");
			}
			
			@Override
			public void down() {
				System.out.println("머리를 내려요!");
			}
		});
	}
	public static void useRemocon(Remocon r) {
		r.up();
		r.down();
	}
}

// Drill 인터페이스

public interface Drill {
	// 구멍을 뚫는 추상 메소드 1개만 정의해 보자
	public void hole();
}
// main 클래스

Drill d1 = new Drill() {
	@Override
	public void hole() {
		System.out.println("바닥에 구멍을 뚫어요!");
	}
};
useDrill(d1);

🟥 람다 표현식으로 간소화

  • ( )->{ }
  • 조건 : 인터페이스에 메소드가 1개만 있을 경우만 가능
Drill d2 = () -> {
	System.out.println("천장에 구멍을 뚫어요!");
};

useDrill(() -> {
	System.out.println("변기 구멍을 뚫어요!");
});

@FunctionalInterface

// Warmer 인터페이스

@FunctionalInterface
public interface Warmer {
	public void warm(String target);
	
}
  • 함수 형태로 사용하기 위한 어노테이션
  • 추상 메소드 1개만 허용
// main 클래스

import test.mypac.Warmer;

public class MainClass06 {
	public static void main(String[] args) {
		Warmer w1 = new Warmer() {
			@Override
			public void warm(String target) {
				System.out.println(target+"을 따뜻하게 해요");
			}
		};
		useWarm(w1);
		
		Warmer w2 = (String target)->{
			System.out.println(target+"을 뜨겁게 해요");
		};
		useWarm(w2);
		
		// 매개변수 type 생략 가능
		Warmer w3 = (e)->{
			System.out.println(e+"에 불을 붙여요");
		};
		useWarm(w3);
		
		useWarm((e)->{
			System.out.println(e+"이 불타고 있어요");
		});
	}
	
	public static void useWarm(Warmer w) {
		w.warm("손");
	}
}
  • 매개변수 2개, 리턴값이 존재하는 함수형 인터페이스
// Operator 인터페이스

@FunctionalInterface
public interface Operator {
	public double execute(double num1, double num2);
}
// main 클래스

import test.mypac.Operator;

public class MainClass07 {
	public static void main(String[] args) {
		
		Operator plus = (double num1, double num2)->{
			return num1+num2;
		};
		
		Operator minums = (num1, num2)->{
			return num1-num2;
		};
        
		Operator multiply = (a, b)-> a*b;
		
		double result1 = plus.execute(10, 10); // 20
		double result2 = minums.execute(10, 10); // 0
		double result3 = multiply.execute(10, 10); // 100
	}
}

  • 인터페이스 다중 구현
// Singer 인터페이스

public interface Singer {
	public void sing();
}
// Programmer 인터페이스

public interface Programmer {
	public void develope();
}
// work 클래스

public class Person implements Singer, Programmer{
	public void work() {
		System.out.println("일을 해요!");
	}

	@Override
	public void develope() {
		System.out.println("노래를 불러요!");
	}

	@Override
	public void sing() {
		System.out.println("App을 개발해요!");
	}
}
  • 하나의 객체는 다양한 type으로 사용 가능
// main 클래스

import test.mypac.Person;
import test.mypac.Programmer;
import test.mypac.Singer;

public class MainClass08 {
	public static void main(String[] args) {
		// Person 객체를 생성ㅎ해서 Person type 으로 받으면
		Person p1 = new Person();
		p1.work();
		p1.sing();
		p1.develope();
		
		System.out.println("-----------");
		// Person 객체를 생성해서 Singer type 으로 받으면 sing() 메소드만 사용 가능
		Singer p2 = new Person();
		p2.sing();
		
		System.out.println("-----------");
		// Person 객체를 생성해서 Programmer type 으로 받으면 develope() 메소드만 사용 가능
		Programmer p3 = new Person();
		p3.develope();
	}
}

Generic 클래스

  • < > : 포괄적인 클래스
// Apple 클래스

public class Apple {}

// Banana 클래스

public class Banana {}
  • FruitBox<T> 를 통해 타입 안정성과 재사용성 확보
// FruitBox 클래스

public class FruitBox <T> {
	// T 를 필드의 type 으로 활용
	private T item;
	
	// T 를 매개변수의 type 으로 활용
	public void pack(T item) {
		this.item = item;
	}
	
	// T 를 메소드의 return type 으로 활용
	public T unPack() {
		return item;
	}
}
// main 클래스

import test.box.FruitBox;
import test.fruit.Apple;
import test.fruit.Banana;

public class MainClass02 {
	public static void main(String[] args) {
		// Apple 을 담은 용도로 사용할 FruitBox 객체 생성하기
		FruitBox<Apple> box1 = new FruitBox<Apple>();
		box1.pack(new Apple());
		
		// Banana 을 담은 용도로 사용할 FruitBox 객체 생성하기
		FruitBox<Banana> box2 = new FruitBox<Banana>();
		box2.pack(new Banana());
	}
}
profile
학원 공부 내용 정리

0개의 댓글