Dev/Java

[java] 상속, Object 클래스, String클래스, StringBuffer와 StringBuilder

창문닦이 2019. 1. 24. 19:37

모든 생성자안에는 super()가 생략되어 있다.

A class - B class - C class 부모-자식 관계일 때

전혀 상관 없는 별도의 D class에서 C class의 객체를 생성할때 기본생성자안에있는 super를 통해

부모클래스의 메모리를 먼저 할당받은 뒤 마지막에 자식클래스 생성.

이때 최상위에 있는 A class의 부모클래스는? Object .

java에서 가장 큰 자료형 = Object . 무엇이든지 넣을 수 있다. 자동으로 옮길 경우에는 무조건 object로 옮김. 제일 크니까.

class Test{

private String title;

protected int area;

//public Test(){}//기본생성자

public Test(String title){ //오버로딩된 생성자

this.title = title;

}

public void print(){

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

}

}

class Rect extends Test{ //에러발생.

//기본생성자 생략되어있음.

//이 기본생성자안에는 super(); 포함

//부모클래스의 기본생성자를 생략하게 되면, 사용하지 않겠다는 의미.

//자식클래스에서 부모클래스의 기본생성자를 사용못해서 오류

private int w,h;

public Rect(int w, int h){

//default값은 기본생성자임 super();

//-> 그런데 부모클래스에 기본생성자를 삭제했으므로 오버로딩된 생성자를 통해 객체 생성해야함

super("사각형"); //super에 매개변수를 할당하면 오류 사라짐. 부모클래스의 오버로딩된 생성자를 호출

//부모클래스가 먼저 만들어져야 자식클래스가 생성 가능

this.w =w;

this.h =h;

//super("사각형"); 밑에 쓰면 오류남. 부모클래스 없는데 매개변수를 입력받아 처리 불가능. 두번입력도 불가능

}

public void rectArea(){

area=w*h; //부모클래스 생성된 상태이므로 부모클래스의 변수 사용 가능

}

}

public class Test1 {

public static void main(String[] args) {

Rect ob = new Rect(10,20);

ob.rectArea();

ob.print(); //부모클래스에서 가져다 씀

}

}


기본생성자와 super()


class Super{

public Super(){}

public Super(int x){

}

public Super(int x, int y){

}

}

class Sub extends Super{

//Sub(){} 기본생성자 존재

//그 안에 super() 숨겨져있음. super()의 역할은 부모-자식간의 관계를 유지시켜주는 것

public Sub(){

this(10); //public Sub(int a){} 호출. 생성자에서 생성자 호출. 이럴땐 this사용

}

public Sub(int a){

//super(); 기본생성자 호출

super(10,20); //오버로딩된 생성자를 호출.

}

}

public class Test2 {

public static void main(String[] args){

Sub ob = new Sub(10);

}

}


오버로딩된 생성자

override(오버라이드, 재정의, 다형성) : 저장공간이 다르기 때문에 메소드이름이 동일해도 가능함.

상속관계에서 부모의 메소드와 똑같이 만들고...(메소드명, 매개변수 등) 내용만 다르게 만듦

하는 역할은 유사. 자식의 마음대로 내용을 변형. 프로그래머의 의도가 반영

@Override 어노테이션(Annotation)

class SuperA{

private String title;

protected double area;

public SuperA(){} //기본생성자

public SuperA(String title){ //오버로딩된 생성자

this.title = title;

}

//메소드

public void write(){

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

}

}

//Circle클래스와 Recta클래스는 아무 상관 없음.

class Circle extends SuperA{

private int r;

protected static final double PI = 3.14; //static이므로 폰트 기울여짐. 메모리상에 알아서 올라감

public Circle(int r){

super("원"); //SuperA클래스의 기본생성자를 찾아가는데 그곳에 기본생성자가 없다면. 에러

this.r=r;

}

public void circleArea(){

area=r*r*PI; //PI가 double이므로 형변환됨

}

}

class Recta extends SuperA{

private int w,h;

public void rectArea(int w, int h){

this.w= w; //이게없으면 초기값 0으로 처리

this.h= h;

area = w*h;

//super.write();

}

//마우스우클릭 - Source > Override > 부모클래스중에 어느 메소드를 재정의할지 어노테이션 기능 사용 가능

//Annotation : 메소드명이나 매개변수 갯수,자료형들이 달라지면 알려줌

//부모클래스가 무엇인지도 쉽게 볼 수 있음

@Override

public void write() {

//super.write(); //자식클래스의 메소드안에서 부모의 메소드를 간접적으로 사용 가능. main문에서는 작성안됨.

System.out.println("가로:"+w);

System.out.println("세로:"+h);

System.out.println("면적:"+area);

}

}

public class Test3 {

public static void main(String[] args) {

Circle ob1 = new Circle(10);

ob1.circleArea();

ob1.write();

System.out.println("------------------------------------");

Recta ob2 = new Recta();//기본생성자로 생성

ob2.rectArea(10, 20); //매개변수값 필요

ob2.write(); //5. 부모도 가지고 있고 나도 가지고 있으면 내꺼 쓴다. 무조건!!

//어떠한 방법으로도 부모 메소드를 사용할 수 없음. 보안이 철저하기 때문. 클래스 정의시 메소드 안에서는 가능(53줄).

//메소드는 하늘이 두쪽나도 자신 것을 사용함. 그만큼 보안이 철저.

}

}


Object : 모든클래스는 Object를 상속받는다.


class TestA extends Object{ // 모든클래스의 부모클래스는 Object.

//extends Object를 쓰지 않아도 오류 안남. 기본적으로 상속개념이 이미 반영되어있음

private int a = 10;

public void write(){

System.out.println("a: " + a);

}

}

public class Test4 {

public static void main(String[] args) {

TestA ob1 = new TestA(); // new : 물리적으로 새롭게 만들어라. 100번 썼으면 100개 만들어짐

TestA ob2 = new TestA();

System.out.println("ob1==ob2 : " + (ob1==ob2) ); //false : 주소를 비교한 것 이기 때문

//똑같은 클래스로 객체 생성했지만 ob1에 들은 주소와 ob2에 들은 주소가 다르기 때문

System.out.println("ob1.equals(ob2) : " + (ob1.equals(ob2)) ); //.equals()라는 메소드 사용

//모든 클래스의 부모는 Object. 내맘대로 가져다 쓸 수 있음

//equals() 메소드는 주소와 주소를 비교함

System.out.println("ob1: " + ob1); //com.day9.TestA@15db9742    <- @뒤에 숫자는 hashcode

System.out.println("ob2: " + ob2.toString()); //com.day9.TestA@6d06d69c 패키지.클래스.hashcode

//자바에서는 포인터변수 사용 안한다.

}

}


String

String은 class이다.(자료형이 아니다.)

다만, String을 자료형처럼 사용하는 이유는 저장하는 양은 방대하고 사용빈도가 높기 때문

stack영역에 저장할 수 없고 heap영역에 저장해야 함 -> 그러다보니 class여야함

그런데 사용빈도가 높다보니 new 쓰면 번거로움 -> 그래서 자료형모양새 처럼 씀

String은 불변의 법칙을 가지고 있다.

String은 equals로 비교한다.


public class Test5 {

public static void main(String[] args) {

String ob1 = "Seoul"; //heap영역에 "Seoul"이 저장됨

String ob2 = "Seoul"; //Call by reference

String ob3 = new String("Seoul"); //사용빈도가 높다보니 이렇게 쓰기 어려움

System.out.println("ob1 == ob2 : " + (ob1 == ob2)); //주소를 비교하면 false가 나와야하는데 true가 나옴

//ob1, ob2 객체 생성시 new를 사용한게 아니기 때문에 Call by reference. 주소를 나눠가짐

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

//new를 통해 객체 생성, 무조건 heap영역에 새로운 메모리 할당. 주소값 상이하므로 false나옴

System.out.println("ob1.equals(ob3) : " + ob1.equals(ob3)); //true

//String은 클래스지만 자료형의 흉내를 내야함.

//ob1의 주소를 찾아가서의 값과 ob3의 주소를 찾아가서의 값을 비교해야 함

//object.equals() : 이 메소드는 주소값 비교.

//object의 equals 메소드를 쓴게 아니라 String의 equals 메소드를 사용 (override : 자식클래스에서 메소드재정의)

ob2 = "korea"; //새롭게 메모리 할당함

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

ob2 = "japan"; //korea와는 다르게 또 새로운 메모리 할당함

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

//이게 바로 String 불변의 법칙

ob2 = "Seoul"; //이미 Seoul을 할당해둔 게 있으니 그 주소로 저장

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

//쓰레기값이 굉장히 많이 남아있다.

//일반적으로 많은 문자열을 입력할 경우 사용하는게 따로 있음

System.out.println(ob1); //hashcode가 아닌 Seoul이 나옴

System.out.println(ob1.toString()); //Seoul. override함. String의 toString()메소드 사용

//String을 보조해주는 클래스 2개 존재 -> Test6

}

}


StringBuffer - 동기화지원O(builder보다 느림)

StringBuilder - 동기화지원X(지원하지 않아 빠름)

위에 두 클래스는 import하지 않아도 사용가능! -> 즉, 둘다 lang에 있다.

둘은 하는 역할이 다름

동기화 지원 여부에 따라서 선택하여 사용하면 됨


public class Test6 {

public void stringTime(){ //쓰레기값이 많이생김, a, aa, aaa, aaaa ... 모두 저장됨.

System.out.println("stringTime...");

//long start = System.currentTimeMillis(); //시스템의 초시간을 재겠다

long start = System.nanoTime(); //시작시간

String str = "A";

for(int i=1;i<50000;i++){

str+="A";

}

long end = System.nanoTime(); //종료시간

System.out.println("실행시간 : "+ (end-start));

}

public void stringBufferTime(){ //누적시키는 것. append메소드 이용.

System.out.println("stringBufferTime...");

long start = System.nanoTime(); //시작시간

StringBuffer str = new StringBuffer("A");

for(int i=1;i<50000;i++){

str.append("A");

}

long end = System.nanoTime(); //종료시간

System.out.println("실행시간 : "+ (end-start));

}

public void stringBuilderTime(){

System.out.println("stringBuilderTime...");

long start = System.nanoTime(); //시작시간

StringBuilder str = new StringBuilder("A");

for(int i=1;i<50000;i++){

str.append("A");

}

long end = System.nanoTime(); //종료시간

System.out.println("실행시간 : "+ (end-start));

}

public static void main(String[] args) {

Test6 ob = new Test6();

ob.stringTime();

ob.stringBufferTime();

ob.stringBuilderTime();

}

}


Integer(int의 참조형 자료형) double의 참조자료형은 Double

int a = 10; //일반자료형

Integer b = new Integer(10); //자료형의 참조형 자료형 8개있음. (String은 class이므로 제외)


public class Test7 {

public static void main(String[] args) {

StringBuffer sb = new StringBuffer();

sb.append("서울");

sb.append("부산");

sb.append("대구");

System.out.println(sb);

String str = sb.toString(); //object.toString을 override한 것. 결과만 저장.

System.out.println(str); //StringBuffer와 StringBuilder사용시 이렇게 저장 후 출력해주면 됨

int a = 24;

System.out.println(a); //정수 10

System.out.println(Integer.toString(a)); //문자 10

System.out.println(Integer.toString(a,2)); //2진수

System.out.println(Integer.toString(a,8)); //8진수

System.out.println(Integer.toString(a,16)); //16진수

}

}