6일차 - 생성자 & 패키지

은채의 성장통·2025년 6월 4일

KCC정보통신

목록 보기
7/30

노션 링크

1.생성자

1. 생성자 선언 및 사용

  • 객체를 생성할 떄 new다음에 오는 것을 생성자라고 한다.
public	Pen(String	init_color,	int	init_price)	{
	color	=	init_color;
	price	=	init_price;
	System.out.println("생성자를	이용하여	color,	price를	초기화");
}

public	class	PenConstructorExample	{
	public	static	void	main(String[]	args)	{
		Pen	blackPen	=	new	Pen();	//	에러
		blackPen.write(1); //	에러
		Pen	redPen	=	new	Pen("빨간",	900);
		redPen.write(2);
	}
}

1.1 기본 생성자

  • 인자가 없고 클래스 이름과 동일할떄 → 기본생성자의 이름은 클래스의 이름과 동일하다.
public pen() {}

1.2 생성자 중복

  • 하나의 클래스에 생성자를 여러개 선언해 두는 것을 생성자 중복이라고 한다.
  • 중복해서 정의하는 이유는 여러가지 상황에서 객체를 생성하는 유연성을 제공하기 위함이다.
  • this는 현재 객체의 멤버(변수 또는 메서드)를 참조하기 위해 사용한다.
 public	class	Book	{
	 String	title;
		String	author;
		int	pageCount;
		
		//	기본	생성자
		public	Book()	{	
		//	모두	기본값	설정
			this.title	=	"Unknown	Title";
			this.author	=	"Unknown	Author";
			this.pageCount	=	0;
		}
		//	일부	정보만	받는	생성자
		public	Book(String	title,	String	author)	{
			this.title	=	title;
			this.author	=	author;
			this.pageCount	=	0;	//	나머지는	기본값으로	초기화
		}
		
		//	모든	정보를	받는	생성자
		public	Book(String	title,	String	author,	int	pageCount)	{
			this.title	=	title;
			this.author	=	author;
			this.pageCount	=	pageCount;
		}
	}

1.3 this의 사용

  • this는 현재 객체를 사용하며 같은 클래스내에서 멤버 변수 및 메서드를 참조할 떄 사용한다. this. 은 주로 생성자나 메서드에서 멤버변수를 참조하는 용도 사용한다.
  • this()는 같은 클래스 내에서 다른 생성자를 호출한다.

public class Student {
    private String name;
    private int age;
    private String major;

    // 생성자
    public Student(String name, int age, String major) {
        this.name = name;
        this.age = age;
        this.major = major;
    }

    // 학생 정보 출력 메서드
    public void displayStudentInfo() {
        System.out.printf("이름 : %s , 나이 : %d , 전공 : %s \n", name, age, major);
    }
}

public class StudentTest {
    public static void main(String[] args) {
        // 객체 생성
        Student student1 = new Student("홍길동", 20, "컴퓨터 공학");
        Student student2 = new Student("김철수", 22, "전자 공학");

        // 학생 정보 출력
        System.out.println("첫 번째 학생 정보:");
        student1.displayStudentInfo();

        System.out.println("\n두 번째 학생 정보:");
        student2.displayStudentInfo();
    }
}

2.메서드 중복과 가변인자

Java 메서드 중복, 가변 인자, 제네릭과 타입 추론 정리

2.1 메서드 중복 (Method Overloading)

메서드 중복이란 같은 이름의 메서드를 여러 개 선언할 수 있도록 하는 기능입니다. 단, 매개변수의 타입, 개수, 순서가 달라야 합니다.

public class MyClass {
    public void abc(int i, String str) {
        System.out.println("정수와 문자열이 입력됨");
    }
    public void abc(double a, double b) {
        System.out.println("부동소수점이 입력됨");
    }
    public void abc(String str) {
        System.out.println("문자열이 입력됨");
    }
}

public class OverloadingExample {
    public static void main(String[] args) {
        MyClass obj = new MyClass();
        obj.abc(100, "자바");     // 정수와 문자열이 입력됨
        obj.abc(3.5, 4.3);       // 부동소수점이 입력됨
        obj.abc("자바");         // 문자열이 입력됨
        obj.abc(100, 200);       // abc(double, double) 메서드가 호출됨
    }
}

메서드 오버로딩을 활용하면 코드의 가독성과 재사용성이 높아집니다.


2.2 가변 인자 (Variable Arguments)

매개변수의 개수를 미리 정할 수 없을 때 가변 인자(...)를 사용하여 여러 개의 값을 받을 수 있습니다.

public class Calculator {
    public int sum(int... values) {  // 가변 인자 사용
        int sum = 0;
        for (int value : values) {
            sum += value;
        }
        return sum;
    }

    public static void main(String[] args) {
        Calculator calc = new Calculator();
        System.out.println(calc.sum(1, 2, 3, 4, 5)); // 15 출력
    }
}

가변 인자 주의사항

  • 가변 인자는 배열과 함께 사용할 수 없습니다 (sum(int[], int...) 같은 형식은 불가능).
  • 가변 인자는 메서드의 마지막 매개변수로만 사용할 수 있습니다.
public class Logger {
    public void log(Object... args) {
        String message = (String) args[0];
        Exception error = (Exception) args[1];
        System.out.println("로그 메시지: " + message);
        error.printStackTrace();
    }

    public static void main(String[] args) {
        Logger logger = new Logger();
        logger.log("에러 발생!", new RuntimeException("예외 정보"));
    }
}

가변 인자 내부에서 형변환을 통해 특정 자료형을 구별하여 사용할 수 있습니다.


2.3 제네릭 (Generics)

제네릭은 타입을 지정하여 코드의 안정성과 재사용성을 높이는 기법입니다.

제네릭 없이 사용하는 경우

class Box1 {
    private Object value;

    public void setValue(Object value) {
        this.value = value;
    }

    public Object getValue() {
        return value;
    }
}

public class NonGenericExample {
    public static void main(String[] args) {
        Box1 stringBox = new Box1();
        stringBox.setValue("Hello, Java!");

        Box1 intBox = new Box1();
        intBox.setValue(42);

        // 형변환 필요
        String stringValue = (String) stringBox.getValue();
        int intValue = (int) intBox.getValue();

        System.out.println(stringValue + " " + intValue);
    }
}

형변환이 필요하여 실수로 잘못된 타입을 할당하면 오류가 발생할 가능성이 높습니다.

제네릭을 사용하는 경우

class Box2<T> {
    private T value;

    public void setValue(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }
}

public class GenericExample {
    public static void main(String[] args) {
        Box2<String> stringBox = new Box2<>();
        stringBox.setValue("Hello, Java!");

        Box2<Integer> intBox = new Box2<>();
        intBox.setValue(42);

        // 형변환 불필요
        String stringValue = stringBox.getValue();
        int intValue = intBox.getValue();

        System.out.println(stringValue + " " + intValue);
    }
}

제네릭을 사용하면 형변환 없이 안전하게 데이터를 처리할 수 있습니다.


2.4 타입 추론 (Type Inference)

타입 추론이란 컴파일러가 코드 문맥을 통해 타입을 자동으로 결정하는 기능입니다.

제네릭 타입 추론 예제

// 타입 추론 사용 전
List<String> myList = new ArrayList<String>();

// 타입 추론 사용 후 (<> 내부 타입을 생략할 수 있음)
List<String> myList = new ArrayList<>();

var를 활용한 타입 추론 예제

// 올바른 사용
var myVar = "Hello, Java!";

// 오류: 초기화되지 않은 변수는 사용할 수 없음
// var uninitializedVar;

// 잘못된 사용 (var로 선언된 변수는 다른 타입으로 재할당 불가)
var x = 10;  // int 타입으로 추론
// x = "Hello";  // 오류 발생

var는 코드 가독성을 위해 특정 상황에서만 사용하는 것이 좋습니다.

람다 표현식에서 타입 추론 예제

// 타입 명시 (사용 전)
MyFunction myFunc = (String s) -> s.length();

// 타입 추론 (사용 후)
MyFunction myFunc = (s) -> s.length();

추가 개념

제네릭의 와일드카드 (? 사용)

public void printBox(Box2<?> box) {  // 어떤 타입이든 받을 수 있음
    System.out.println(box.getValue());
}

<?>를 사용하면 모든 타입을 받을 수 있어 범용성이 높아집니다.

💡 타입 제한 (extends 활용)

public <T extends Number> void printNumber(T num) {
    System.out.println("숫자: " + num);
}

T extends Number를 사용하면 숫자 타입만 허용할 수 있습니다.


3. 패키지

3.1 import 선언과 패키지

  • import 구문은 다른 패키지의 클래스나 인터페이스를 사용할 때 전체 경로를 반복해서 쓰지 않도록 도와주는 문법입니다.

예제

import java.util.ArrayList;

public class MyArrayListExample {
    public static void main(String[] args) {
        ArrayList<String> myList = new ArrayList<>();
        // myList를 이용한 작업 수행
    }
}
  • import java.util.ArrayList;을 사용하면 ArrayList를 전체 패키지 경로 없이 바로 사용할 수 있습니다.

3.1.1 import static 선언

  • import static을 사용하면 특정 클래스의 정적(static) 멤버를 직접 참조할 수 있습니다.
  • 예를 들어 Math.sqrt를 가져오면 sqrt(값) 형태로 간편하게 사용할 수 있습니다.

예제

import static java.lang.Math.sqrt;

public class ImportStaticExample {
    public static void main(String[] args) {
        double result = sqrt(16.0);
        System.out.println("Square root of 16 is: " + result);
    }
}

✔️ Math.sqrt(16.0) 대신 sqrt(16.0)만 사용해도 되므로 코드가 더 간결해집니다.


3.1.2 패키지 선언

  • 패키지는 관련된 클래스 및 인터페이스를 그룹화하고 이름 충돌을 방지합니다.
  • 패키지 이름은 소문자로 작성하는 것이 일반적입니다.

예제

package hello;

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

✔️ package hello; 선언을 통해 hello라는 패키지 안에 HelloWorld 클래스를 포함합니다.


3.1.3 패키지 은닉 (접근 제한자)

접근 제한자설명
public어떤 클래스에서든 접근 가능
protected동일 패키지 또는 상속받은 클래스에서 접근 가능
default (아무것도 안 씀)동일 패키지 내에서만 접근 가능
private해당 클래스 내부에서만 접근 가능

예제

package com.example.mypackage;

public class MyClass {
    // 패키지 내에서만 접근 가능한 메서드
    void packagePrivateMethod() {
        System.out.println("패키지 내부에서만 접근 가능");
    }
}
package com.example.otherpackage;

import com.example.mypackage.MyClass;

public class AnotherClass {
    public static void main(String[] args) {
        MyClass myObject = new MyClass();
        // myObject.packagePrivateMethod(); // ❌ 컴파일 오류 발생 (다른 패키지에서 접근 불가)
    }
}

✔️ packagePrivateMethod()default 접근 수준이므로 같은 패키지 내에서만 호출할 수 있습니다.


4. 클래스 모델

4.1 속성(Attribute)

  • 객체의 정보나 상태를 표현하는 변수입니다.
  • 속성은 하나의 구체적인 정보를 나타내야 합니다.
  • 속성 이름은 정보를 가장 정확하게 표현하는 단어로 정합니다.

✔️ 클래스 다이어그램에서는 속성을 필드(변수)로 표현합니다.

예제

public class Car {
    String brand;  // 자동차 브랜드
    int year;      // 제조 연도

    public Car(String brand, int year) {
        this.brand = brand;
        this.year = year;
    }
}

✔️ Car 클래스는 brandyear 속성을 갖고 있으며, 자동차의 브랜드와 제조 연도를 나타냅니다.


4.2 클래스 다이어그램

  • 클래스의 구조를 시각적으로 표현하는 다이어그램입니다.
  • 속성, 메서드, 접근 제한자 등을 정리하여 클래스 관계를 명확히 보여줍니다.

예제 (클래스 다이어그램)

+---------------------+
|       Car          |
+---------------------+
| - brand: String    |
| - year: int        |
+---------------------+
| + Car(brand, year) |
+---------------------+

✔️ Car 클래스에는 brandyear 속성이 있으며, 생성자를 통해 초기화됩니다.

4.2.1 속성과 연산의 표현과 자바코드

public class Rectangle {
    // 클래스 변수
    public static int count = 0;

    // 인스턴스 변수
    private int width;
    private int height;
    private double area;

    // 생성자
    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
        this.setArea();
    }

    // 너비 설정 및 반환 메서드
    public void setWidth(int width) {
        this.width = width;
        setArea();
    }

    public int getWidth() {
        return width;
    }

    // 높이 설정 및 반환 메서드
    public void setHeight(int height) {
        this.height = height;
        setArea();
    }

    public int getHeight() {
        return height;
    }

    // 면적 설정 및 반환 메서드
    public void setArea() {
        this.area = width * height;
    }

    public double getArea() {
        return area;
    }
}

4.2.2 관계

  • 클래스와 인터페이스의 관게를 표기하는 것

public class Customer {
	String name;
	char gender;
	String email;
	int birthYear;
	
	public Customer(String name, char gender, String email, int birthYear) {
		this.name = name;
		this.gender = gender;
		this.email = email;
		this.birthYear = birthYear;
	}
	
	public Customer() {
		
	}
}
profile
인생 별거 없어

0개의 댓글