본문 바로가기

자바

[자바기초요약5] 메서드오버라이딩, 오버로딩, @Override, 생성자


[ex]오버라이딩
/*
package java.lang;
public class Object{
 public String toString(){
 }
}
*/
class A{
 public static void main(String args[]){
  B o=new B();
  System.out.println(o); // aaa
 }
}
class B{
 public String toString(){     // object클래스의 toString()메서드를 오버라이딩했음!
  return "aaa";
 }
}

# 오버라이딩
[ex]
class A{
 String m(){
  return "aaa";
 }
}
class B extends A{
 String m(){
  System.out.print(super.m());       //super는 은닉변수나 은닉메서드를 나타냄
  return "bbb";
 }
}
class C{
 public static void main(String args[]){
  B o=new B();
  System.out.println(o.m()); // aaa bbb
 }
}


[ex]
class A{
 public static void main(String args[]){
  Car car1=new Car();  car1.color="red";
  Car car2=new Car();  car2.color="white";
  System.out.println(car1); // red car            //car1.toString() 이 생략되어있음!!!
  System.out.println(car2); // white car
 }
}
class Car{
 String color;
 //here
}

[an] 따라서 toString()을 오버라이딩 하여 기능을 변경하면됨..
class Car{
 String color;
 public String toString(){
  return color+" car";
 }
}


# 접근제어자
 클래스,멤버변수,메서드앞에서 사용가능
 클래스앞에 선언될 수 있는 제어자 : public
 public > protected > default(키워드,예약어가 아님~) > private
 
 public : 모두에게 접근 허용
 protected : 같은패키지, 다른패키지일경우 상속이라면 접근 허용
 default : 같은패키지에서 접근 허용
 private : 모두에게 접근 금지
 
[접근제어자] class 클래스명{                     //클래스
     [접근제어자] 자료형 변수명;                  //멤버변수(지역변수, 매개변수앞에는 접근제어자 선언할수없음.. 그안에서만쓰이니깐)
     [접근제어자] 반환형 메서드명(){               //메서드

      }
}


[ex]
package a.b;
class A{
 public int a=100;
 protected int b=200;
 int c=300;
 private int d=400;
}
class B{
 void m(){
  A o=new A();
  System.out.println(o.a);
  System.out.println(o.b);
  System.out.println(o.c);
  System.out.println(o.d);  // 컴파일에러... d는 A클래스내에서만 접근가능함..
                            //여기 B클래스에서 사용할수없음
 }
}

 
[ex]
package a.b;                                  //패키지를만들때 a.b를담는패키지랑 c.d를담는패키지를
                                              //한곳에 넣으면안됨...(이 예제를 해보면암)
public class A{
 public int a=100;
 protected int b=200;
 int c=300;
 private int d=400;
}

package c.d;
import a.b.A;
class B{
 void m(){
  A o=new A();
  System.out.println(o.a);
  System.out.println(o.b);  // 컴파일에러... 다른패키지라도 상속관계라면
                            //자손클래스에서 접근할수있음. 하지만 상속관계가아님
  System.out.println(o.c);  // 컴파일에러
  System.out.println(o.d);  // 컴파일에러
 }
}


//상속으로 b값을 출력하려면
package c.d;
import a.b.A;
 class B extends A{
 void m(){
  A o=new A();
  System.out.println(o.a);
  System.out.println(a)  
  System.out.println(b);     // 이렇게 바로 나의 은닉변수를 불러야함
  //System.out.println(o.b); //컴파일에러  // 이렇게 은닉변수를 부르는게 아니라 객체주소값을 통해서
                             // 상속받아도 private접근제어자는 접근 안됨!!   
 // System.out.println(o.c); // 컴파일에러
 // System.out.println(o.d); // 컴파일에러
 }
 }


//클래스C를따로만들어서 출력하려면 
//클래스B
package c.d;                             //package는 폴더를만드는것
import a.b.A;                            //import는 B클래스가저장된 패키지를 불러오기위한것
public class B extends A{                //B랑C랑 다른패키지라서 접근하기위해 public를 붙혀줘야함
     public void m(){
            A o=new A();
            System.out.println(a);
            System.out.println(b);  
            // System.out.println(o.c); // 컴파일에러
            // System.out.println(o.d); // 컴파일에러
            }
}
//클래스C
package e.f;
import c.d.B;
class C{
     public static void main(String[] args){
           B b=new B();
           b.m();
     }
}

 
 

# public 이 선언된 클래스
[ex]
test.java                                        // 클래스명.java 해야오류안남
=========
public class A{                    
}
 

# 명령행 매개변수
[ex]
class A{
 public static void main(String args[]){
  System.out.println(args[0]);
  System.out.println(args[1]);
  System.out.println(args[2]);
 }
}
[an]
그냥 실행시 오류남(인덱스오류)
실행시 => java A 10 20 30 
만약 java A 10 20 30 40 50 하면 인덱스오류는 나지않지만 10 20 30 만 출력됨
 
 
# 문자열값을 정수값으로 바꾸기
 int 변수명=Integer.parseInt(문자열값);     //문자열값에는 숫자로된문자만 가능 => "10" , "30"  가능
                                                                                                                   10  , "삼백" 불가능 
[ex]
class A{
 public static void main(String[] args){
  String a="100";
  int b=Integer.parseInt(a);

  System.out.println(a+200); // 100200
  System.out.println(b+200); // 300
 }
}

 
[ex] NumberFormatException이라는 실행에러발생~
class A{
 public static void main(String[] args){
  int n=Integer.parseInt("삼백");
  System.out.println(n+100);
 }
}

[an] 문자열의 형식이 숫자값이 아닐경우 정수형으로 바꿔줄 수 없기 때문에 
 NumberFormatException이라는 실행오류가 발생한다.

[ex] 아래와 같이 실행될 수 있도록 소스코드를 완성하시오.
[exec] java A -1
 음수
[exec] java A 5
 양수
[exec] java A 0
 영

[an]
//if조건문을 이용할경우
class A{                                    
 public static void main(String[] args){

  int num=Integer.parseInt(args[0]);
  if(num==0){
   System.out.println("영");
  }else if(num>0){
   System.out.println("양수");
  }else{
   System.out.println("음수");
  }
 }
}
//삼항연산자를 이용할경우
class B{
 public static void main(String args[]){

  int num=Integer.parseInt(args[0]);

  String a= (num>=0) ? ((num==0) ? "영" :"양수")  : "음수";

  System.out.println(a);
 }
}


 
 

# 메서드호출방식
1. 값전달방식  call by value
2. 주소값전달방식 call by reference
 
[ex] call by reference (말그대로 주소값을 전달(객체를전달 )
class A{
 public static void main(String[] args){
  B o=new B();
  o.m(args);             //args는 주소값임.... 주소값을 m(String[] a) 메서드로  전달
 }
}
class B{
 void m(String[] a){
  System.out.println(a[0]);
  System.out.println(a[1]);
  System.out.println(a[2]);
 }
}

 
[ex] call by value ( 말그대로 값을 전달 )
class A{
 public static void main(String[] args){
  B o=new B();
  o.m(args[0],args[1],args[2]);            //args[0],args[1],args[2]는 각각 그냥 값임...
                                           //값을 m(String a, String b, String c) 메서드로 전달
 }
}
class B{
 void m(String a, String b, String c){
  System.out.println(a);
  System.out.println(b);
  System.out.println(c);
 }
}

 
[ex] 지역변수a의 값 100이 출력되게하려면??
class A{
 int a=200;
 public static void main(String[] args){
  int a=100;

  B o=new B();
  o.m();
 }
}
class B{
 void m(){
  A o=new A();
  System.out.println(o.a);
  //here
 }
}

 
[an]
class A{
 int a=200;
 public static void main(String[] args){
  int a=100;

  B o=new B();
  o.m(a);                                  //매개변수를 이용
 }
}
class B{
 void m(int c){                         //매개변수의 자료형을 맞추어줌
  A o=new A();
  System.out.println(o.a);
  System.out.println(c);           //매개변수를 통해 받은 a=100의값을 그대로 출력
 }
}

 
 
[ex] 오류났을시 용어 
class A{
 public static void main(String[] args){
  B o=new B();
  o.m(100); //    100=actual argument
 }
}
class B{
 void m(int n){  // n=formal argument
  System.out.println(n);
 }
}
 

#  메서드오버라이딩 : 상속관계일때 부모메서드를 자식클래스에서 메서드를 재정의하는것
    메서드오버로딩 : 메서드의 이름이 같은것이 여러개선언되어 있는 경우(매개변수의 개수나 자료형으로 구분)

[ex] 오버로딩 규칙!!!
class A {
       public static void main(String[] args) {
              B o = new B();
              o.m(); // 1
              o.m(100, 200); // 3
       }
}

class B {            // B클래스에 선언된 4가지 종류의 메서드는 메서드오버로딩으로
                     // 4가지다 다르기때문에 오류X
       void m() {
              System.out.println(1);
       }

       void m(int n) {
              System.out.println(2);
       }

       void m(int n, int n2) {
              System.out.println(3);
       }

       void m(String n) {
              System.out.println(4);
       }
}

 
[ex]
class A{
 public static void main(String[] args){
  B o=new B();
  o.m(1);
  int n=o.m(100,0);
  System.out.println(n); // 300
  System.out.println(o.m("aaa")); // aaa
 }
}
class B{
 void m(){
  System.out.println(1);
 }
 void m(int n){
  System.out.println(2);
 }
 int m(int n, int n2){
  System.out.println(3);
  return 300;
 }
 String m(String n){
  System.out.println(4);
  return n;
 }
}
[an]
2
3
300
4
aaa
 
 
[ex] 컴파일에러가 발생하는 이유는?
class A{
 void m(){
  System.out.println(1);
 }
}
class B extends A{
      void m(){                       //오버라이딩
            System.out.println(2);
      }
      void m(String a){               //오버로딩
            System.out.println(3);
      }
      int m(){                        //int m(int a) 이렇게하거나 오버로딩규칙에 맞게 바꿔줘야함
            return 4;
      }
}

 

[ex] 실행결과는?
class A{
      void m(){
            System.out.println(1);
      }
}
class B extends A{
      void M(){                     //대소문자구분...이거는 오버라이딩이 아님(대소문자틀려서)
            System.out.println(2);
      }
}
class C함{
      public static void main(String args[]){
            B o=new B();
            o.m();
      }     
}


[ex] 오버라이딩시 가독성을 높임(이렇게 써주면 이것이 오버라이딩 했다는걸 알수있음)(속도는상관없음)
class A{
     @Override public String tostring(){                   //대문자로
            return "aaa";
      }
}

 
# 메서드오버라이딩
 메서드의 선언부는 동일해야한다.
 private메서드는 오버라이딩할 수 없다.
 접근제어자의 범위는 좁아질 수 없다. public > protected > default > private

[ex] 컴파일에러발생하는 이유는?    // 자식이 부모보다 접근제어자 범위가 더 좁아질수없음 
// 근데 이거 안되네? 무슨 에러인지 모르겠음...
class A{                   // 부모의 접근제어자가 public이면 자손은 그이상이어야함 => public
 public void m(){
       System.out.println("aa");
 }
}
class B extends A{
  public static void main(String[] args){
     void m(){                            //public이 붙어야함
       System.out.println("bb");
      }
  }
}


 


# 생성자 : 객체를 생성할때 멤버변수의 초기값을 설정하기 위해 존재한다.
             객체생성과동시에 멤버변수의 초기값을 설정!

[ex] 실행결과는?
class A{
 A(String s){
  System.out.println(s);
 }
}
class B{
 public static void main(String args[]){
  A o=new A("aa");                                  //객체생성과동시에 값전달!
 }
}

 
[ex] 컴파일될 수 있도록 생성자를 선언하시오.
class A{
 A(String s){
  System.out.println(s);
 }
 //here
}
class B{
 public static void main(String args[]){
  A o1=new A("aa");
  A o2=new A("bb");
  A o3=new A(100);                     //오류내용에 actual argument에러뜸
 }
}

[an]
 A(int s){ 
  System.out.println(s);
 }

[ex] 첫번째 소스코드가 컴파일될 때 두번째 소스코드로 변경된다.
 그러나 클래스내에 생성자가 선언되어 있을경우 기본생성자는 선언되지 않는다.
class A{
}
-----------------------
import java.lang.*;
class A extends Object{
 A(){    // 기본생성자,인자없는생성자         //생성자의 이름은 클래스이름과 같아야한다.
 }                                          //생성자는 리턴값이 없다.
}

 
[ex]
class Car{
 String color;
 int speed;
 Car(String s,int speed){
  color=s;
  this.speed=speed;
 }
 @Override public String toString(){
  return color+","+speed;
 }
}
class A{
 public static void main(String args[]){
  Car car1=new Car("red",100);
  Car car2=new Car("yellow",200);
  System.out.println(car1);            //car1.toString() 이 생략되어있어서... 즉 car1객체의
                                       // toString()메서드를 실행시 리턴값으로
                                       // car1의 color+","+speed 가 출력됨
  System.out.println(car2);
 }
}