package class_;

public class VarArgs {

   public int sum(int... ar) {  // 배열화
      int hap = 0;
      for(int i = 0; i <ar.length; i++) {
         hap += ar[i];

      }   return hap;
   }
//-----------------------------------------------------
   public static void main(String[] args) {
      VarArgs va = new VarArgs();
      System.out.println("합 = " + va.sum(10, 20));  // va. 객체값  // 함수 호출시 구현부 필요
      System.out.println("합 = " + va.sum(10, 20, 30));  // va. 객체값  // 함수 호출시 구현부 필요
      System.out.println("합 = " + va.sum(10, 20, 30, 40));  // va. 객체값  // 함수 호출시 구현부 필요
   }
}

매개변수 ar은 int... 형태로 선언되어 있으며, 이는 가변 인자를 나타냅니다.
메서드 내부에서는 이 가변 인자 ar을 배열처럼 사용하여 각 숫자들을 더한 후,
그 합계를 hap 변수에 누적합니다.

가변 인자를 사용하는 메서드를 호출할 때, 해당 메서드에 정해진 개수의 인자를 전달할 필요 없이 필요한 개수만큼 인자를 전달할 수 있습니다.
예를 들어, va.sum(10, 20)은 10과 20을 전달하여 합을 구하고, va.sum(10, 20, 30)은 10, 20, 30을 전달하여 합을 구합니다.

생성자 (Constructor) 메소드

객체 초기화

  1. 생성자명은 반드시 클래스명과 동일하다.

  2. 자동호출 - 클래스를 메모리에 생성 시 (new 할때)

  3. return Type(결과형)이 없다.

  4. 클래스 안에 생성자가 하나도 없을 시에는 자동으로 기본(default) 생성자 호출 기본
    생성자 - 인수가 없는 메소드

Static클래스

  1. 메모리 static 영역에 한번만 생성된다.
    → 초기화 한번만 수행 모든 객체가 공유한다. (공유변수)

  2. static 메소드에서는 static 변수만 사용 가능 static 메소드에서는 this 를 참조할 수 없다

  3. static 변수나 메소드는 호출시 클래스명으로 직접 호출 할 수 있다.
    객체로도 호출이 가능하다

  4. static{ } - 초기화 영역
    생성자보다도 먼저 수행한다.

★ import static
: 간단하게 static 상수 또는 메소드를 호출할 때 사용

★★통계 누적을 구할 땐 Static을 사용해야 한다★★
소모되지 않고 누적되기 때문에

package class_;

class StaticTest {
    private int a; 				//월드, 인스턴스, 변수
    private static int b; 		//필드, 클래스 변수

   								// public 생성자는 void 절대로 않쓴다.
    static {
        System.out.println("static 초기화 영역");
    }

public StaticTest() {
	System.out.println("기본 생성자");
	a = 10;
}


public void calc() {
a++;
b++;
}
    public void disp() {
        System.out.println("a = " + this.a + " b = " + StaticTest.b);
    }

public static void output(){
	System.out.println("static 메소드");
//        	System.out.println("a = " + this.a + " b = " + StaticTest.b);

        }
    }
//------------------------------------------
public class StaticMain{

public static void main(String[] args) {
	StaticTest aa = new StaticTest();
	aa.calc();
	aa.disp();
	System.out.println("-------------------");
	
	StaticTest bb = new StaticTest();
	aa.calc();
	aa.disp();
	System.out.println("-------------------");
	
	StaticTest cc = new StaticTest();
	aa.calc();
	aa.disp();
	System.out.println("-------------------");
	
	StaticTest.output();  // 클래스명, 메소드명()
	aa.output(); // 객체, 메소드명()객체를 따로 불러도 된다.
    }
}


[문제] 과일 판매량 구하기

월별 매출합계도 구하시오

클래스 : Fruit
필드   : pum, jan, feb, mar, tot
        sumJan, sumFeb, sumMar

메소드 : 생성자(품명, 1월, 2월, 3월)
        calcTot()
        display() - 품명, 1월, 2월, 3월, 합계 출력
        public static void output() 1월 합계, 2월 합계, 3월 합계 출력

클래스 : FruitMain

[실행결과]
________________________________
PUM		JAN   FEB   MAR		TOT
________________________________
사과    100    80    75     255
포도     30    25    10     65
딸기     25    30    90     145
________________________________
       155    135   175				output()로 처리


package constructor;

class Fruit{
    private String pum;
    private int jan;
    private int feb;
    private int mar;
    private int tot;
    private static int sumJan; // 독립적으로 따로 잡아줘야함 static
    private static int sumFeb;
    private static int sumMar;

// 생성자를 써서!!!!!!!!!!!!!!!!!!!!!!!!void 절대 안됨
public Fruit(String pum, int jan, int feb, int mar) {
// void를 사용함...	public void season(String pum, int jan, int feb, int mar) {
        this.pum = pum;
        this.jan = jan;
        this.feb = feb;
        this.mar = mar;
    }

public void calcTot() {
	tot=jan+feb+mar;
	
	sumJan += jan;
	sumFeb += feb;
	sumMar += mar;
}

내가 한 것들...

//	
//	public void sumJan() {
//		sumJan += jan;
//		System.out.println(sumJan);
//	}
//	
//	public void sumFeb() {
//		sumFeb += feb;
//		System.out.println(sumFeb);
//	}
//	
//	public void sumMar() {
//		sumMar += mar;
//		System.out.println(sumMar);
//	}



public void display() {
	System.out.println(pum+"\t"+jan+"\t"+feb+"\t"+mar+"\t"+tot);
}

public static void output() {
	System.out.println("합계"+"\t"+sumJan+"\t"+sumFeb+"\t"+sumMar);
	}
}
//--------------------------------------------
public class FruitMain {

public static void main(String[] args) {
	System.out.println("-------------------------------------");
	System.out.println("PUM\tJAN\tFEB\tMAR\tTOT");
	System.out.println("-------------------------------------");
	
	Fruit apple = new Fruit("사과",100,80,75);
	apple.calcTot();
	apple.display();
	
	Fruit grape = new Fruit("포도",30,25,10);
	grape.calcTot();
	grape.display();
	
	Fruit strr = new Fruit("딸기",25,30,90);
	strr.calcTot();
	strr.display();
	
	System.out.println("-------------------------------------");
	Fruit.output();

    }
}


중첩클래스

has~a 관계 다른 클래스 내부에 정의 되는 클래스를 중첩클래스(nested class)라고 한다.

중첩클래스는 독립적으로 오브젝트로 만들어질 수 있는 스태틱 클래스(static class)와 자신이 정의된 클래스의 오브젝트 안에서만 만들어질 수 있는 내부 클래스(inner class)로 구분된다.

내부클래스는 다시 범위에 따라 세 가지로 구분된다.

멤버필드처럼 오브젝트 레벨에 정의되는 멤버 내부 클래스(member inner class)와 메소드 레벨에서 로컬변수를 선언하여 사용하듯 선언된 메소드 내에서만 사용 가능한 로컬 내부 클래스(local inner class), 그리고 이름을 갖지 않는 익명 내부 클래스(anonymous inner class)다.

상속 (inheritance)

is~a 관계 ~이다
클래스의 재 구현

  1. 상속받는 클래스는 상속해주는 클래스의 생성자와 private 를 제외한 모든 것을 상속받는다.
  2. Super class : 상속해 주는 클래스(부모)
    Sub class : 상속받는 클래스(자식)
  3. 접근제한자 protected 는 Sub class 에서 접근이 가능하다
  4. Sub class 로 객체를 생성하면 Super class 와 자신의 생성자를 모두 호출한다.
  5. 다중상속을 할 수 없다.
    -> 다중상속을 해결하기 위해 interface 사용(상속 받은 것처럼 사용)

[형식]
class Sub 클래스명 extends Super 클래스명{ }

package inheritance;

public class Super {
    protected double weight, height;

// 인수가 2개인 생성자 - weight, height

public Super() {
	System.out.println("나는 Super의 기본 생성자입니다.");
}

public Super(double weight, double height) {
	System.out.println("나는 일반 생성자입니다.");
	this.weight = weight;
	this.height = height;
}

public void disp() {
	System.out.println("몸무게 = " + this.weight);
	System.out.println("키 = " + this.height);
	}
}
    -----------------class Sub-----------------
    package inheritance;

// 기본생성자를 만들지 않고 일반 생성자를 주석 처리하면 Sub에 에러 난다.
public class Sub extends Super{

private String name;
private int age;

public Sub(){
	System.out.println("나는 Sub의 기본 생성자입니다.");
}

public static void main(String[] args) {
	Sub aa = new Sub();	
    }
}

Sub(main)에서 실행 했을 때도 Super 클래스(부모 클래스)도 같이 출력된다.

package inheritance;

public class Sub extends Super{ 
// 기본생성자를 만들지 않고 일반 생성자를 주석 처리하면 Sub에 에러 난다.

private String name;
private int age;

public Sub(){
	System.out.println("나는 Sub의 기본 생성자입니다.");
}
public Sub(String name,int age, double weight, double height){
	System.out.println("나는 Sub의 기본 생성자입니다.");
	
	this.name = name;
	this.age = age;
	this.weight = weight; // this.weight = weight;
	this.height = height; // this.height = height;
}

public void output() {
	System.out.println("이름 = "+name);
	System.out.println("나이 = "+age);
	System.out.println("몸부게 ="+weight);
	System.out.println("키 = "+name);
}

public static void main(String[] args) {
	Sub aa = new Sub();	
	System.out.println("--------------------------");
	Sub bb = new Sub("홍길동", 25, 85.3, 183.5);
	bb.disp(); //키 몸무게
	System.out.println();
	bb.output();
	System.out.println("--------------------------");
	
	Super cc = new Sub("라이언",30, 78.3, 178.9);
	// cc.output(); - 비록 Sub 클래스로 생성했지만 참조 값을 부모만 했기 때문에 호출할 수 없다. 
}
}

//Sub 클래스 생성을 하면 ---- 자신의 클래스와 부모 클래스를 모두 생성한다.
//                ---- 생성자 2번 호출 (대신 부모는 기본 생성자를 호출한다.)

cc.output( )으로 호출할 수 없다.

package inheritance;

public class Child extends Super{

private String name;
private int age;

public Child(){
	System.out.println("나는 Child 기본 생성자입니다.");
}
public Child(String name, int age, double weight, double height){
	System.out.println("나는 Child 생성자입니다.");
	
	this.name = name;
	this.age = age;
	super.weight = weight;
	super.height = height;
}
	// this.weight = weight;
	// this.height = height;
	
	public void output() {
		System.out.println("이름 = "+name);
		System.out.println("나이 = "+age);
		System.out.println("몸부게 ="+weight);
		System.out.println("키 = "+name);
}

public static void main(String[] args) {
	Child bb = new Child("홍길동", 25, 85.3, 183.5);
	bb.disp();
	System.out.println("--------------------------");
	
	Super cc = new Child("라이언", 30, 78.3, 178.9);
	cc.disp();
	}
}



cc는 Super의 disp( )가 아닌 Child의 disp()로 출력 이게 바로 override

같은 이름을 가지는 순간 자기 자신 것만 사용한다.
(오타 AA->CC)


Override 메소드

  1. Super 클래스와 Sub 클래스에 똑같은 메소드가 존재
  2. 모든 우선권은 Sub 클래스가 갖는다.
  3. Super, Sub 클래스의 접근제어자(Modifier)는 틀려도 되지만
    Super 보다 Sub 클래스의 접근제어자(Modifier)가 더 커야한다.
Overload						             Override
하나의 클래스 안에 있어야 하고                   부모와 자식 클래스의 관계
메소드의 이름이 똑같다                          한 글자도 틀림없이 다 똑같아야한다.
인수형 또는 인수 개수가 틀릴 경우                단, 접근 제어자는 틀려도 된다.
                                             단, 자식 클래스가 더 커야 한다.
                                            (private-protected-public)
package inheritance;

import java.util.Scanner;

class Shape{
    protected double area;
    protected Scanner scan = new Scanner(System.in);

public Shape() {
	System.out.println("Shape 기본생성자");
}
public void calcArea() {
	System.out.println("도형을 계산합니다.");
}
public void dispArea() {
	System.out.println("도형을 출력합니다.");
}	
}
//------------------------------------------

class Sam extends Shape{
    protected int base, height;

public Sam() {
    System.out.println("Sam의 기본생성자");
    System.out.print("밑변 : ");
    base = scan.nextInt();
    System.out.println("높이 : ");
    height = scan.nextInt();
    }
@Override
public void calcArea() {
    area = base * height;
}
Override
public void dispArea() {
    System.out.println("삼각형 넓이 = " + area);
    }
}

//------------------------------------------
public class ShapeMain {

public static void main(String[] args) {
	Sam sam = new Sam();
	sam.calcArea();
	sam.dispArea();
    }
}

package inheritance;

import java.util.Scanner;

class Shape{
    protected double area;
    protected Scanner scan = new Scanner(System.in);

public Shape() {
	System.out.println("Shape 기본생성자");
}
public void calcArea() {
	System.out.println("도형을 계산합니다.");
}
public void dispArea() {
	System.out.println("도형을 출력합니다.");
	}
}
//------------------------------------------

class Sam extends Shape{
    protected int base, height;

public Sam() {
    System.out.println("Sam의 기본생성자");
    System.out.print("밑변 : ");
    base = scan.nextInt();
    System.out.print("높이 : ");
    height = scan.nextInt();
    }
@Override
public void calcArea() {
    area = base * height;
}
public void dispArea() {
    System.out.println("삼각형 넓이 = " + area);
    }
}
//------------------------------------------
class Sa extends Shape{
protected int width, height;

public Sa() {
	System.out.println("Sa의 기본생성자");
	System.out.print("가로 : ");
	width = scan.nextInt();
	System.out.print("세로 : ");
	height = scan.nextInt();
	}
@Override
public void calcArea() {
	area = width * height;
}
public void dispArea() {
	System.out.println("사각형 넓이 = " + area);
	}
}

//------------------------------------------
class Sadari extends Shape{
    protected int top, bottom, height;

public Sadari() {
    System.out.println("Sadari의 기본생성자");
    System.out.print("윗변 : ");
    top = scan.nextInt();
    System.out.print("밑변 : ");
    bottom = scan.nextInt();
    System.out.print("높이 : ");
    height = scan.nextInt();
    }
@Override
public void calcArea() {
    area = (top+bottom)*height/2;
}
public void dispArea() {
    System.out.println("사다리꼴 넓이 = " + area);
    }
}
//------------------------------------------
public class ShapeMain {

public static void main(String[] args) {
	Sam sam = new Sam();
	sam.calcArea();
	sam.dispArea();
	
	System.out.println();
	
	Sa sa = new Sa();
	sa.calcArea();
	sa.dispArea();
	
	System.out.println();
	
	Sadari sadari = new Sadari();
	sadari.calcArea();
	sadari.dispArea();
	
    }
}

★★★상속의 다형성

Sam sam = new Sam( );
같은 것은 1:1관계로 결합도가 100%여서 다른 브랜드의 리모콘으로 텔레비젼을 조절할 수 없다.
하지만 부모는 만능 리모콘
위와 같은 식으로

package inheritance;

import java.util.Scanner;

class Shape{
    protected double area;
    protected Scanner scan = new Scanner(System.in);

public Shape() {
	System.out.println("Shape 기본생성자");
}
public void calcArea() {
	System.out.println("도형을 계산합니다.");
}
public void dispArea() {
	System.out.println("도형을 출력합니다.");
	}
}
//------------------------------------------

class Sam extends Shape{
    protected int base, height;

public Sam() {
    System.out.println("Sam의 기본생성자");
    System.out.print("밑변 : ");
    base = scan.nextInt();
    System.out.print("높이 : ");
    height = scan.nextInt();
    }
@Override
public void calcArea() {
    area = base * height;
}
public void dispArea() {
    System.out.println("삼각형 넓이 = " + area);
    }
}
//------------------------------------------
class Sa extends Shape{
protected int width, height;

public Sa() {
	System.out.println("Sa의 기본생성자");
	System.out.print("가로 : ");
	width = scan.nextInt();
	System.out.print("세로 : ");
	height = scan.nextInt();
	}
@Override
public void calcArea() {
	area = width * height;
}
public void dispArea() {
	System.out.println("사각형 넓이 = " + area);
	}
}

//------------------------------------------
class Sadari extends Shape{
    protected int top, bottom, height;

public Sadari() {
    System.out.println("Sadari의 기본생성자");
    System.out.print("윗변 : ");
    top = scan.nextInt();
    System.out.print("밑변 : ");
    bottom = scan.nextInt();
    System.out.print("높이 : ");
    height = scan.nextInt();
    }
@Override
public void calcArea() {
    area = (top+bottom)*height/2;
}
public void dispArea() {
    System.out.println("사다리꼴 넓이 = " + area);
    }
}
	// 다형성 (상속을 하는 100%이유)
	Shape shape;
	shape = new Sam(); // 부모는 자식 클래스를 참조 할 수 있어요
	shape.calcArea();
	shape.dispArea();
	
	System.out.println();
	
	shape = new Sa(); // 부모는 자식 클래스를 참조 할 수 있어요
	shape.calcArea();
	shape.dispArea();
	
	System.out.println();
	
	shape = new Sadari(); // 부모는 자식 클래스를 참조 할 수 있어요
	shape.calcArea();
	shape.dispArea();
	}
}


강제 형변환

오버라이딩은 변수에게는 해당되지 않는다.

package inheritance;

class AA{
    public int a = 3;

public void disp() {
	a += 5;
	System.out.println("AA : " + a + " ");
	}
}
//----------------------------------------------
class BB extends AA{
    public int a = 8;

public void disp() {
	this.a += 5;
	System.out.println("BB : " + a + " ");
	}
}
//----------------------------------------------
public class OverrideMain {

public static void main(String[] args) {
	BB aa = new BB();
	aa.disp();
	System.out.println("aa : " + aa.a);
	
	System.out.println();
	
	AA bb = new BB();
	bb.disp();
	System.out.println("bb : " + bb.a);
	
	System.out.println();
	
	BB cc = (BB)bb;// 현재 bb 자식=(자식)부모
	cc.disp();
	System.out.println("cc : " + cc.a); // 위 bb가 이미 13
    
    AA dd = new AA();
	dd.disp();
	System.out.println("dd : " + dd.a);
    }
}


오버라이딩 안됨


BB aa = new BB();		
aa.disp();
System.out.println("aa : " + aa.a);


AA bb = new BB();
bb.disp();
System.out.println("bb : " + bb.a);


BB cc = (BB)bb;// 현재 bb 자식=(자식)부모
cc.disp();
System.out.println("cc : " + cc.a); // 위 bb가 이미 13

그값을 그대로 받음


AA dd = new AA();
dd.disp();
System.out.println("dd : " + dd.a);


Object

클래스 생성시 항상 빠져있는 말 = (extends Object)

package inheritance;

class Test extends Object{
}

//------------------------------------------

class Sample{

@Override
public String toString() {
//오브젝트가 쥐고 있는 toString(주소)을 바꾸겠다
	return getClass() + "@개바부";
	}
}	

//------------------------------------------

class Exam{
    private String name = "홍길동";
    private int age = 25;

public String getName(){
	return name;
}
public int getAge(){
	return age;
}

@Override
public String toString() {
	return name + "\t" + age;
	}
}

//------------------------------------------

public class ObjectMain {

public static void main(String[] args) {
	Test t = new Test();
	System.out.println("객체 t = " + t); 		 	// 패키지명.클래스명@16진수
	System.out.println("객체 t = " + t.toString()); // .toString()은 Object에 가서 찾는다. 16진수
	System.out.println("객체 t = " + t.hashCode()); // 해쉬값 = 10진수 

	Sample s = new Sample();
	System.out.println("객체 s = " + s); 			// 패키지명.클래스명@16진수
	System.out.println("객체 s = " + s.toString()); // .toString()은 Object에 가서 찾는다. 16진수
	

	Exam e = new Exam();
	System.out.println("객체 e = " + e); 			// 패키지명.클래스명@16진수
	System.out.println(e.getName() + "\t" + e.getAge());
	

	/*
	class Object {
		public String toString() {}			클래스명@16진수
		public int hashCode() {}			10진수
		public boolean equals(Object ob){}	참조값 비교
	}

	class String{
		public String toString() {}			문자열
		public int hashCode() {}			10진수 (믿으면 안된다) - 문자열의 10진수는 믿으면 안돼
		 									-> 표기할 수 있는 문자열은 무한대이기 때문에 10진수로는
                                            다 표기할 수 없다.
                                            
		public boolean equals(Object ob){}	문자열 비교
	}
	 */
	
	String aa = "apple";
	System.out.println("객체 aa = " + aa); // Override 16진수가 아닌 문자열로 나오게 함
	System.out.println("객체 aa = " + aa.toString());
	System.out.println("객체 aa = " + aa.hashCode()+" (믿지는 마)");
    

    String bb = new String("apple");
	String cc = new String("apple");
	System.out.println("bb==cc : " + (bb==cc)); // false -> 주소가 같니?
	System.out.println("bb==cc : " + bb.equals(cc)); // true -> 문자열이 같니?
    

	Object dd = new Object();
	Object ee = new Object();
	System.out.println("dd==ee : " + (dd==ee)); // false -> 주소가 같니?
	System.out.println("dd==ee : " + dd.equals(ee)); // false -> 주소??
    

	Object ff = new String("apple");
	Object gg = new String("apple");
	System.out.println("ff==gg : " + (ff==gg)); // false -> 주소가 같니?
	System.out.println("ff==gg : " + ff.equals(gg)); // true -> 문자열이 같니? (오버라이드)
    


1개의 댓글

comment-user-thumbnail
2023년 7월 20일

항상 좋은 글 감사합니다.

답글 달기