[JAVA] Day 10 - boolean / 상속 / Override / equals / toString / String

sue·2023년 11월 27일

📒국비학원 [JAVA]

목록 보기
7/20
post-thumbnail

상속 (부모 → 자식)

c언어 - 다중상속
java, c# = 단일상속만 가능 / interface의 언어임

  • 부모꺼는 자식꺼다
  • private로 선언한 것 = 부모꺼 (일단, 모든 변수는 private로 선언하고 봄)
  • protected로 선언한 것 = 상속이 가능함 (자식 or 패키지안에선 모두 다 갖다 쓸 수 있음)
  • 내꺼(자식) = 내꺼임(부모는 받을 수 없음)
  • 부모와 내가 같은 객체를 가지고 있으면 내꺼

Object

  • 무조건 상속받음
  • 자바에서 이미 만들어져있는 클래스 + 내가 만든 클래스 + 앞으로 만들 클래스의 (무조건) 부모임
  • Object는 자바에서 가장 큰 자료형(부모)임
  • Object가 가지고있는 메서드 - equals , toString 많이 사용함
  • 상속을 표현하지 않으면 자동으로 상속되는 클래스

Override(오버라이드) - alt+shift+s -> h

  • 메소드 통일화 (깔끔한 코딩을 위해)
  • 상속관계에서 부모의 메소드 이름과 통일하게 만들고 내용만 다르게 만들어줌
  • 부모와 나의 위치(folder)가 달라서 [메서드 이름(매개변수)]를 똑같이 써줄 수 있음

🔎 [Eclipse] - [package] - [class] 생성


📌 Note Code


  • (자료형타입) System.in.read( ) : 사용자에게 여러개 값 중에 하나의 값을 받겠다 ex) 사칙연산
  • if문( )
    ① 조건들이 다 부정이면, && : [and]를 씀
    ② 긍정적인 것들이 if문안에 많아질 수록 좋지 않으니, if( ) 안쪽 return = 부정적, 바깥쪽 return = 긍정적
  • private = 직원 only! 타 부서에서 끌어다 쓸 수 있음

Test1. 계산기 만들기 ver.3

💻 입력


import java.io.IOException;
import java.util.Scanner;

class Calc{

	private int num1, num2;
	private char oper;

	public boolean input() throws IOException { 

		Scanner sc = new Scanner(System.in);

		System.out.print("두개의 수?");
		num1 = sc.nextInt();
		num2 = sc.nextInt();

		System.out.print("연산자?");
		oper = (char) System.in.read(); 

		if (oper!='+' && oper!='-' && oper!='*' && oper!='/') {
			return false;
		}
		return true; // 긍정적인 코딩 바깥
	}

	public int result() {

		int r = 0;

		switch (oper) { 
		
		case '+': // case 띄움 ' 
			r = num1 + num2;
			break;
		case '-':
			r = num1 - num2;
			break;
		case '*':
			r = num1 * num2;
			break;
		case '/':
			r = num1 / num2;
			break;

		}

		return r;
	}

	public void print(int r) {
		System.out.printf("%d %c %d = %d\n", num1, oper, num2, r); // r=결과값
	}

}


public class Test1 {

	
	public static void main(String[] args) throws IOException {

		Calc ob = new Calc();
		
		//boolean값으로 받는 공식 (역으로 ! )
		if(!ob.input()) {
			//if(bool!=true) {

			System.out.println("연산자 오류");
			return; //여기까지만 실행해라 - stop (아래문장 실행 x)
		}
		
		//긍정적인건 바깥으로!
		int r = ob.result(); //true이면 실행
		ob.print(r);//r값 반환
		
	}

}

💡 **출력**
두개의 수?10 20
연산자?*
10 * 20 = 200
-------------------------------
두개의 수?3 5
연산자??
연산자 오류


📌 Note Code


  • 값 초기화하는 방법
    ① : 우회도로 만들기 ex)public void setData ( ) { - this
    ② : 오버로딩된 생성자 (기본생성자로써 객체생성할 수 없다고 코드 짤 때) ex)public RectA () { - this
    -> 위에 값이 생성되지 않았으므로 null = 0;이 나옴, 그래서 위에 자료형에 대한 메소드가 필요!
  • 상속 : extends 부모클래스이름

Test2-1. 사각형의 이름과 넓이를 나타내라 (private / protected)

💻 입력


class SuperA {

	private String title;
	private int area;
    //*protected int area로 선언하게 되면 - 상속가능 -> 밑에 area 관련한 코딩 다 x)

	// 값 초기화하는 1번째 방법 - 우회도로
	public void set(String title, int area) {
		this.title = title;
		this.area = area;

	}

	public void print() {

		System.out.println(title + " : " + area);

	}

}

class RectA extends SuperA {// extends 부모클래스이름 => 상속관계 성립

	private int w, h;

	// 값 초기화하는 2번째 방법 - 오버로딩된 생성자
	public RectA(int w, int h) { // 오버로딩된 생성자로만 객체 생성해야한다고 내가 짬
		this.w = w;
		this.h = h;
	}

	public void rectArea() { // 위의 title이 뭔지, area가 뭔지에 대한 메소드 필요!

		int a = w * h; // 지역변수면 값이 빠져나올 수 없음
		set("사각형", a); // 1.부모는 자식꺼다 - 내부라서 객체생성 앞에 안써줌

	}

}

public class Test2 {

	public static void main(String[] args) {

		RectA r = new RectA(10, 20);

		r.rectArea(); // 자식의 (원래)자식꺼 = 5. 부모와 내가 같은 객체를 가지고 있으면 내꺼 씀
		r.print();// 자식의 (원래)부모꺼

	}

}

💡 **출력**
사각형 : 200


📌 Note Code


  • (기본생성자 x) 오버로딩 생성자로 값 초기화 하는 방법
    ex) private String title; -> public 클래스이름(String title) { this title = title; }
  • ex) this(50); - this = 오버로딩된 생성자 / this(); - (자기자신의) 기본 생성자
  • class는 메소드없이 변수만 설정 가능
  • 부모 생성자를 찾는 super( )이 먼저 생겨야, 자식이 생기니까 -> super(맨 선두) > this보다 위
    super( ): 상속받은 자식의 기본 생성자 안에 생략되어있음 / 매개변수에는 private를 넣으면 에러 사라짐

Test2-2. 사각형의 이름과 넓이를 나타내라 (생성자)

💻 입력


class SuperC{
	
	private String title;
	protected int area;
	
	
	//오버로딩된 생성자로만 객체생성
	public SuperC(String title) { //protected라서 area는 안해줘도됨
		this.title = title;
	}

	public void print() {
		System.out.println(title+" : "+area);
	}

}

class RectC extends SuperC{ //클래스는 메서드없이 변수만 설정 가능
	
	private int w,h;
	
	/*
	public RectC() { //상속 - 생성자 안에는 super가 숨겨져 있음
		super("사각형");
	}
	*/
	
	public RectC(int w, int h) {

		//생성자 - 맨 선두에 호출(부모 생성자 찾는 super 먼저 생겨야, 자식이 생기니까) > 생성자
		 //부모 생성자를 호출(생성자안에 기본으로 생략되어있음)
		//매개변수에 맞게 써주면 에러 사라짐.
        
		super("사각형");
   
		this.w = w;
		this.h = h;

	}

	public void rectArea() {
		area = w*h;
	}

}

public class Test4 {

	public static void main(String[] args) {

		RectC ob = new RectC(10,20); 
		ob.rectArea();
		ob.print();
	}

}

💡 **출력**
사각형 : 200


📌 Note Code


  • final은 생성할 때 값 초기화 해야함
  • @Override (어노테이션 : 오타를 잡아냄)
    찾는 방법 : ① 우클릭 -> source -> Override / ② 같이 override할 부모 메소드 이름 적으면 됨

Test2-3. 사각형의 이름과 넓이를 나타내라 (다른 자료형, final 상수,Override)

💻 입력


class SuperClass {

	private String title;
	protected double area;

	public SuperClass() {
	}

	public SuperClass(String title) {
		this.title = title;
	}

	public void write() {
		System.out.println(title + " : " + area);
	}

}

class Circle extends SuperClass {

	private int r;
	protected static final double PI = 3.14; // final은 생성할 때 값 초기화 해야함

	public Circle(int r) { // 생성자로 객체 생성
		super("원");
		this.r = r;
	}

	public void circleArea() {
		area = r * r * PI;

	}
}

class Rectt extends SuperClass {

	private int w, h;

	public void rectArea(int w, int h) {// 기본생성자로 객체 생성하고 , 초기화는 메서드로 하겠다.
		this.w = w;
		this.h = h;

		area = w * h;

	}

	@Override // 어노테이션
	public void write() {
		System.out.println("가로: " + w);
		System.out.println("세로: " + h);
		System.out.println("면적: " + area);
	}

}

public class Test5 {

	public static void main(String[] args) {

		Circle ob1 = new Circle(10);

		ob1.circleArea();
		ob1.write();

		Rectt ob2 = new Rectt(); // Rectt() <- 기본생성자로 객체 생성

		ob2.rectArea(10, 20);
		ob2.write();
	}
}

💡 **출력**
사각형 : 200


📌 Note Code


  • equals = 객체와 객체가 같은지 비교하는 API
    ex) ob1.equals(ob2)
    -----------------------------------------------------------------------------------------------
    ①-1 : new String("Seoul")은 새 String 객체에 Seoul이라는 값을 넣고 그걸 객체생성한것임
    ①-2 : 새로 객체생성 후, 값을 넣어 주소가 생성할때마다 다름
    -----------------------------------------------------------------------------------------------
    ②-1 : String a = "Seoul"은 그냥 Seoul이라는 값을 String 에 넣은 것임.
    ②-2 : 새로 객체 생성을 한게 아니므로 주소가 같음
  • toString = 받은거 문자로 바꿔서 보여달라는 API
  • 해시코드 = 주소 : System.out.print(new의 복사본이름)

    ex) Test ob1 = new Test();
    Test ob2 = new Test();

    [hashcode 다름]

Test3. true / false 비교 (Object 상속)

💻 입력


class Test {// extends Objext

	private int a = 10;

	public void wirte() {
		System.out.println("a : " + a);
	}

}

public class Test6 {

	public static void main(String[] args) {

		Test ob1 = new Test();
		Test ob2 = new Test();

		System.out.println("ob1 == ob2" + (ob1 == ob2)); // false - 주소 비교 : 해쉬코드 다름 저장되는 위치가 다르니까
		System.out.println("ob1.equals(ob2):" + ob1.equals(ob2));// false - 오브젝트의 equals라서 사용가능

		System.out.println("ob1 : " + ob1);
		System.out.println("ob1.toString() : " + ob1.toString()); 
		System.out.println("ob2: " + ob2);// ob2: com.day10.Test@379619aa [@379619aa = 해시코드]

	}

}

💡 **출력**
ob1 == ob2false
ob1.equals(ob2):false
ob1 : com.day10.Test@1c4af82c
ob1.toString() : com.day10.Test@1c4af82c
ob2: com.day10.Test@379619aa



📌 Note Code


  • String
    클래스 (자료형이 아님)
    ② 저장하는 양은 방대하고, 사용하는 빈도는 높기 때문에 자료형처럼 사용
    ③ 불변의 법칙 (절대 변하지 않음)을 가지고 있음
    → String은 heap영역에 한번 기록하게 되면, 지우거나 덮어쓰지 못함. 그래서 새로운 주소값이 생김

  • String 값이 같을 땐 = 객체생성 X → 주소공유(같음) (Call By Reference)

  • String 값 != new String (값) = 객체생성 O (String은 클래스이므로 객체생성[new] 가능) -> 주소다름

  • String constant pool (문자열 상수 풀) :
    같은 문자열일 경우 주소 공유 -> 메모리 효율 좋아짐 / 문자열 자주 변경시 새로운 공간 할당이 많아지므로 좋지 않음

  • garbage collection (가비지 컬렉션) : 쓰레기 수집 / JVM이 알아서 사용하지 않는 공간(메모리)를 정리하고 관리함


Test3. true / false 비교 (Object 상속)

💻 입력


public class Test7 {

	public static void main(String[] args) {

		String ob1 = "Seoul";
		String ob2 = "Seoul"; // 다시 저장공간을 만들지 않고 ob1과 ob2는 주소 공유
		String ob3 = new String("Seoul"); //객체생성

		System.out.println("ob1==ob2: " + (ob1 == ob2));
		System.out.println("ob1==ob3: " + (ob1 == ob3));

		// 5. ob1의 부모 = Object의 equals(주소와주소 비교) / String의 자식 = Object의 equals를 오버라이드함
		// 자료형의 흉내를 내야하니까 ob의 주소로 찾아가서 저장되어있는 데이터를 비교하게끔 Override함
		// 그래서 ob1 = Seoul과 ob3 = Seoul이 데이터값은 같으니 true
		System.out.println("ob1.equals(ob3) " + ob1.equals(ob3));

		ob2 = "korea"; // 새로운 korea 주소값 생성
		System.out.println("ob1==ob2: " + (ob1 == ob2));

		ob2 = "japan";
		System.out.println("ob1==ob2: " + (ob1 == ob2));

		ob2 = "Seoul"; // 원래 있던 주소값으로 들어올 순 있음
		System.out.println("ob1==ob2: " + (ob1 == ob2));

		System.out.println(ob2); // 자료형처럼 사용하니까 = Seoul
		System.out.println(ob2.toString());

		/*
		 * String a = "A"; a = "AA"; a = "AAA"; ...값이 무수히 많다면 garbage collector : 쓰레기 메모리관리
		 */

	}

}

💡 **출력**
ob1==ob2: true
ob1==ob3: false
ob1.equals(ob3) true
ob1==ob2: false
ob1==ob2: false
ob1==ob2: true
Seoul
Seoul


0개의 댓글