JAVA_DAY3

이정찬·2023년 1월 25일
0

JAVA

목록 보기
3/5

2일차 추가

클래스 뒤에 implements Serializable을 붙이면 직렬화된다. 모바일 개발할 때 화면간 통신할 때 쓰인다.

data class화 한다는것운 hashcode()equals() 함수를 만들어준다는 것이다. 이클립스에서 자동완성 지원한다.

상속

클래스간의 상속(단일 상속), 인터페이스 간의 상속(다중 상속): extends
클래스와 인터페이스 간의 상속(다중 상속): implements

  • 모든 클래스는 이름 뒤에 extends Object 가 생략되어 있다.
public class Parent /*extends Object*/

@Override는 반드시 상속받은 부모 함수와 재정의할 내 함수의 이름이 같아야 한다.

상속을 맺으면, 메모리상에 모든 부모 클래스가 다 생성되기 때문에, 메모리상으로 그렇게 효율적이진 않다.

자바는 원래 메서드 안에 메서드를 정의할 수 없다. (람다식 제외)

// Parent.java
package test.com;

public /*final*/ class Parent extends Object { // final 붙이면, 상속 안됨 ex) String
	final int num = 11;
	String name = "kim";

	public /*final*/ int sleep() { // sleep에 final 붙일 경우, 재정의 불가
		System.out.println("Parent sleep()...");
		return 8;
	}
}

// Mother.java
package test.com;

public abstract class Mother { // 추상 클래스
	int num;
	String name;
	
	public Mother() {
		// TODO Auto-generated constructor stub
	}
	
	public int drive() {
		System.out.println("Mother drive()...");
		return 8;
	}
	
	public abstract void run(); // 클래수 내부에 블럭 없이 정이된 메소드 -> 추상메소드
	public abstract String run2(int x); // 매개변수 넣어서도 가능
}

// MySister.java
package test.com;

public class MySister extends Mother {
	// 추상 클래스를 상속받은 클래스는 반드시 추상 매서드를 오버라이드 해야한다.
	
	@Override
	public void run() {
		
	}
	
	@Override
	public String run2(int x) {
		return "";
	}
	
	public void stop(int x, int y, int z) {
		System.out.println("stop()...");
	}
	
	public void stop2(int ...z) { // 개수 상관없이 int면 된다.
		System.out.println("stop2()..." + z);
	}
}


// MyBrother.java
package test.com;

public class MyBrother extends Parent {
	int score = 100;
	String hobby = "golf";
	
	public int play(String x) {
		System.out.println("play()..." + x);
		return 10;
	}
}


// My.java
package test.com;

public class My extends Parent{
	int money = 1000;
	String name = "kim";
	
	public My() {
		
	}
	
	public int work() {
		System.out.println("My work()...");
		return 8;
	}
	
	@Override
	public int sleep() { // Ctrl + space로 자동완성 가능
		System.out.println("My sleep()...");
		return 10;
	}
}

//Child.java
package test.com;

public class Child extends My{
	int money = 10;
	String name = "kim";
	
	public int study() {
		System.out.println("Child study()...");
		System.out.println("super.num: " + num); // super.num이지만, super 생략해도 된다.
		System.out.println("super.money: " + super.money); // 1000
		System.out.println("this.money: " + this.money); // 10
		// 부모와 내 변수 구분 가능
		
		return 10;
	}
	
	public Child() {
		System.out.println("child...");
	}
	
	// 알바
	@Override
	public int work() {
		System.out.println("Child work()...");
		return 4;
	}
	
	@Override
	public int sleep() {
		System.out.println("Child sleep()...");
		return 6;
	}
}

여기까지 클래스

// Test01main.java
package test.com;

public class Test01main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("상속...");
		
		Parent p = new Parent();
		System.out.println(p.num);
		System.out.println(p.name);
		System.out.println(p.sleep());
		
		System.out.println("=====================");
		
		My m = new My();
		System.out.println(m.money);
		System.out.println(m.name);
		System.out.println(m.work());
		
		System.out.println("=====================");
	
		Child c = new Child();
		System.out.println(c.money);
		System.out.println(c.name);
		System.out.println(c.study());
		System.out.println(c.work());
		
		System.out.println("=====================");
		
		My my = new My();
		System.out.println(my.money);
		System.out.println(my.name);
		System.out.println(my.work());
		System.out.println(my.num);
		System.out.println(my.sleep()); 
		
		System.out.println("=====================");
		
		Child ch = new Child(); // 상속을 맺으면, 메모리상에 
		System.out.println(ch.money);
		System.out.println(ch.name);
		System.out.println(ch.study());
		System.out.println(ch.work());
		System.out.println(ch.sleep());
		
		System.out.println("===========다형성==========");
		
		Parent p2 = new My(); // 가능
		System.out.println(p2.num);
		System.out.println(p2.name);
		System.out.println(p2.sleep()); // Parent(좌측)의 자원들만 사용할 수 있다.
		
		Parent p3 = new Child(); // 가능
		System.out.println(p3.num);
		System.out.println(p3.name);
		System.out.println(p3.sleep()); // Parent(좌측)의 자원들만 사용할 수 있다.
		

		System.out.println(p2 instanceof Parent); // true
		System.out.println(p3 instanceof Parent); // true
		
		// 내부 클래스로 상속을 구현할 수 있다.
		System.out.println("===========내부 클래스로 상속 구현==========");
		
		Parent p4 = new Parent() {
			// 클래스 영역, 이름 없는 익명 내부 클래스
			
			// 속성
			String myName = "Lee";
			int kor = 99;
			
			// 메소드 정의, 밖으로 빠져나가면 호출 불가
			public String myFriend(int x) {
				return "Yang";
			}
			
			@Override
			public int sleep() {
				System.out.println("Inner sleep()...");
				return 7;
			}
		};
//		System.out.println(p4.myFriend()); // error
		System.out.println(p4.sleep()); // 재정의 한 것은 콜 가능
	}
}

// Test02main.java
package test.com;

public class Test02main {
	public static void main(String[] args) {
		System.out.println("디형성...");
		
		// Parent p = new Parent();
		Parent p = test();
	}
	
	public static Parent test() {
		return new My();
	}
}

// Test03main.java
package test.com;

public class Test03main {
	public static void main(String[] args) {
//		Mother m = new Mother(); // error
		Mother m = new MySister(); // ok
		// 반드시 상속받는 쪽으로 생성해야 한다.
		
		MySister ms = new MySister();
		ms.stop(11, 22, 33);
		ms.stop2(11);
		ms.stop2(11, 22);
		ms.stop2(11, 22, 33);
		ms.stop2(11, 22, 33, 44);
	}
}
  • this` 명령어를 이용하여 클래스 내의 다른 생성자를 호출할 수도 있다.
this("홍길동", 100, false);
this("길동홍", 200);
  • super() 생성자 위에는 어떤 코드도 쓸 수 없다.

  • protected는 상속관계라면, 패키지 밖에서도 접근할 수 있다는 뜻이다.

  • 추상 클래스 사용 이유: 사용자의 혼동을 방지하기 위해, 사용 패턴을 강제하기 위해

Singleton

// SingletonClass.java
package test.com;

public class SingletonClass {
	private static SingletonClass st = new SingletonClass(); // 외부 접근 불가능. 싱글톤 막는다.
    // 접근 시 외부 getter 함수 필요
	
	private SingletonClass() { // 외부 접근 불가능(new 불가능)
		// TODO Auto-generated constructor stub
	}
	
	public static SingletonClass getInstance() { // 보통 이름을 이렇게 짓는다.
		return st;
	}
}

// SingletonMain.java
package test.com;

public class SingletonMain {

	public static void main(String[] args) {
		System.out.println("Singleton class");

		SingletonClass st1 = SingletonClass.getInstance();
		System.out.println(st1); // 주소

		SingletonClass st2 = SingletonClass.getInstance();
		System.out.println(st2); // 주소
	}

}

Interface

// Friend.java
package test.com;

public interface Friend {
	// 인터페이스는 생성자가 존재하지 않는다.
	// 반드시 누군가가 상속받아서 오버라이딩하거나, inner class로 명시해야 한다.
	
	// 인터페이스의 필드는 항상 public static final이다. 생략 가능
	String USER_NAME = "YANG";
	
	// 1. abstract
	public void sleep(); // abstract 키워드 생략 가능
	
	// 2. default
	public default void stop() { // interface는 default 키워드 명시 필수
		System.out.println("Friend default stop()...");
	}
	
	// 3. static
	public static void start() {
		System.out.println("Friend static start()...");
	}
}

// Student.java
package test.com;

public interface Student {
	String SCHOOL_NAME = "SDS";
	
	public int study(String name);
}

// Person.java
package test.com;

public class Person implements Friend, Student { // 다중 상속 가능

	@Override
	public void sleep() {
		System.out.println("Person sleep()...");

	}
	
	@Override
	public int study(String name) {
		System.out.println("Person study()..." + name);
		
		return 10;
	}
}

// Test01main.java
package test.com;

public class Test01main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("interface...");
		
		Friend f = new Friend() {
			@Override
			public void sleep() {
				System.out.println("anonymous inner sleep()...");
			}
		};
		f.sleep();
		
		Friend f2 = new Person();
		f2.sleep();
        f2.stop();
        Friend.start();
		
		Student st = new Person();
		int studyTime = st.study("Kim");
		System.out.println("studyTime: " + studyTime);
	}
}

단일 상속과 다중 상속의 조건들을 잘 보고 추상 클래스(단일 상속)랑 인터페이스(다중 상속)를 구별해서 사용하면 된다. default에도 주의하자.
대세는 인터페이스다. 인터페이스에서도 default, static 등의 키워드를 모두 쓸 수 있기 때문에, 굳이 추상 클래스의 제약조건을 신경 쓸 필요가 없다.

Collection

가변배열 처리를 위해 사용. 자료구조 라고도 불린다.
1. 순서 있고, 중복 허용: List 계열 -> ArrayList, Vector
2. 순서 없고, 중복 불가: Set 계열 -> HashSet
3. 키와 값으로 여러 데이터 갖는 객체이며 키는 중복 불가능, 값은 가능: Map 계열 -> HashMap, HashTable

  • Set 계열은 랜덤이 아니지만, 순서대로 쌓이는 것도 아니다.
  • index가 없어서 set()은 불가능하고, remove()도 값 기반으로 해야한다.

package test.com;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Test01main {

	public static void main(String[] args) {
		// 가변배열: Collection
		
		int[] sus = new int[3];
		Integer[] sus2 = new Integer[3];
		
		// 1. List 계열
		
		List<Integer> sus3 = new ArrayList<Integer>();
		sus3.add(1000); // 0
		sus3.add(1000); // 1
		sus3.add(2000); // 2
		
		sus3.set(2, 4000);
		
		System.out.println(sus3); // [1000, 1000, 4000]
		
		for (int v : sus3)
			System.out.println(v);
	
		sus3.remove(0);
		
		for (int i = 0; i < sus3.size(); i++)
			System.out.println(sus3.get(i));
		
		// sus3.clear(); // 다 지움
	
		System.out.println("=========================================");
		
		// List<BoardVO> vos = new ArrayList();
		// vos.add(new BoardVO(1, "kim", "aaa", "Lee"));

		// 2. Set 계열
		Set<Integer> s = new HashSet<>();
		s.add(1000);
		s.add(1000);
		s.add(1000);
		s.add(1000);
		s.add(1000);
		s.add(2000);
		System.out.println("s.size(): " + s.size()); // 2
		
		s.remove(2000);
		
		// s.clear();
		
		System.out.println("=========================================");
		
		
		Set<BoardVO> svos = new HashSet<>();
		svos.add(new BoardVO());
		svos.add(new BoardVO());
		svos.add(new BoardVO(1, "kim", "aaa", "Lee"));
		svos.add(new BoardVO(1, "kim", "aaa", "Lee"));
		
		System.out.println("svos size(): " + svos.size()); // 2
		// Data class(hashCode, equals)가 아니라면, equals가 없기 때문에 제대로 실행되지 않는다. 4 나옴.
		
		// Serializable과는 아예 다른 개념이다. 객체를 매개변수로 전달할 때 쓰이는 기법이다. new를 통해 만든 객체를 전송할 때, 받는 쪽이 Serializable type인 경우가 있다. 그 때 쓰는거다.
		// Byte code로 직렬화가 되며, 그냥 상속만 해주면 된다.
	}
}
profile
개발자를 꿈꾸는 사람

0개의 댓글