반응형

클래스

6.1 객체 지향 프로그래밍

객체 지향 프로그래밍

OOP: Object Oriented Programming

부품 객체를 먼저 만들고 이것들을 하나씩 조립해 완성된 프로그램을 만드는 기법

 

6.1.1 객체란?

물리적으로 존재하는 것 (자동차, , 사람)

추상적인 것(회사, 날짜) 중에서 자신의 속성과 동작을 가지는 모든 것

객체는 필드(속성) 과 메소드(동작)로 구성된 자바 객체로 모델링 가능

현실 세계의 객체를 소프트웨어 객체로 설계하는 것을 객체 모델링(.Object Modeling)이라고 한다.

 

6.1.2 객체의 상호 작용

객체들은 서로 간에 기능(동작)을 이용하고 데이터를 주고 받음

 

객체들은 각각 독립적으로 존재하고, 다른 객체와 서로 상호작용한다. 이때 상호작용의 수단은 메서드이며 객체가 다른 객체의 기능을 이용하는 것이 메서드 호출이다. 정리하자면 객체의 상호작용은 객체 간의 메서드 호출을 의미하며 매개 값과 리턴 값을 통해서 데이터를 주고받는 것이다.

 

메소드 호출

리턴값 = 전자계산기객체.메소드(매개값1, 매개값2, ..)

 

int result = Calculator.add(10 , 20);

 

6.1.3 객체 간의 관계

객체 지향 프로그램에서는 객체는 다른 객체와 관계를 맺음

 

=>관계의 종류

집합 관계: 완성품과 부품의 관계

사용 관계: 객체가 다른 객체를 사용하는 관계

상속 관계: 종류 객체와  구체적인 사물 객체 관계

 

 

6.1.4 객체 지향 프로그래밍의 특징

객체를 사용하는 프로그램을 객체 지향 프로그래밍(OOP)이라고 한다

 

=>캡슐화(Encapsulation)->노출을 방지하기 위해서

객체의 필드, 메소드를 하나로 묶고, 실제 구현 내용을 감추는 것

외부 객체는 객체 내부 구조를 알지 못하며 객체가 노출해 제공하는 필드와 메소드만 이용 가능

필드와 메소드를 캡슐화하여 보호하는 이유는 외부의 잘못된 사용으로 인해 객체가 손상되지 않도록

자바 언어는 캡슐화된 멤버를 노출시킬 것인지 숨길 것인지 결정하기 위해 접근 제한자(Access Modifier) 사용

 

 

=>상속(Inheritance)

      상위(부모) 객체의 필드와 메소드를 하위(자식) 객체에게 물려주는 행위

      하위 객체는 상위 객체를 확장해서 추가적인 필드와 메소드를 가질 수 있음

      상속 대상: 필드와 메소드

      상속의 효과

상위 객체를 재사용해서 하위 객체를 빨리 개발 가능

반복된 코드의 중복을 줄임

  유지 보수의 편리성 제공

객체의 다형성 구현

 

 

=>다형성(Polymorphism)

같은 타입이지만 실행 결과가 다양한 객체를 대입할 수 있는 성질

       부모 타입에는 모든 자식 객체가 대입

       인터페이스 타입에는 모든 구현 객체가 대입

효과

       객체를 부품화시키는 것 가능

       유지보수 용이

 

 

6.2 객체(Object)와 클래스(Class)

현실세계: 설계도 -> 객체

자바: 클래스  ->  객체

클래스에는 객체를 생성하기 위한 필드와 메소드가 정의

클래스로부터 만들어진 객체를 해당 클래스의 인스턴스(instance)

하나의 클래스로부터 여러 개의 인스턴스를 만들 수 있음

 

 

 

 

 

 

 

 

클래스를 설계 -> 설계된 클래스를 가지고 사용할 객체를 생성 ->생성된 객체를 이용하는 것

 

6.3 클래스 선언

=>클래스의 이름

자바 식별자 작성 규칙에 따라야

 

 

 

한글 이름도 가능하나, 영어 이름으로 작성

알파벳 대소문자는 서로 다른 문자로 인식

첫 글자와 연결된 다른 단어의 첫 글자는 대문자로 작성하는 것이 관례

 

 

 

 

 

=>클래스 선언과 컴파일

소스 파일 생성: 클래스이름.java (대소문자 주의)

소스 작성

 

컴파일

클래스이름.class

javac.exe

 

 

 

 

 

 

소스 파일당 하나의 클래스를 선언하는 것이 관례

두 개 이상의 클래스도 선언 가능

소스 파일 이름과 동일한 클래스만 public으로 선언 가능

선언한 개수만큼 바이트 코드 파일이 생성

 

Car.java

public class Car {

}

class Tire {

}

컴파일

Car.class

Tire.class

javac.exe

 

 

 

 

 

 

 

 

 

두개 class가 있을 경우 public는 하나만 있어야 한다.

주의할 점은 파일 이름과 동일한 이름의 클래스 선언에만 public 접근 제한자를 붙일 수 있다.

만약 파일 이름과 일치하지 않는 클래스 선언에 public 접근 제한자를 붙이면 컴파일 에러가 발생한다.

가급적이면 소스파일 하나당 동일한 이름의 클래스 하나를 선언하는 것이 좋다.

 

6.4 객체 생성과 클래스 변수

=>new 연산자

객체 생성 역할

 

 

 

클래스()는 생성자를 호출하는 코드

생성된 객체는 힙 메모리 영역에 생성

new 연산자는 객체를 생성 후, 객체 생성 번지 리턴

 

=>클래스 변수

new 연산자에 의해 리턴 된 객체의 번지 저장 (참조 타입 변수)

힙 영역의 객체를 사용하기 위해 사용

 

클래스 타입으로 선언된 변수에 new 연산자가 리턴한 객체의 주소를 저장하는 코드

 

클래스 변수 선언과 객체 생성을 한 개의 실행문으로 작성할 수도 있다.

 

 

 

 

 

new 연산자로 객체를 생성하고 리턴된 객체의 주소를 변수에 저장하면 다음 그림과 같이 변수가 객체를 참조하게 된다.

 

 

 

 

 

 

 

[ Student.java]클래스 선언

public class Student {

 

}

 

[ StudentExample.java]클래스로부터 객체 생성

public class StudentExample {

       public static void main(String[] args) {

               Student s1 = new Student();

               System.out.println("s1 변수가 Student 객체를 참조합니다.");

 

               Student s2 = new Student();

               System.out.println("s2 변수가 다른 Student 객체를 참조합니다.");

       }

}

비록 같은 클래스로 부터 생성되었지만, 각각의 Student 객체는 자신만의 고유 데이터를 가지면서 메모리에서 활동하게 된다

s1, s2가 참조하는 Student 객체는 완전히 독립된 서로 다른 객체이다.

 

 

=>클래스의 용도

라이브러리(API: Application Program Interface)

자체적으로 실행되지 않음

다른 클래스에서 이용할 목적으로 만든 클래스

 

실행용

main() 메소드를 가지고 있는 클래스로 실행할 목적으로 만든 클래스

 

 

public class Student {

           //라이브러리로서의 코드(필드 ,생성자 ,메소드)

          

           //실행하기 위한 코드

           public static void main(String[] args) {

                       Student s1 = new Student();

                       System.out.println("s1 변수가 Student 객체를 참조합니다.");

 

                       Student s2 = new Student();

                       System.out.println("s2 변수가 또 다른 Student 객체를 참조합니다.");

           }

}

대부분의 객체 지향 프로그램은 라이브러리(부품 객체 및 완성 객체)와 실행 클래스가 분리되어 있다.

 

6.5클래스의 구성 멤버

=>클래스의 구성 멤버

필드(Field)

생성자(Constructor)

메소드(Method)

 

 

 

 

 

 

6.5.1필드

필드는 객체의 고유 데이터, 부품 객체, 상태 정보를 저장하는 곳..

선언 형태는 변수와 비슷하지만, 필드는 변수가 아니다.

변수는 생성자와 메소드 내에서만 사용되고, 생성자와 메소드가 실행 종료되면 자동 소멸된다.

하지만 필드는 생성자와 메소드 전체에서 사용되며 객체가 소멸되지 않는 한 객체와 함께 존재한다.

 

6.5.2생성자

생성자는 new연산자로 호출되는 특별한 중괄호 {} 블록이다.

생성자의 역할은 객체 생성 시 초기화를 담당한다.

필드를 초기화하거나 ,메소드를 호출해서 객체를 사용할 준비를 한다.

생성자는 메소드와 비슷하게 생겼지만, 크래스 이름으로 되어 있고 리턴 타입이 없다.

 

6.5.3 메소드

메소드는 객체의 동작에 해당하는 중괄호 {} 블록을 말한다.

중괄호 블록은 이름을 가지고 있는데, 이것이 메소드 이름이다.

메소드를 호출하게 되면 중괄호 블록에 있는 모든 코드들이 일괄적으로 실행된다.

메소드는 필드를 읽고 수정하는 역할도 하지만, 다른 객체를 다양한 기능을 수행하기도 한다.

메소드는 객체 간의 데이터 전달의 수단으로 사용한다.

외부로부터 매개값을 받을 수 있고 , 실행 후 어떤 값을 리턴할 수도 있다.

 

6.6 필드

=>필드의 내용

객체의 고유 데이터

객체가 가져야 할 부품 객체

객체의 현재 상태 데이터

 

 

 

 

6.6.1  필드 선언

필드 선언은 클래스 중괄호 {} 블록 어디서든 존재할 수 있다.

생성자 선언과 메소드 선언의 앞과 뒤 어떤 곳에서도 필드 선언이 가능하다.

생성자와 메소드 중괄호 블록 내부에 선언된 것은 모두 로컬 변수가 된다.

 

 

타입은 필드에 저장할 데이터의 종류를 결정한다.

 

 

 

 

 

 

 

 

 

=>필드의 기본 초기값

초기값 지정되지 않은 필드

객체 생성시 자동으로 기본값으로 초기화

 

 

 

 

6.6.2 필드 사용

필드 값을 읽고, 변경하는 작업을 말한다.

필드 사용 위치

객체 내부: “필드이름” 으로 바로 접근

객체 외부: “변수.필드이름”으로 접근

필드는 객체에 소속된 데이터이므로 객체가 존재하지 않으면 필드도 존재하지 않기 때문이다.

 

 

 

 

 

 

변수는 자신이 선언된 생성자 또는 메소드 블록내부에서만 사용할 수 있는 반면 필드는 생성자와 모든 메소드에서 사용이 가능하다.

Car myCar = newCar():

myCar.speed = 60; //필드값을 60으로 변경

 

[ Car.java]Car 클래스 필드 선언

public class Car {

           // 필드

           String company = "현대자동차";

           String model = "그랜저";

           String color = "검정";

           int maxSpeed = 350;

           int speed;

}

 

[ CarExample.java]외부 클래스에서 Car 필드값 읽기와 변경

public class CarExample {

           public static void main(String[] args) {

                       // 객체 생성

                       Car myCar = new Car();

 

                       // 필드 값 읽기

                       System.out.println("제작회사: " + myCar.company);

                       System.out.println("모델명: " + myCar.model);

                       System.out.println("색깔: " + myCar.color);

                       System.out.println("최고속도: " + myCar.maxSpeed);

                       System.out.println("현재속도: " + myCar.speed);

 

                       // 필드 값 변경

                       myCar.speed = 60;

                       System.out.println("수정된 속도: " + myCar.speed);

           }

}

Car클래스는 speed필드 선언 시 초기값을 주지 않았다. 그러나 출력해보면 기본값은0이 들어있는 것을 볼 수 있다.

 

[FieldInitValue.java]필드 자동 초기화

public class FieldInitValue {

           // 필드

           byte byteField;

           short shortField;

           int intField;

           long longField;

 

 

           boolean booleanField;

           char charField;

 

           float floatField;

           double doubleField;

 

           int[] arrField;

           String referenceField;

}

 

[ FieldInitValueExample.java]필드값 출력

public class FieldInitValueExample {

           public static void main(String[] args) {

                       FieldInitValue fiv = new FieldInitValue();

 

                       System.out.println("byteField: " + fiv.byteField);

                       System.out.println("shortField: " + fiv.shortField);

                       System.out.println("intField: " + fiv.intField);

                       System.out.println("longField: " + fiv.longField);

                       System.out.println("booleanField: " + fiv.booleanField);

                       System.out.println("charField: " + fiv.charField);

                       System.out.println("floatField: " + fiv.floatField);

                       System.out.println("doubleField: " + fiv.doubleField);

                       System.out.println("arrField: " + fiv.arrField);

                       System.out.println("referenceField: " + fiv.referenceField);

           }

}

 

6.7 생성자

생성자(Constructor) : new 연산자와 같이 사용되어 클래스로부터 객체를 생성할 때 호출되어 객체의 초기화를 담당
객체 초기화 : 필드를 초기화하거나 메서드를 호출해서 객체를 사용할 준비를 하는 것

생성자의 실행 없이 객체 생성은 불가능.

new 연산자에 의해 생성자가 성공적으로 실행되면 힙(Heap)영역에 객체가 생성되고 객체의 주소가 리턴된다. 리턴된 객체의 주소는 클래스 타입 변수에 저장되어 객체에 접근할 때 이용된다. 만약 생성자가 성공적으로 실행되지 않고 예외(에러)가 발생했다면 객체는 생성되지 않는다.

 

6.7.1기본 생성자 (Default Constructor)

모든 클래스는 생성자가 반드시 존재하며 하나 이상 가질 수 있음

생성자 선언을 생략하면 컴파일러는 다음과 같은 기본 생성자 추가

 

public 없이 class로만 선언되면 기본 생성자에도 public이 붙지 않는다.

 

 

 

컴파일러는 기본 생성자를 추가하지 않는다.

 

 

 

6.7.2 생성자 선언

=>생성자 선언

디폴트 생성자 대신 개발자가 직접 선언

 

 

 

 

 

=>개발자 선언한 생성자 존재 시 컴파일러는 기본 생성자 추가하지 않음

new 연산자로 객체 생성시 개발자가 선언한 생성자 반드시 사용

 

 

클래스에 생성자가 명시적으로 선언되어 있을 경우에는 반드시 선언된 생성자를 호출해서 객체를 생성해야만 한다.

 

[ Car1.java]생성자 선언

public class Car1 {

           // 생성자

           Car1(String color, int cc) {// 검정, 3000

           }

}

 

[ CarExample1.java]생성자를 호출해서 객체 생성

public class CarExample1 {

           public static void main(String[] args) {

                       Car1 myCar = new Car1("검정", 3000);

                       // Car1 myCar = new Car1(); (X) // 기본 생성자를 호출할 수 없다.

           }

}

 

6.7.3필드 초기화

클래스로부터 객체가 생성될 때 필드는 기본 초기값으로 자동 설정됩니다.

만약 다른 값으로 초기화하고 싶다면 두가지 방법이 있습니다

-필드를 선언할 때 초기값을 주는 방법

-생성자에서 초기값을 주는 방법

필드를 선언할 때 초기값을 주면 동일한 클래스로부터 생성되는 객체들은 모두 같은 데이터를 갖게 됩니다.

객체 생성 후 변경할 수 있지만 객체 생성 시점에는 필드의 값이 모두 같습니다.


:

korean 클래스에 nation필드를 선언하면서 "대한민국"으로 초기값을 준 경우 ,Korean클래스로부터 k1k2객체를 생성하면k1k2객체의 nation필드에는 모두 "대한민국"이 저장되어 있다.

  

 

객체 생성 시점에 외부에서 제공되는 다양한 값들로 초기화되어야 한다면 생성자에서 초기화를 해야 합니다.

위 코드에서 name(이름) ssn(주민번호) 필드값은 클래스를 작성할 때 초기값을 줄 수 없고 객체 생성시점에서 다양한 값을 가져야 합니다.

따라서 생성자의 매개값으로 이 값들을 받아 초기화 하는 것이 맞습니다.

 

 

생성자의 매개값으로 초기값 설정

 

 

 

 

 

[ Korean.java]생성자에서 필드 초기화

public class Korean {

           // 필드

           String nation = "대한민국";

           String name;

           String ssn;

 

           // 생성자

           public Korean(String n, String s) {

                       name = n;

                       ssn = s;

           }

}

 

[ KoreanExample.java]객체 생성 후 필드값 출력

public class KoreanExample {

           public static void main(String[] args) {

                       Korean k1 = new Korean("박자바", "011225-1234567");

                       System.out.println("k1.name : " + k1.name);

                       System.out.println("k1.ssn : " + k1.ssn);

 

                       Korean k2 = new Korean("김자바", "930525-0654321");

                       System.out.println("k2.name : " + k2.name);

                       System.out.println("k2.ssn : " + k2.ssn);

           }

}

 

매개 변수와 필드명 같은 경우 this 사용

public Korean(String name, String ssn) {

   this.name = name;

   this.ssn = ssn;

}

 

6.7.4 생성자 오버로딩(Overloaging)

=>생성자 다양화해야 하는 이유

객체 생성할 때 외부 값으로 객체를 초기화할 필요

외부 값이 어떤 타입으로 몇 개가 제공될 지 모름 - 생성자도 다양화

 

=>생성자 오버로딩(Overloading)

매개변수의 타입, 개수, 순서가 다른 생성자 여러 개 선언

 

 

 

Car클래스에서 생성자를 오버로딩한 예:

 

 

생성자 오버로딩 시 주의할 점은 매개 변수의 타입과 개수 그리고 선언된 순서가 똑같을 경우 여러 변수 이름만 바꾸는 것은 생성자 오버로딩이라고 볼 수 없다.

 

 

생성자가 오버로딩되어 있을 경우 ,new 연산자로 생성자를 호출할 때 제공되는 매개값의 타입과수에 의해 생성자가 렬정된다.

 

 

[ Car2.java]생성자의 오버로딩

public class Car2 {

           // 필드

           String company = "현대자동차";

           String model;

           String color;

           int maxSpeed;

 

           // 생성자

           Car2() { // 기본생성자이지만, 다른 생성자들도 만들었으므로, 자동으로 생성X, 그래서 이 예제에서 명시적으로 만듬

           }

 

           Car2(String model) {

                       this.model = model;

           }

 

           Car2(String model, String color) {

                       this.model = model;

                       this.color = color;

           }

 

           Car2(String model, String color, int maxSpeed) {

                       this.model = model;

                       this.color = color;

                       this.maxSpeed = maxSpeed;

           }

}

 

[CarExample2.java]객체 생성 시 생성자 선택

public class CarExample2 {

           public static void main(String[] args) {

                       Car2 car1 = new Car2();

                       System.out.println("car1.company : " + car1.company);

                       System.out.println();

 

                       Car2 car2 = new Car2("자가용"); // String model

                       System.out.println("car2.company : " + car2.company);

                       System.out.println("car2.model : " + car2.model);

                       System.out.println();

 

                       Car2 car3 = new Car2("자가용", "빨강"); // String model, String color

                       System.out.println("car3.company : " + car3.company);

                       System.out.println("car3.model : " + car3.model);

                       System.out.println("car3.color : " + car3.color);

                       System.out.println();

 

                       Car2 car4 = new Car2("택시", "검정", 200); // String model, String color, int maxSpeed

                       System.out.println("car4.company : " + car4.company);

                       System.out.println("car4.model : " + car4.model);

                       System.out.println("car4.color : " + car4.color);

                       System.out.println("car4.maxSpeed : " + car4.maxSpeed);

           }

}

 

6.7.5 다른 생성자 호출(tis())

=>다른 생성자 호출( this() )

생성자 오버로딩되면 생성자 간의 중복된 코드 발생

초기화 내용이 비슷한 생성자들에서 이러한 현상을 많이 볼 수 있음

초기화 내용을 한 생성자에 몰아 작성

다른 생성자는 초기화 내용을 작성한 생성자를 this()로 호출

 

 

this() 는 자신의 다른 생성자를 호출하는 코드로 반드시 생성자의 첫줄에서만 허용됩니다

this()의 매개값은 호출되는 생성자의 매개 변수 타입에 맞게 제공해야 합니다.

this()다음에는 추가적인 실행문들이 올 수 있다. 이 말은 호출되는 생성자의 실행이 끝나면 원래 생성자로 돌아와서 다음 실행문을 진행한다는 뜻이다.

 

[ Car3.java]위코드의 중복을 제거하는 예제를 보겠습니다.

public class Car3 {

           // 필드

           String company = "현대자동차";

           String model;

           String color;

           int maxSpeed;

 

           // 생성자

           Car3() {

                       this("자가용", "은색", 250); // this는 생성자의 첫줄에만 있어야한다 아니면 오류가 난다.

           }

 

           Car3(String model) {

                       this(model, "은색", 250);

           }

 

           Car3(String model, String color) {

                       this(model, color, 250);

           }

 

           Car3(String model, String color, int maxSpeed) // 공통 실행 코드, 초기화 내용을 한 생성자에 몰아서 작성한다

           {

                       this.model = model;

                       this.color = color;

                       this.maxSpeed = maxSpeed;

           }

}

 

[ CarExample3.java]다른 생성자를 호출해서 중복 코드 줄이기

public class CarExample3 {

           public static void main(String[] args) {

                       Car3 car1 = new Car3();

                       System.out.println("car1.company : " + car1.company);

                       System.out.println("car1.model : " + car1.model);

                       System.out.println("car1.color : " + car1.color);

                       System.out.println("car1.maxSpeed : " + car1.maxSpeed);

                       System.out.println();

 

                       Car3 car2 = new Car3("자가용");

                       System.out.println("car2.company : " + car2.company);

                       System.out.println("car2.model : " + car2.model);

                       System.out.println("car2.color : " + car2.color);

                       System.out.println("car2.maxSpeed : " + car2.maxSpeed);

                       System.out.println();

 

                       Car3 car3 = new Car3("자가용", "빨강");

                       System.out.println("car3.company : " + car3.company);

                       System.out.println("car3.model : " + car3.model);

                       System.out.println("car3.color : " + car3.color);

                       System.out.println("car3.maxSpeed : " + car3.maxSpeed);

 

                       System.out.println();

 

                       Car3 car4 = new Car3("택시", "검정", 200);

                       System.out.println("car4.company : " + car4.company);

                       System.out.println("car4.model : " + car4.model);

                       System.out.println("car4.color : " + car4.color);

                       System.out.println("car4.maxSpeed : " + car4.maxSpeed);

           }

}

 

 

6.8 메소드

메소드객체의 동작에 해당하는 중괄호 {} 블록

-중괄호 블록은 이름을 가지고 있는데 이것이 메소드 이름입니다

-메소드를 호출하면 중괄호 블록에 있는 모든 코드들이 일괄적으로 실행

-메소드는 필드를 읽고 수정하는 역할도 하지만, 다른 객체를 생성해서 다양한 기능을 수행하기도 합니다

-메소드는 객체 간의 데이터 전달의 수단으로 사용됩니다

-외부로부터 매개값을 받을 수도 있고 실행 후 어떤 값을 리턴할 수도 있습니다.

 

6.8.1 메소드 선언

 

 

 

 

선언부와(리턴타입, 메서드이름, 매개변수선언)와 실행 블록으로 구성.

메소드 선언부를 메서드 시그니처라고도 합니다.

객체의 동작(기능)

호출해서 실행할 수 있는 중괄호 { } 블록

메소드 호출하면 중괄호 { } 블록에 있는 모든 코드들이 일괄 실행

 

=>리턴 타입

리턴 타입은 메소드가 실행 후 리턴하는 값이 타입을 말한다.

메소드가 실행 후 결과를 호출한 곳에 넘겨줄 경우에는 리턴값이 있어야 합니다

리턴값이 없는 메소드 : 리턴타입에 void가 와야하고 ,

리턴값이 있는 메소드 : 리턴값의 타입이 와야합니다.



리턴값이 있나냐 없느냐에 따라 메소드를 호출하는 방법이 조금 다르다.

 

 

리턴 타입을 맞추어야 한다.

int result = divide(10, 20 ); //컴파일 에러

 

리턴 타입이 있다고 해서 리턴 값을 변수에 저장할 필요는 없다.

divide(10,20);

 

=>메소드 이름

메소드 이름은 자바 식별자 규칙에 맞게 작성하면 됩니다.

-숫자로 시작하면 안되고 $ , _ 를 제외한 특수문자를 사용하면 안된다.

-관례적으로 메서드명은 소문자로 작성한다.

-서로 다른 단어가 혼합된 이름이라면 뒤이어 오는 단어의 첫머리 글자는 대문자로 작성한다.

 

기능에 맞게 이름을 지어주는 것이 좋다.

 

=> 매개 변수 선언

매개변수는 메소드를 실행할 때 필요한 데이터를 외부에서 받기 위해 사용

매개변수도 필요 없을 수 있음

 

매개변수가 선언 예:

double divide(int x, int y ){...}

이렇게 선언된 divide() 메소드를 호출할 때에는 반드시 두개의 int값을 주어야 한다.

double result = divide(10,20);

잘못된 매개값을 사용해서 컴파일 오류가 발생

double result = divide(10.0 , 20.0 );//컴파일 에러

하지만 매개값의 타입과 매개 변수의 타입(int)이 달라도 byte타입은 int타임으로 자동 타입 변환되기 때문에 컴파일 오류가 생기지 않는다.

byte b1 =10;

byte b2 =20;

double result = divide(b1, b2);

 

[ Calculator.java]메소드 선언

public class Calculator {

           // 메소드

           void powerOn() {

                       System.out.println("전원을 켭니다.");

           }

 

           int plus(int x, int y) {

                       int result = x + y;

                       return result;

           }

 

           double divide(int x, int y) {

                       double result = (double) x / (double) y;

                       return result;

           }

 

           void powerOff() {

                       System.out.println("전원을 끕니다");

           }

}

 

[ CalculatorExample.java]메소드 호출

public class CalculatorExample {

           public static void main(String[] args) {

                       Calculator myCalc = new Calculator();

                       myCalc.powerOn();

 

                       int result1 = myCalc.plus(5, 6);

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

 

                       byte x = 10;

                       byte y = 4;

                       double result2 = myCalc.divide(x, y);

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

 

                       myCalc.powerOff();

           }

}

 

=>매개변수의 수를 모를 경우

메소드의 매개 변수는 이미 정해져 있는 것이 입반적이지만, 경우에 따라서느느 메소드를 선언할 때 매개변수의 개수를 알 수 없는 경우가 있다.

int sum(int[] values) { }

sum() 메소드를 호출할 때 배열을 넘겨줌으로써 배열의 항목 값들을 모두 전달할 수 있습니다배열의 항목 수는 호출할 때 결정됩니다.
int[] values = {1,2,3};

int result = sum(values);

int result = sum(new int[] = {1,2,3,4,5};

배열을 생성하지 않고 값의 리스트만 넘겨주는 방법도 있습니다. 매개 변수를 "..." 을 사용해서 선언하게 되면 메소드 호출 시 넘겨준 값의 수에 따라 자동으로 배열이 생성되고 매개값으로 사용됩니다.

 int sum2(int ... values) { }

"..." 으로 선언된 매개 변수의 값은 아래와 같이 메소드 호출 시 리스트로 나열해주면 됩니다.

int result = sum2(1,2,3);

int result = sum2(1,2,3,4,5);

"..." 으로 선언된 매개 변수는배열 타입이므로 배열을 직접 매개값으로 사용해도 됩니다.

int[] values = {1,2,3};

int result = sum2(values);

int result = sum2(new int[] = {1,2,3,4,5};

 

[ Computer.java]매개 변수의 수를 모를 경우

public class Computer {

           int sum1(int[] values) {

                       int sum = 0;

                       for (int i = 0; i < values.length; i++) {

                                  sum += values[i];

                       }

                       return sum;

           }

 

           int sum2(int... values) {

                       int sum = 0;

                       for (int i = 0; i < values.length; i++) {

                                  sum += values[i];

                       }

                       return sum;

           }

 

}

 

[ ComputerExample.java]매개 변수의 수를 모를 경우

public class ComputerExample {

           public static void main(String[] args) {

                       Computer myCom = new Computer();

                      

                       int[] values1 = { 1, 2, 3 };

                       int result1 = myCom.sum1(values1);

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

 

                       int result2 = myCom.sum1(new int[] { 1, 2, 3, 4, 5 });

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

 

                       int result3 = myCom.sum2(1, 2, 3);

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

 

                       int result4 = myCom.sum2(1, 2, 3, 4, 5);

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

           }

}

 

6.8.2 리턴(return)

=>메소드 실행을 중지하고 리턴값 지정하는 역할

=>리턴값이 없는 메소드

메소드 실행을 강제 종료 시키는 역할

return 결과값;

=>리턴값이 있는 메소드

반드시 리턴(return)문 사용해 리턴값 지정해야

 

 

return 문 뒤에 실행문 올 수 없음 ->Unreachable code라는 오류가 난다.

int plus(int x, int y){

           int result = x +y;

           return result;

           System.out.println(result); //Unreachable code

}

다음과 같은 경우는 컴파일 에러가 발생하지 않는다.

 

 

 

 

 

=>리턴 값이 없는 메소드(void)

return 문을 사용하면 메소드 실행을 강제 종료시킨다.

return;

아래에서는 return문을 대신해서 break 문을 사용할 수도 있습니다

만약 while문 뒤에 실행문이 추가적으로 더 있을 경우, break문을 반드시 사용해야 합니다.

return문은 즉시 메서드를 종료시키기 때문입니다.

 

 

[Car4.java]return

public class Car4 {

           // 필드

           int gas;

 

           // 생성자

 

           // 메소드

           // 리턴값이 없는 메소드로 매개값을 받아서 gas필드값을 변경

           void setGas(int gas) {

                       this.gas = gas;

           }

          

           //리턴값이 boolean인 메소드로 gas필드값이 0이면 false 0이 아니면 true로 리턴

           boolean isLeftGas() {

                       if (gas == 0) {

                                  System.out.println("gas가 없습니다.");

                                  return false;

                       }

                       System.out.println("gas가 있습니다.");

                       return true;

           }

       //리턴값이 없는 메소드로 gas필드값이 0이면 return문으로 메소드를 강제 종료

           void run() {

                       while (true) {

                                  if (gas > 0) {

                                              System.out.println("달립니다.(gas잔량:" + gas + ")");

                                              gas -= 1;

                                  } else {

                                              System.out.println("멈춥니다.(gas잔량:" + gas + ")");

                                              return;//메소드 실행 종료

                                  }

                       }

           }

}

 

[ CarExample4.java]return

public class CarExample4 {

           public static void main(String[] args) {

                       Car4 myCar = new Car4();

                       myCar.setGas(5); // Car setGas() 메소드 호출

 

                       boolean gasState = myCar.isLeftGas(); // Car isLeftGas() 메소드 호출

                       if (gasState) {

                                  System.out.println("출발합니다.");

                                  myCar.run(); // Car run() 메소드 호출

 

                       }

 

                       if (myCar.isLeftGas()) { // Car isLeftGas() 메소드 호출

                                  System.out.println("gas를 주입할 필요가 없습니다.");

                       } else {

                                  System.out.println("gas를 주입하세요.");

                       }

           }

}

 

6.8.3      메소드 호출

=>메소드는 클래스 내∙외부의 호출에 의해 실행

클래스 내부: 메소드 이름으로 호출

클래스 외부: 객체 생성 후, 참조 변수를 이용해 호출 , 그 이유는 객체가 존재해야 메소드도 존재하기 때문이다.

 

 

=>객체 내부에서 호출

 

:

public class ClassName{

           void method1(String p1, int p2){

}

void method2{}{

           method1("홍길동",100);

}

}

 

리턴값이 있는 메소드를 호출하고 리턴값을 받고 싶다면 다음과 같이 변수를 선언하고 대입하면 된다.

 

주의해야 할 점은 변수 타입은 메서드 리턴값과 동일하거나 타입 변환이 될수 있어야 합니다.

ex) int 타입은 double 타입으로 자동 변환되기 때문에 int 리턴값은 double 변수에 대입할 수 있습니다

public class ClassName {

        int method1(int x, int y){

            int result = x + y;

          return result;

          }

 

      void method2(){

        int result1 = method1(10,20);

       double result2 = method1(10,20);

    }

}

 

[ Calculator1.java]클래스 내부에서 메소드 호출

public class Calculator1 {

           int plus(int x, int y) {

                       int result = x + y;

                       return result;

           }

          

           double avg(int x, int y) {

                       double sum = plus(x,y);

                       double result = sum / 2;

                       return result;

           }

          

           void execute() {

                       double result = avg(7, 10);

                       println("실행결과 : "+result);

           }

          

           void println(String messge) {

                       System.out.println(messge);

           }

}

 

[ CalculatorExample1.java]Calculatorexecute()실행

public class CalculatorExample1 {

           public static void main(String[] args) {

                       Calculator1 myCals = new Calculator1();

                       myCals.execute();

           }

}


=>
객체 외부에서 호출

클래스 참조변수 = new 클래스(매개값,...); //객체 생성

 

객체가 생성되었다면 참조변수와 도트(.) 연산자를 사용해서 메서드를 호출할 수 있습니다

도트 연산자는 객체 접근 연산자로 객체가 가지고 있는 필드나, 메서드에 접근할 때 사용됩니다.

 

참조타입.메서드(매개값,...); //리턴값이 없거나, 있어도 리턴값을 받지 않을 경우

타입 변수 = 참조변수.메서드(매개값,...); // 리턴값이 있고, 리턴값을 받고 싶을 경우


Car myCar = new Car();

myCar.keyTurnOn();

myCar.run();

int speed = myCar.getSpeed();

[ Car5.java]클래스 외부에서 메소드 호출

public class Car5 {

           // 필드

           int speed;

 

           // 생성자

 

           // 메소드

           int getSpeed() {

                       return speed;

           }

 

           void keyTurnOn() {

                       System.out.println("키를 돌립니다.");

           }

 

           void run() {

                       for (int i = 10; i <= 50; i += 10) {

                                  speed = i;

                                  System.out.println("달립니다.(시속:" + speed + "km/h)");

                       }

           }

}

 

[CarExample5.java]글래스 외부에서 메소드 호출

public class CarExample5 {

           public static void main(String[] args) {

 

                       Car5 myCar = new Car5();

                       myCar.keyTurnOn();

                       myCar.run();

                       int speed = myCar.getSpeed();

                       System.out.println("현재 속도: " + speed + "km/h");

           }

}

 

6.8.4 메소드 오버로딩(Overloading)

클래스 내에 같은 이름의 메소드를 여러 개 선언하는 것

하나의 메소드 이름으로 다양한 매개값 받기 위해 메소드 오버로딩

오버로딩의 조건: 매개변수의 타입, 개수, 순서가 달라야

 

 

메소드 오버로딩이 필요한 이유는 매개값을 다양하게 받아 처리할 수 있도록 하기 위해서이다.

 

 

int ->double

 

 

plus()메소드 호출

plust(10,20);

plus(10.5, 20.3)

 

 

int x = 10;

double y = 20.3;

plus(x, y); =>puls(double, double)메소드가 실행된다.

자동 타입 변환

 

int divide(int x, int y ){...}

double divide(int boonja, int boonmo){...}

 

메소드 오버로딩된 println()메소드를 보여준다.

 

 

[Calculator2.java]메소드 오버로딩

public class Calculator2 {

           // 정사각형의 넓이

           double areaRectangle(double width) {

                       return width * width;

           }

 

           // 직사각형의 넓이

           double areaRectangle(double width, double height) {

                       return width * height;

           }

}

 

[ CalculatorExample2.java]메소드 오버로딩

public class CalculatorExample2 {

           public static void main(String[] args) {

                       Calculator2 myCalcu = new Calculator2();

                      

                       //정사각형의 넓이 구하기

                       double result1 = myCalcu.areaRectangle(10);

                      

                       //직사각형의 넓이 구하기

                       double result2 = myCalcu.areaRectangle(10,20);

                      

                       //결과 출력

                       System.out.println("정사각형 넓이 = "+result1);

                       System.out.println("직사각형 넓이 = "+result2);

           }

}

 

6.9   인스턴스 멤버와 this

=>인스턴스 멤버란?

객체(인스턴스) 마다 가지고 있는 필드와 메소드

이들을 각각 인스턴스 필드, 인스턴스 메소드라고 부름

인스턴스 멤버는 객체 소속된 멤버이기 때문에 객체가 없이 사용불가

 

 

 

 

 

 

인스턴스를 생성하고 참조 변수 등을 접근

 

메소드 영역

 

 

=>this ->

객체(인스턴스) 자신의 참조(번지)를 가지고 있는 키워드

객체 내부에서 인스턴스 멤버임을 명확히 하기 위해 this. 사용

매개변수와 필드명이 동일할 때 인스턴스 필드임을 명확히 하기 위해 사용

 

 

[Car6.java]인스턴스 멤버와 this

public class Car6 {

           // 필드

           String model;

           int speed;

 

           // 생성자

           Car6(String model) {

                       this.model = model;

           }

 

           // 메소드

           void setSpeed(int speed) {

                       this.speed = speed;

           }

 

           void run() {

                       for (int i = 10; i <= 50; i += 10) {

                                  this.setSpeed(i);

                                  System.out.println(this.model + "가 달립니다.(시속:" + this.speed + "km/h)");

                       }

           }

}

 

[ CarExample6.java]인스턴스 멤버와 this

public class CarExample6 {

           public static void main(String[] args) {

                       Car6 myCar = new Car6("포르쉐");

                       Car6 yourCar = new Car6("벤츠");

 

                       myCar.run();

                       yourCar.run();

           }

}

 

6.10 정적 멤버와 static

=>정적(static) 멤버란?

클래스에 고정된 필드와 메소드 - 정적 필드, 정적 메소드

정적 멤버는 클래스에 소속된 멤버

객체 내부에 존재하지 않고, 메소드 영역에 존재

정적 멤버는 객체를 생성하지 않고 클래스로 바로 접근해 사용

클래스에 소속된 멤버이기 때문에 클래스멤버라고도 합니다.

 

6.10.1 정적 멤버 선언

필드 또는 메소드 선언할 때 static 키워드 붙임

 

 

 

 

 

 

 

 

 

정적 필드와 정적 메소드는 클래스에 고정된 멤버이므로 클래스 로더가 클래스를 로딩해서 메소드 메모리 영역에 적재할 때 클래스별로 관리된다.

 

 

 

 

 

 

 

 

객체마다 가지고 있을 필요성이 없는 공용적인 데이터라면 정적 필드로 선언하는 것이 좋다.

인스턴스 멤버 선언 vs 정적 멤버 선언의 기준

§  필드

      객체 마다 가지고 있어야 할 데이터 è 인스턴스 필드

      공용적인 데이터 è 정적 필드

public class Calculator {

           String color;  // 계산기별로 색까리 다를 수 있ㄷ.

           static double pi = 3.14159; // 계산기에서 사용하는 파이 값은 동일하다.

}


인스턴스 필드를 이용해서 실행해야 한다면 인스턴스 메소드로 선언

    • 메소드

      인스턴스 필드로 작업해야 할 메소드 è 인스턴스 메소드

      인스턴스 필드로 작업하지 않는 메소드 è 정적 메소드

 

 

 

public class Calculator{

           String color; //인스턴스 메소드

           void setColor(String color){this.color = color;} //인스턴스 메소드

           static int plus(int x, int y){return x + y ;} //정적 메소드

           static int minus(int x, int y){return x - y;} //정적 메소드

}

6.10.2 정적 멤버 사용

클래스 이름과 함께 도트(.) 연산자로 접근

 

 

 

:

 

[바람직하지 못한 사용]

[바람직한 사용]

   

 

 

 

 

 

 

 

 

 

 

 

 

 

(1) 클래스 이름으로 접근해야 하지만

(2) 객체를 먼저 생성하고 참조 변수(객체 참조 변수) 접근이 가능하다. (클래스 이름으로 접근하기.. 아니면 오류 생길 수 있음)

 

==>클래스 이름으로 접근

[Calculator3]정적 멤버 사용

public class Calculator3 {

           static double pi = 3.14159;

 

           static int plus(int x, int y) {

                       return x + y;

           }

 

           static int minus(int x, int y) {

                       return x - y;

           }

}

 

[CalculatorExample3.java]정적 멤버 사용

public class CalculatorExample3 {

           public static void main(String[] args) {

                       double result1 = 10 * 10 * Calculator3.pi;

                       int result2 = Calculator3.plus(10, 5);

                       int result3 = Calculator3.minus(10, 5);

 

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

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

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

           }

}

 

 

6.10. 3 정적 초기화 블록

정적 필드는 다음과 같이 필드 선언과 동시에 초기값을 주는 것이 보통이다.

static double pi = 3.14159;

정적 필드는 필드 선언과 동시에 초기값을 주는 것이 일반적입니다.

계산이 필요한 초기화 작업이 있을 수도 있습니다

정적 필드는 객체 생성 없이 사용해야 하므로 생성자에서 초기화 작업을 할 수 없습니다

정적 필드의 복잡한 초기화 작업을 위해서 정적 블록을 제공합니다.

§  클래스가 메소드 영역으로 로딩될 때 자동으로 실행하는 블록

static {

      ......

}

정적 블록은 클래스가 메모리로 로딩될 때 자동적으로 실행된다.정적 블록은 클래스 내부에 여러개가 선언되어도 상관 없다. 클래스가 메모리로 로딩될때 선언된 순서대로 실행된다.

 

정적 필드의 복잡한 초기화 작업과 정적 메소드 호출 가능

클래스 내부에 여러 개가 선언되면 선언된 순서대로 실행

 

[Television.java]정적 초기화 블록

public class Television {

           static String company = "Samsung";

           static String model = "LCD";

           static String info;

 

           static {

                       info = company + "-" + model;

           }

}

 

[TelevisionExample.java]정적 초기화 블록

public class TelevisionExample {

           public static void main(String[] args) {

                       System.out.println(Television.info);

           }

}

 

6.10.4 정적 메소드와 정적 블록 작성시 주의할 점

객체가 없어도 실행 가능

블록 내부에 인스턴스 필드나 인스턴스 메소드 사용 불가

객체 자신의 참조인 this 사용 불가

EX)

public class ClassName{

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

}

 

객체 생성하고 참조 변수로 접근해야 한다.

 

 

 

 

 

 

 

main()메서드도 동일한 규칙이 적용됩니다.

main()메서드도 정적 메서드이므로 객체 생성 없이 인스턴스 필드와 인스턴스 메서드를  

main() 메서드에서 바로 사용할 수 없습니다.

 

예제)

public class Car {

 int speed;

 

 void run() {...}

public static void main(String[] args) {

speed = 60;

run();

}

}

 

메인 메소드를 올바르개 수정하면 다음과 같다.

public static void main(String[] args) {

  Car myCar = new Car(); 

  myCar.speed = 60;

  myCar.run();

 }

}

 

[Car7.java ]정적 메소드와 블록 선언 시 주의 할 점

public class Car7 {

           int speed;

 

           void run() {

                       System.out.println(speed + "으로 달립니다.");

           }

 

 

           public static void main(String[] args) {

                       Car7 myCar = new Car7();

                       myCar.speed = 60;

                       myCar.run();

           }

}

6.10.5싱글톤(Singleton)

하나의 애플리케이션 내에서 단 하나만 생성되는 객체

=>싱글톤을 만드는 방법

외부에서 new 연산자로 생성자를 호출할 수 없도록 막기

private 접근 제한자를 생성자 앞에 붙임

클래스 자신의 타입으로 정적 필드 선언

자신의 객체를 생성해 초기화

private 접근 제한자 붙여 외부에서 필드 값 변경 불가하도록

외부에서 호출할 수 있는 정적 메소드인 getInstance() 선언

정적 필드에서 참조하고 있는 자신의 객체 리턴

public class 클래스{

           //정적 필드

           private static 클래스 singleton = new 클래스();

 

           //생성자

           private 클래스(){}

 

           //정적 메소드

           static 클래스 getInstance(){

                       return singleton;

}

}

 

=>외부에서 싱글톤 얻는 방법

 

 

 

[Singleton.java] 싱글톤

public class Singleton {

           private static Singleton singleton = new Singleton();

 

           private Singleton() {

           }

          

           static Singleton getInstance() {

                       return singleton;

           }

}

 

[SingletonExample.java] 싱글톤 객체

public class SingletonExample {

           public static void main(String[] args) {

                        /* Singleton obj1= new Singleton();//컴파일 에러  (private때문에 클래스 외부에서 new 생성자로 호출 X)

                        * Singleton obj2= new Singleton();//컴파일 에러  (싱글톤은 하나의 객체이고, 생성자를 호출한만큼 객체가 생성 되므로 X)*/

 

                       Singleton obj1 = Singleton.getInstance();

                       Singleton obj2 = Singleton.getInstance();

 

                       if (obj1 == obj2) {

                                  System.out.println("같은 Singleton 객체 입니다.");

                       } else {

                                  System.out.println("다른 Singleton 객체 입니다.");

                       }

           }

}

 

6.11 inal필드와 상수

6.11.1 final 필드

최종적인 값을 갖고 있는 필드 = 값을 변경할 수 없는 필드

final 타입 필드 = [= 초기값];

=>final 필드의 딱 한번의 초기값 지정 방법

필드 선언 시

생성자

단순 값이라면 필드 선언시에 주는 것이 제일 간단하다.

하지만 복잡한 코드가 필요하거나 객체 생성 시에 외부 데이터로 초기화해야 한다면 생성자에서 초기값을 지정해야 한다.

 

 

[Person.java] fianl 필드 선언과 초기화

public class Person {

           final String nation = "Korea";

           final String ssn;

           String name;

 

           public Person(String ssn, String name) {

                       this.ssn = ssn;

                       this.name = name;

           }

}

 

[PersonExample.java] final 필드 테스트

public class PersonExample {

           public static void main(String[] args) {

 

                       Person p1 = new Person("123456-1234567", "계백");

 

 

                       System.out.println(p1.nation);

                       System.out.println(p1.ssn);

                       System.out.println(p1.name);

 

                       // p1.nation = "Corea"; //final 필드는 수정이 불가합니다.

                       // p1.ssn = "654321-7654321";

                       p1.name = "을지문덕";

                       ;

           }

}

 

6.11.2상수(static final)

일반적으로 불변의 값을 상수라고 부른다.

=>상수 = 정적 final 필드

==>final 필드:

-객체마다 가지는 불변의 인스턴스 필드

==>상수(static final):

-객체마다 가지고 있지 않음

-메소드 영역에 클래스 별 로 관리되는 불변의 정적 필드

-공용 데이터로서 사용

일반적으로 불변의 값을 상수라고 부른다

불변의 값을 저장하는 필드를 자바에서는 상수라고 한다

final 필드를 상수라고 부르지는 않는다

상수는 static 이면서 final 이어야 함.

static final 필드는 객체마다 저장되지 않고, 클래스에만 포함

한 번 초기값이 저장되면 변경 불가.

 

 

static final 타입 상수 [= 초기값];

 

초기값이 단순 값이라면 선언 시에 주는 것이 일반적이지만

복잡한 초기화일 경우 정적 블록에서도 할 수 있습니다.

 static final 타입  상수;

  static {

    상수 = 초기값;

  }

 

상수 이름은 전부 대문자로 작성

다른 단어가 결합되면 _ 로 연결

static final double PI = 3.1459;

static final double EARTH_SURFACE_AREA;

 

[Earth.Java] 상수 선언

public class Earth {

           static final double EARTH_RADIUS = 6400;

           static final double EARTH_SURFACE_AREA;

          

           static {

                       EARTH_SURFACE_AREA = 4 * Math.PI * EARTH_RADIUS * EARTH_RADIUS;

           }

}

 

[EarthExample.java] 상수 사용

public class EarthExample {

           public static void main(String[] args) {

                       System.out.println("지구의 반지름 : " + Earth.EARTH_RADIUS + "km");

                       System.out.println("지구의 표면적 : " + Earth.EARTH_SURFACE_AREA + "km^2");

           }

}

 

6.12 패키지란?

=>클래스를 기능별로 묶어서 그룹 이름을 붙여 놓은 것

==>파일들을 관리하기 위해 사용하는 폴더(디렉토리)와 비슷한 개념

==>패키지의 물리적인 형태는 파일 시스템의 폴더

=>클래스 이름의 일부

==>클래스를 유일하게 만들어주는 식별자

==>전체 클래스 이름 = 상위패키지.하위패키지.클래스

==>클래스명이 같아도 패키지명이 다르면 다른 클래스로 취급

패키지명 + 클래스명

 

패키지가 중요한 이유는 클래스만 따로 복잡해서 다른 곳으로 이동하면 클래스는 사용할 수 없기 때문이다.

 

v  패키지란?

§  클래스 선언할 때 패키지 결정

      클래스 선언할 때 포함될 패키지 선언

      클래스 파일은(~.class) 선언된 패키지와 동일한 폴더 안에서만 동작

      클래스 파일은(~.class) 다른 폴더 안에 넣으면 동작하지 않음

 

 

6.12.1 패키지 선언

클래스를 컴파일하는 과정에서 자동적으로 생성되는 폴더

컴파일러는 클래스에 포함되어 있는 패키지 선언을 보고 파일 시스템의 폴더로 자동 생성

 

패키지 선언 방법

package 상위패키지.하위패키지;

public class ClassName { ... }

 

패키지 이름은 개발자가 임의대로 지어주면 되지만 여기에도 지켜야 할 몇가지 규칙이 있습니다.

- 숫자로 시작해서는 안되고 특수문자는 $ _ 만 사용.

- java로 시작하는 패키지는 자바 표준 API에서만 사용하므로 사용해서는 안됨.

- 모두 소문자로 작성하는 것이 관례.

 

도메인은 등록 기관에서 유일한 이름이 되도록 검증되었기 떄문에 ,도메인 이름으로 패키지를 만들면 다른 회사의 패키지와 중복되는 경우가 발생하지 않는다.

com.samsung.projetname

com.hyndai.projectname

com.lg.projectname

org.apache.projectname

 

6.12.2 패키지 선언이 포함된 클래스 컴파일

javac -d . ClassName.java <- 현재 폴더 내에 생성

 

 

 

6.12.3 이클립스에서 패키지 생성과 클래스 생성

패키지 생성

프로젝트의 src폴더를 선택하고 메뉴에서 [File ->New ->Package]

마우스 오늘똑 버튼을 클릭해서 [ New->Package]를 선택해도 좋다.

 

6.12.4 import

패키지 내에 같이 포함된 클래스간 클래스 이름으로 사용 가능

=>패키지가 다른 클래스를 사용해야 할 경우

==>패키지 명 포함된 전체 클래스 이름으로 사용

 

==>Import 문으로 패키지를 지정하고 사용

 

 

import com.mycompany.*;

import com.mycompany.project.*;

 

 

다음 예제는 서로 다른 패키지에 소속된 Tire클래스를 사용:

 

[Car.java] import

package textbook.chapter6.mycompany;

 

import textbook.chapter6.hanbook.SnowTire;

import textbook.chapter6.hyndai.Engine;

import textbook.chapter6.kumbo.BigWidthTire;

 

public class Car {

 

           //필드

           Engine engine = new Engine();

           SnowTire tire1= new SnowTire();

           BigWidthTire tire2 = new BigWidthTire();

           textbook.chapter6.hanbook.Tire tire3 = new textbook.chapter6.hanbook.Tire();

           textbook.chapter6.kumbo.Tire tire4 = new textbook.chapter6.kumbo.Tire();

}

 

6.13 접근 제한자(Access Modifier)

클래스 및 클래스의 구성 멤버에 대한 접근을 제한하는 역할

      다른 패키지에서 클래스를 사용하지 못하도록 (클래스 제한)

      클래스로부터 객체를 생성하지 못하도록 (생성자 제한)

      특정 필드와 메소드를 숨김 처리 (필드와 메소드 제한)

§  접근 제한자의 종류

 

 

6.13.1 클래스의 접근 제한

 

클래스에 적용할 수 있는 접근 제한은 publicdefault단 두가지인데

//defautl접근 제한

class 클래스 {...}

 

//public 접근 제한

public class 클래스

 

=>default

클래스 선언할 때 public 생략한 경우

다른 패키지에서는 사용 불가

 

=>public

다른 개발자가 사용할 수 있도록 라이브러리 클래스로 만들 때 유용

제한 없이 사용할 수 있다.

인터넷으로 배포되는 라이브러리 클래스들도 모두 public 접근 제한을 가지고 있다.

 

 

 

[A.java] 클래스의 접근 제한

package textbook.chapter6.exam01_class_acess.package1;

 

class A {} //default 접근 제한

 

 

[B.java] 클래스의 접근 제한

package textbook.chapter6.exam01_class_acess.package1;

 

public class B {

           A a; //A클래스 접근 가능(필드로 선언할 수 있음)

}

 

 

[C.java] 클래스의 접근 제한

package textbook.chapter6.exam01_class_acess.package2;

 

import textbook.chapter6.exam01_class_acess.package1.B;

 

public class C {

           A a; //A클래스 접근 불가능(컴파일 에러)

           B B;

}

 

6.13.2 생성자 접근 제한

§  생성자가 가지는 접근 제한에 따라 호출 여부 결정

§  필드와 메소드의 접근 제한 (p.262~264)

§  클래스 내부, 패키지 내, 패키지 상호간에 사용할 지 고려해 선언

객체를 생성하기 위해서는 new 연산자로 생성자를 호출해야 합니다

생성자를 어디에서나 호출할 수 있는 것은 아닙니다

생성자라 어떤 접근 제한을 갖느냐에 따라 호출 가능 여부가 결정됩니다.

생성자는 아래와 같이 public, protected, default, private 접근 제한을 가질 수 있습니다.

 

 

public class ClassName {

    //public 접근 제한

      public ClassName(...) { ... }

    //protected 접근 제한

      protected ClassName(...) { ... }

    //default 접근 제한

      ClassName(...) { ... }

    //private 접근 제한

      private ClassName(...) { ... }

}

 

클래스에 생성자를 선언하지 않았을 때 자동으로 선언되는 기본 생성자는 클래스와 같은 접근 제한을 가집니다.

접근 제한자 

생성자

설명

 public

클래스( ... ) 

public 접근 제한은 모든 패키지에서 아무런 제한 없이 생성자를 호출할 수 있도록 합니다. 생성자가 public 접근 제한을 가진다면 클래스도 public 접근 제한을 가지는 것이 정상적입니다. 클래스가 default 접근 제한을 가진다면 클래스 사용이 같은 패키지로 한정되므로, 비록 생성자가 public 접근 제한을 가지더라도 같은 패키지에서만 생성자를 호출할 수 있습니다

protected

클래스( ... ) 

protected 접근 제한은 default 접근 제한과 마찬가지로 같은 패키지에 속하는 클래스에서 생성자를 호출할 수 있도록 합니다. 차이점은 다른 패키지에 속한 클래스가 해당 클래스의 자식(child)클래스라면 생성자를 호출할 수 있습니다.

default

클래스( ... ) 

생성자를 선언할 때 public 또는 private 를 생략 했다면 생성자는 default 접근 제한을 가집니다. default 접근 제한은 같은 패키지에서는 아무런 제한 없이 생성자를 호출할 수 있으나, 다른 패키지에서는 생성자를 호출할 수 없도록 합니다

private

클래스( ... ) 

private 접근 제한은 동일 패키지이건 다른 패키지이건 상관없이 생성자를 호출하지 못하도록 제한합니다. , 클래스 외부에서 new 연산자로 객체를 만들 수 없습니다. 오로지 클래스 내부에서만 생성자를 호출할 수 있고, 객체를 만들 수 있습니다


[A.java] 생성자의 접근 제한

 

package textbook.chapter6.exam02_constructor_acess.package1;

 

public class A {

           //필드

            A a1 = new A(true);

            A a2 = new A(1);

            A a3 = new A("문자열");

 

            //생성자

            public A(boolean b) {} //public 접근 제한

            A(int b) {}                                //default 접근 제한

            private A(String s) {} //private 접근 제한

}

 

 

[B.java] 생성자의 접근 제한

package textbook.chapter6.exam02_constructor_acess.package1;//패키지 동일

 

public class B {

           // 필드

           A a1 = new A(true);

           A a2 = new A(1); // A클래스와 같은 패키지이므로 default 생성자 호출가능.

           // A a3 = new A("문자열"); //private 생성자 접근 불가(컴파일 에러)

}

 

 

[C.java] 생성자의 접근 제한

package textbook.chapter6.exam02_constructor_acess.package2;

 

import textbook.chapter6.exam02_constructor_acess.package1.A;

 

public class C {

             //필드

            A a1 = new A(true);     

            //A a2 = new A(1); //default 다른 패키지이므로 default 생성자 호출 불가. 

            //A a3 = new A("문자열");  //private 생성자이므로 접근 불가

 

}

 

가끔 전체 프로그램에서 단 하나의 객체만 만들도록 보장해야 하는 경우가 있다. 이럴 경우 여러 개의 객체를 만들지 못하도록 설계해야 하는데 이것을 싱글톤 패턴이라고 한다.

싱글톤 패턴은 생성자를 private접근제한으로 선언하고 ,자신의 유일한 객체를 리턴하는 getInstance() 정적 메소드를 선언하는 것을 말한다.

 

6.13.3 필드와 메소드의 접근 제한

필드와 메서드를 선언할 때 고려해야 할 사항은 클래스 내부에서만 사용할 것인지

패키지 내에서만 사용할 것인지, 아니면 다른 패키지에서도 사용할 수 있도록 할 것인지를 결정해야 합니다

이것은 필드와 메서드가 어떤 접근 제한을 갖느냐에 따라 결정됩니다.

 

 

필드와 메서드는 public, protected, default, private 접근 제한을 가질 수 있습니다.

//필드 선언

[ public | protected | private ] [static] 타입 필드;

 

//메소드 선언

[ public | protected | private ] [static] 리턴 타입 메소드( ... ) { ... }

 

접근 제한자 

생성자

설명

 public

필드

메소드 ( ... )

public 접근 제한은 모든 패키지에서 아무런 제한 없이 필드와 메소드를 사용할 수 있도록 해줍니다. 필드와 메소드가 public 접근 제한을 가질 경우 클래스도 public 접근 제한을 가져야 합니다. 클래스가 default 접근 제한을 가지게 되면 같은 패키지 안에서만 클래스가 사용되기 때문입니다

protected

필드

메소드 ( ... )

protected 접근 제한은 default 접근 제한과 마찬가지로 같은 패키지에 속하는 클래스에서 필드와 메소드를 사용할 수 있도록 합니다. 차이점은, 다른 패키지에 속한 클래스가 해당 클래스의 잣기 클래스라면 필드와 메소드를 사용할 수 있습니다

default

필드

메소드 ( ... )

필드와 메소드를 선언할 때 public 또는 private 를 생략했다면 default 접근제한을 가진다. default 접근 제한은 같은 패키지에서는 아무런 제한 없이 필드와 메소드를 사용할 수 있으나, 다른 패키지에서는 필드와 메소드를 사용할 수 없도록 한다

private

필드

메소드 ( ... )

private 접근 제한은 동일 패키지이건 다른 패키지이건 상관 없이 필드와 메소드를 사용하지 못하도록 제한합니다. 오로지 클래스 내부에서만 사용할 수 있습니다

 

 

[A.java] 필드와 메소드의 접근 제한

package textbook.chapter6.field_method_access.package1;

 

public class A {

           // 필드

           public int field1; //public 접근 제한

           int field2;                     //default 접근 제한

           private int field3; //private 접근 제한

 

           // 생성자

           public A() {

                       field1 = 1;

                       field2 = 1;

                       field3 = 1;

                       // 클래스 내부일 경우 접근 제한자의 영향을 받지 않습니다.

                       method1();

                       method2();

                       method3();

           }

          

           //메소드

           public void method1() {}//public 접근 제한

           void method2() {}//default 접근 제한

           private void method3() {}//private 접근 제한

}

 

[B.java] 필드와 메소드의 접근 제한

 

package textbook.chapter6.field_method_access.package1;//패키지가 동일

 

public class B {

           public B() {

                       A a = new A();

                       a.field1 = 1;

                       a.field2 = 1;

                       // a.field3 = 1;// private 필드와 메서드 접근 불가.

                      

                       a.method1();

                       a.method2();

                       // a.method3();// private 필드와 메서드 접근 불가.

           }

}

 

[C.java] 필드와 메소드의 접근 제한

 

package textbook.chapter6.field_method_access.package2;

 

import textbook.chapter6.field_method_access.package1.A;

 

public class C {

           public C() {

                       A a = new A();

                       a.field1 = 1;

                       // a.field2 = 1;// default 필드 접근 불가(컴파일 에러)

                       // a.field3 = 1;// private 필드 접근 불가(컴파일 에러)

                      

                       // public 필드와 메서드만 접근 가능.

                       a.method1();

                       // a.method2();// default 필드 접근 불가(컴파일 에러)

                       // a.method3();// private 필드 접근 불가(컴파일 에러)

           }

}

 

6.14 GetterSetter 메소드

일반적으로 객체 지향 프로그래밍에서 객체의 데이터는 객체 외부에서 직접적으로 접근하는 것을 막습니다.

객체의 데이터를 외부에서 마음대로 읽고 변경할 경우 객체의 무결성이 깨어질 수 있기 때문입니다.

 

예를 들어 자동차의 속도는 음수가 될 수 없는데 외부에서 음수로 변경하면 무결성이 깨집니다

myCar.speed = -100;

 

이러한 문제점 해결을 위해 메서드를 통해 데이터를 변경하는 방법을 선호합니다

데이터는 외부에서 접근할 수 없도록 막고 메서드는 공개해서 

외부에서 메서드를 통해 데이터에 접근하도록 유도하는 것입니다

메서드는 매개값을 검증해서 유효한 값만 데이터로 저장할 수 있기 때문

 

이런 역할을 하는 메서드가 Setter입니다

void setSpeed(double speed) {

    if(speed<0) {

      this.speed = 0;

     return;    

     }

    else {

     this.speed = speed;

     }

 }


외부에서 객체의 데이터를 읽을  때도 메서드를 사용하는 것이 좋습니다

객체 외부에서 객체의 필드값을 사용하기에 부적절한 경우도 있습니다

이런 경우에 메서드로 필드값을 가공한 후 외부로 전달하면 됩니다

이 메서드가 Getter 메서드입니다.

 

double getSpeed() {

    double km = speed *1.6; 필드값인 마일을 km 단위로 환산 후 외부로 리턴

    return km;

  }


클래스를 선언할 때 가능하다면 필드를 private 로 선언해서 외부로부터 보호하고

필드에 대한 Setter Getter 메서드를 작성해서 필드값을 안전하게 변경/사용하는 것이 좋습니다

 

아래 코드는 Setter Getter 메서드를 선언하는 방법을 보여주는 코드입니다.

 

 

private 타입 fieldName;//필드 접근 제한자 :private

 

 

//Getter

public 리턴타입 getFieldName(){

    return fieldName;

 }

 

 

//Setter

public void setFieldName(타입 fieldName) {

   this.fieldName = fieldName;

 }

필드 타입이 boolean 이라면 Getter get으로 시작하는 것이 아니라 is 로 시작하는 것이 관례입니다.

 

 

private boolean stop; //필드 접근 제한자 :private

 

 

//Getter

public boolean isStop() {

   return stop;

 }

 

 

//Setter

public void setStop(boolean stop) {

    this.stop = stop;

 }

만약 외부에서 필드값을 읽을 수만 있고 변경하지 못하도록(읽기 전용)하려면 

Getter 메서드만 선언해도 되고, 아니면 Setter 메서드를 private 접근 제한을 갖도록 선언해도 좋습니다.

이클립스는 선언된 필드에 대해 자동적으로 Getter Setter 메서드를 생성시키는 기능이 있습니다.

필드를 선언한 후 메뉴에서 Source -> Generate Getters and Setters 를 선택하면 

선언된 필드에 대한 Getter Setter 를 자동 생성시킬 수 있습니다.

 

[Car8.java] GetterSetter 메소드 선언

 

public class Car8 {

 

           // 필드

           private int speed;

           private boolean stop;

 

           // 생성자

 

           // 메소드

           public int getSpeed() {

                       return speed;

           }

 

           public void setSpeed(int speed) {

                       if (speed < 0) {

                                  this.speed = 0;

                                  return;

                       } else {

                                  this.speed = speed;

                       }

           }

 

           public boolean isStop() {

                       return stop;

           }

 

           public void setStop(boolean stop) {

                       this.stop = stop;

                       this.speed = 0;

           }

}

[
CarExample8.java] GetterSetter 메소드 사용

 

public class CarExample8 {

           public static void main(String[] args) {

                       Car8 myCar = new Car8();

 

                       // 잘못된 속도 변경

                       myCar.setSpeed(-50);

 

                       System.out.println("현재 속도: " + myCar.getSpeed());

 

                       // 올바른 속도 변경

                       myCar.setSpeed(60);

 

                       // 멈춤

 

                       if (!myCar.isStop()) {

                                  myCar.setStop(true);

                       }

 

                       System.out.println("현재 속도: " + myCar.getSpeed());

           }

}

 

v  클래스 선언할 때 필드는 일반적으로 private 접근 제한

§  읽기 전용 필드가 있을 수 있음 (Getter의 필요성)

§  외부에서 엉뚱한 값으로 변경할 수 없도록 (Setter의 필요성)

§  Getter

§  private 필드의 값을 리턴 하는 역할 - 필요할 경우 필드 값 가공

§  getFieldName() 또는 isFieldName() 메소드

v  필드 타입이 boolean 일 경우 isFieldName()

v  Setter

§  외부에서 주어진 값을 필드 값으로 수정

v  필요할 경우 외부의 값을 유효성 검사

§  setFieldName(타입 변수) 메소드

v  매개 변수 타입은 필드의 타입과 동일

 

6.15 어노테이션

=>어노테이션(Annotation)이란?

§  프로그램에게 추가적인 정보를 제공해주는 메타데이터(metadata)

@AnnotationName

§  어노테이션 용도

v  컴파일러에게 코드 작성 문법 에러 체크하도록 정보 제공

v  소프트웨어 개발 툴이 빌드나 배치 시 코드를 자동 생성하게 정보 제공

v  실행 시(런타임시) 특정 기능 실행하도록 정보 제공

 

컴파일러에게 코드 문법 에러를 체크하도록 정보를 제공하는 대표적인 예는 @Override 어노테이션입니다.

@Override 는 메서드 선언 시 사용, 메서드가 오버라이드(재정의)된 것임을 

컴파일러에게 알려주어 컴파일러가 오버라이드 검사를 하도록 합니다

정확히 오버라이드가 되지 않았다면 컴파일러는 에러를 발생시킵니다

어노테이션은 빌드 시 자동으로 XML 설정 파일을 생성하거나

배포를 위해 JAR 압축 파일을 생성하는데에도 사용됩니다

그리고 실행 시 클래스의 역할을 정의하기도 합니다.



6.15.1 어노테이션 타입 정의와 적용

=>어노테이션 타입 정의

소스 파일 생성: AnnotatoinName.java

v  소스 파일 내용

    • 어노테이션 타입 적용

 

 

어노테이션은 엘리먼트(element)를 멤버로 가질 수 있습니다.

 

 각 엘리먼트는 타입과 이름으로 구성되고, 디폴드 값을 가질 수 있습니다.

public @interface AnnotationName {

  타입 elementName() [default ];

  ...

}

 

엘리먼트의 타입으로는 기본타입이나 String, 열거타입, Class타입 그리고 이들의 배열 타입을 사용있음.

엘리먼트 이름 뒤에는 ()를 붙어야함.

public @interface AnnotationName {

 String elementName1();

 int elementName2() default 5;

}

 

 

이렇게 정의한 어노테이션을 코드에서 적용할 때는 아래와 같이 합니다.

@AnnotationName(elementName1="" , elementName2=3);

또는

@AnnotationName(elementName1="");

 

elementName1은 디폴트 값이 없으므로 반드시 값을 기술해야 하고

elementName2는 디폴트 값이 있으므로 생략가능.

 

v  기본 엘리먼트 value

    • 어노테이션 적용할 때 엘리먼트 이름 생략 가능

    • 두 개 이상의 속성을 기술할 때에는 value=값 형태로 기술

6.15.2어노테이션 적용 대상

§  코드 상에서 어노테이션을 적용할 수 있는 대상

§  java.lang.annotation.ElementType 열거 상수로 정의

 

 

어노테이션 적용대상을 지정할 때에는 @Target 어노테이션을 사용

@Target의 기본 엘리먼트인 value ElementType 배열을 값으로 가집니다

어노테이션이 적용될 대상을 복수 개로 지정하기 위해서입니다.

 

@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})

pubilc @interface AnnotationName{

}

 

 

아래 처럼 클래스, 필드, 메서드만 어노테이션을 적용할 수 있고 생성자는 적용할 수 없습니다.

@AnnotationName

public class ClassName{

    @AnnotationName

    private String fieldName;

 

   //@AnootationName (x)  @Target CONSTRUCTOR 가 없어서 생성자는 적용할 수 없습니다.

   public ClassName() { }

 

  @AnnotationName

  public void methodName() { }

}

 

6.15.3어노테이션 유지 정책

§  어노테이션 적용 코드가 유지되는 시점을 지정하는 것

§  java.lang.annotation.RetentionPolicy 열거 상수로 정의

 

      리플렉션(Reflection): 런타임에 클래스의 메타 정보를 얻는 기능

클래스가 가지고 있는 필드, 생성자, 메소드, 어노테이션의 정보를 얻을 수 있음

런타임 시 어노테이션 정보를 얻으려면 유지 정책을 RUNTIME으로 설정

 

어노테이션 유지 정책을 지정할 때는 @Retention어노테이션을 사용한다.

@Retention의 기본 엘리먼트인 valueRetentionPolicy 타입이므로 위 세 가지 상수 중 하나를 지정.

코드 자동 생성 툴을 개발하지 않는 이상작성하는 어노테이션은 대부분 런타임 시점에 사용하기 위한 용도

 

 

@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

public @interface AnnotationName {

}

 

6.15.4런타임시 어노테이션 정보 사용하기

§  클래스에 적용된 어노테이션 정보 얻기

      클래스.class 의 어노테이션 정보를 얻는 메소드 이용

§  필드, 생성자, 메소드에 적용된 어노테이션 정보 얻기

      다음 메소드 이용해 java.lang.reflect 패키지의 Field, Constructor, Method 클래스의 배열 얻어냄

 

§  Field, Constructor, Method가 가진 다음 메소드 호출

      어노테이션 정보를 얻기 위한 메소드

어노테이션 자체는 표식일 뿐이지만, 리플랙션을 이용해서 어노테이션의 적용 여부와 엘리먼트 값을 읽고 적절히 처리할 수 있습니다. 클래스에 적용된 어노테이션 정보를 얻으려면 java.jang.Class를 이용하면 되지만, 필드, 생성자, 메서드에 적용된 어노테이션 정보를 얻으려면 Class의 다음 메서드를 통해서 java.lang.reflect 패키지의 Field, Constructor, Method 타입의 배열을 얻어야 합니다.

 

[PrintAnnotation] 에노테이션 정의

@Target({ElementType.METHOD})//메소드에만 적용하도록 했고

@Retention(RetentionPolicy.RUNTIME)//런타임 시까지 어노테이션 정보를 유지하도록 했다

public @interface PrintAnnotation {

           String value() default "-";//기본 엘리먼트 value는 구분선에 사용될 문자

           //각각 디폴트 값으로 "-" 15를 주었다.

           int number() default 15;//반복 출력 횟수

}

 

[Service.java] 어노테이션 적용 클래스

public class Service {

           @PrintAnnotation//엘레먼트의 기본값으로 적용했고

           public void method1() {

                       System.out.println("실행 내용1");

           }

 

           @PrintAnnotation("*")//엘레먼트의 value값을 "*"로 설정

           public void method2() {

                       System.out.println("실행 내용2");

           }

 

           @PrintAnnotation(value = "#", number = 20)

           //엘레먼트의 value값을 "#"으로 설정 ,number값을 20으로 설정

           public void method3() {

                       System.out.println("실행 내용3");

           }

}

 

[PrintAnnotationExample.java]

public class PrintAnnotationExample {

           public static void main(String[] args) {

                       //servive클래스로부터 메소드 정보를 얻음

                       //sevice 클래스에 선언된 메소드 얻기(리플렉션)

                       Method[] declaredMethods = Service.class.getDeclaredMethods();

                      

                       //Method 객체를 하나씩 처리

                       for(Method method:declaredMethods) {

                                  //printAnnotation이 적용되었는지 확인

                                  if(method.isAnnotationPresent(PrintAnnotation.class)) {

                                              //PrintAnnotation 객체 얻기

                                              PrintAnnotation printAnnotation = method.getAnnotation(PrintAnnotation.class);

                                             

 

                                              //메소드 이름 출력

                                              System.out.println("[" + method.getName() +"]");

                                              //구분선 출력

                                              for(int i = 0; i <printAnnotation.number() ; i++) {

                                                         System.out.print(printAnnotation.value());

                                              }

                                              System.out.println();

                                             

                                              try {

                                                         //메소드 출력

                                                         method.invoke(new Service());

                                              }catch(Exception e) {

                                                         System.out.println();

                                              }

                                  }

                       }

           }

}

 

 

 

연습문제

1. 객체와 클래스에 대한 설명으로 틀린 것은 무엇입니까? (3)

 

1. 클래스는 객체를 생성하기 위한 설계도 (청사진)와 같은 것이다.

2. new 연산자로 클래스의 생성자를 호출함으로써 객체가 생성된다.

3. 하나의 클래스로 하나의 객체만 생성할 수 있다.

4. 객체는 클래스의 인스턴스이다.

 

2. 클래스의 구성 멤버가 아닌 것은 무엇입니까? (4)

1. 필드 (field)

2. 생성자 (constructor)

3. 메소드 (method)

4. 로컬 변수 (local variable)

 

3. 필드 , 생성자 , 메소드에 대한 설명으로 틀린 것은 무엇입니까? (4)

1. 필드는 객체의 데이터를 저장한다.

2. 생성자는 객체의 초기화를 담당한다.

3. 메소드는 객체의 동작 부분으로, 실행 코드를 가지고 있는 블록이다.

4. 클래스는 반드시 필드와 메소드를 가져야 한다.

 

4. 필드에 대한 설명으로 틀린 것은 무엇입니까? (3)

1. 필드는 메소드에서 사용할 수 있다.

2. 인스턴스 필드 초기화는 생성자에서 할 수 있다.

3. 필드는 반드시 생성자 선언 전에 선언되어야 한다.

4. 필드는 초기값을 주지 않더라도 기본값으로 자동 초기화된다.

 

5. 생성자에 대한 설명으로 틀린 것은 무엇입니까? (1)

1. 객체를 생성하려면 생성자 호출이 반드시 필요한 것은 아니다.

2. 생성자는 다른 생성자를 호출하기 위해 this ()를 사용할 수 있다.

3. 생성자가 선언되지 않으면 컴파일러가 기본 생성자를 추가한다.

4. 외부에서 객체를 생성할 수 없도록 생성자에 private 접근 제한자를 붙일 수 있다.

 

6. 메소드에 대한 설명으로 틀린 것은 무엇입니까? (4)

1. 리턴값이 없는 메소드는 리턴 타입을 void로 해야 한다.

2. 리턴 타입이 있는 메소드는 리턴값을 지정하기 위해 반드시 return문이 있어야 한다.

3. 매개값의 수를 모를 경우 "..."를 이용해서 매개 변수를 선언할 수 있다.

4. 메소드의 이름은 중복해서 선언할 수 없다.

 

7. 메소드 오버로딩에 대한 설명으로 틀린 것은 무엇입니까? (2)

1. 동일한 이름의 메소드를 여러 개 선언하는 것을 말한다.

2. 반드시 리턴 타입이 달라야 한다.

3. 매개 변수와 타입, , 순서를 다르게 선언해야 한다.

4. 매개값의 타입 및 수에 따라 호출될 메소드가 선택된다.

 

8. 인스턴스 멤버와 정적 멤버에 대한 설명으로 틀린 것은 무엇입니까? (2)

1. 정적 멤버는 static으로 선언된 필드와 메소드를 말한다.

2. 인스턴스 필드는 생성자 및 정적 블록에서 초기화될 수 있다.

3. 정적 필드와 정적 메소드는 객체 생성 없이 클래스를 통해 접근할 수 있다.

4. 인스턴스 필드와 메소드는 객체를 생성하고 사용해야 한다.

 

9. final 필드와 상수(static final)에 대한 설명으로 틀린 것은 무엇입니까? (2)

1. final 필드와 상수는 초기값이 저장되면 값을 변경할 수 없다.

2. final 필드와 상수는 생성자에서 초기화될 수 있다.

3. 상수의 이름은 대문자로 작성하는 것이 관례이다.

4. 상수는 객체 생성 없이 클래스를 통해 사용할 수 있다.

 

10. 패키지에 대한 설명으로 틀린 것은 무엇입니까? (4)

1. 패키지는 클래스들을 그룹화시키는 기능을 한다.

2. 클래스가 패키지에 소속되려면 패키지 선언을 반드시 해야 한다.

3. import문은 다른 패키지의 클래스를 사용할 때 필요하다.

4. mycompany 패키지에 소속된 클래스는 yourcompany에 옮겨 놓아도 동작한다.

 

11. 접근 제한에 대한 설명으로 틀린 것은 무엇입니까? (3)

1. 접근 제한자는 클래스, 필드, 생성자, 메소드의 사용을 제한한다.

2. public 접근 제한은 아무런 제한 없이 해당 요소를 사용할 수 있게 한다.

3. default 접근 제한은 해당 클래스 내부에서만 사용을 허가한다.

4. 외부에서 접근하지 못하도록 하려면 private 접근 제한을 해야 한다.

 

12. 다음 클래스에서 해당 멤버가 필드, 생성자, 메소드 중 어떤 것인지 빈칸을 채우세요.

public class Member {

private String name;                            // 필드

 

public Member(String name) {...}            // 생성자

 

public void setName(String name) {...}     // 메소드

}

 

13. 현실 세계의 회원을 Member 클래스로 모델링하려고 합니다. 회원의 데이터로는 이름, 아이디, 패스워드, 나이가 있습니다. 이 데이터들을 가지는 Member 클래스를 선언해보세요.

[Member.java]

public class Member {

           //작성 위치

           private String name;

           private String id;

           private String password;

           private int age;

}

 

14. 위에서 작성한 Member 클래스에 생성자를 추가하려고 합니다. 다음과 같이 Member 객체를 생성할 때 name 필드와 id 필드를 외부에서 받은 값으로 초기화하려면 생성자를 어떻게 선언해야 합니까?

Member user1 = new Member("홍길동","hong");

Member user2 = new Member("강자바","java");

[Member.java]

public class Member {    

           //작성위치

           Member(String name, String id) {

                      

           }

}

 

15. MemberService 클래스에 login() 메소드와 logout() 메소드를 선언하려고 합니다. login() 메소드를 호출할 때에는 매개값으로 idpassword를 제공하고, logout() 메소드는 id만 매개값으로 제공합니다. MemberService 클래스와 login(),logout() 메소드를 선언해보세요.

1. login() 메소드는 매개값 id "hong" , 매개값 password "12345"일 경우에만 true로 리턴하고 그 이외의 값일 경우에는 false를 리턴하도록 하세요.

2. logout() 메소드의 내용은 "로그아웃 되었습니다."가 출력되도록 하세요.

[MemberService.java]

public class MemberService {

           //작성위치

           public boolean login(String id, String password) {

                       if(id=="hong" && password=="12345") {

                                  return true;

                       }else {

                                  return false;

                       }

           }

          

           public void logout(String id) {

                       System.out.println("로그아웃 되었습니다.");

           }

}

 

[MemberServiceExample.java]

public class MemberServiceExample {

           public static void main(String[] args) {

                       MemberService memberService = new MemberService();

                       boolean result = memberService.login("hong", "12345");

                       if(result) {

                                  System.out.println("로그인 되였습니다.");

                                  memberService.logout("hong");

                       }else {

                                  System.out.println("id또는 password가 올바르지 않습니다.");

                       }

           }

}

 

16. PrinterExample 클래스에서 Printer 객체를 생성하고 println() 메소드를 호출해서 매개값을 콘솔에 출력하려고 합니다. println() 메소드의 매개값으로는 int,boolean,double,String 값을 줄 수 있습니다. Printer 클래스에서 println() 메소드를 선언해보세요.

 [Printer.java]

public class Printer {

           //작성 위치

           public void println(int a){

                       System.out.println(a);

           }

          

           public void println(boolean a){

                       System.out.println(a);

           }

          

           public void println(double a){

                       System.out.println(a);

           }

          

           public void println(String a){

                       System.out.println(a);

           }

}

 

 

[PrinterExample.java]

public class PrinterExample {

           public static void main(String[] args) {

                       Printer printer = new Printer();

                       printer.println(10);

                       printer.println(true);

                       printer.println(5.7);

                       printer.println("홍길동");

           }

}

 

17. 16번 문제에는 Printer 객체를 생성하고 println() 메소드를 생성했습니다. Printer 객체를 생성하지 않고 PrinterExample 클래스에서 다음과 같이 호출하려면 Printer 클래스를 어떻게 수정하면 될까요?

 

[Printer2.java]

public class Printer2 {

           //작성 위치

           public static void println(int a){

                       System.out.println(a);

          }

          

           public static void println(boolean a){

                       System.out.println(a);

           }

          

           public static void println(double a){

                       System.out.println(a);

           }

          

           public static void println(String a){

                       System.out.println(a);

           }

}

 [PrinterExample2.java]

public class PrinterExample2 {

           public static void main(String[] args) {

                       Printer2.println(10);

                       Printer2.println(true);

                       Printer2.println(5.7);

                       Printer2.println("홍길동");

           }

}

 

18. ShopService 객체를 싱글톤으로 만들고 싶습니다. ShopServiceExample 클래스에서 ShopService getInstance() 메소드로 싱글톤을 얻을 수 있도록 ShopService 클래스를 작성 해보세요.

[ShopService.java]

public class ShopService {

           private static ShopService singleton = new ShopService();

          

           private ShopService() {}

          

           static ShopService getInstance() {

                       return singleton;

           }

}

 

[ShopServiceExample.java]

public class ShopServiceExample {

           public static void main(String[] args) {

                       ShopService obj1 = ShopService.getInstance();

                       ShopService obj2 = ShopService.getInstance();                      

                       if(obj1 == obj2) {

                                  System.out.println("같은 ShopService 객체 입니다.");

                       }else {

                                  System.out.println("다른 ShopService 객체 입니다.");

                       }

           }

}

 

19. 은행 계좌 객체인 Account 객체는 잔고(balance) 필드를 가지고 있습니다. balance 필드는 음수값이 될 수 없고, 최대 백만 원까지만 저장할 수 있습니다. 외부에서 balance 필드를 마음대로 변경하지 못하도록 하고, 0 <= balance <= 1,000,000 범위의 값만 가질 수 있도록 Acoount 클래스를 작성해보세요.



1. Setter Getter를 이용하세요.

2. 0 1,000,000 MIN_BALANCE MAX_BALANCE 상수를 선언해서 이용하세요.

3. Setter의 매개값이 음수이거나 백만 원을 초과하면 현재 balance 값을 유지하세요.

 

 

[Account.java]

public class Account {

           //작성위치

           static final int MIN_BALANCE = 0;

           static final int MAX_BALANCE = 1000000;

          

           private int balance;

 

           public int getBalance() {

                       return balance;

           }

 

           public void setBalance(int balance) {

                       if(balance < MIN_BALANCE || balance > MAX_BALANCE) {

                                  return ;

                       }

                       this.balance = balance;

           }

}

 

 

[AccountExample.java]

public class AccountExample {

           public static void main(String[] args) {

 

                       Account account = new Account();

                      

                       account.setBalance(10000);

                       System.out.println("현재 잔고:" + account.getBalance());

                      

                       account.setBalance(-100);

                       System.out.println("현재 잔고:" + account.getBalance());

                      

                       account.setBalance(2000000);

                       System.out.println("현재 잔고:" + account.getBalance());

                      

                       account.setBalance(300000);

                       System.out.println("현재 잔고:" + account.getBalance());

           }

}

 

20. 다음은 키보드로부터 계좌 정보를 입력받아서, 계좌를 관리하는 프로그램입니다. 실행 결과를 보고, 알맞게 BankApplication 클래스의 메소드를 작성해보세요.

 

[Account2.java]

public class Account2 {

           private String ano;

           private String owner;

           private int balance;

          

           public Account2(String ano, String owner, int balance) {

                       this.ano = ano;

                       this.owner = owner;

                       this.balance = balance;

           }

 

           public String getAno() {

                       return ano;

           }

 

           public void setAno(String ano) {

                       this.ano = ano;

           }

 

           public String getOwner() {

                       return owner;

 

           }

 

           public void setOwner(String owner) {

                       this.owner = owner;

           }

 

           public int getBalance() {

                       return balance;

           }

 

           public void setBalance(int balance) {

                       this.balance = balance;

           }

          

}

 

 

[BankApplication.java]

public class BankApplication {

           private static Account2[] accountArray = new Account2[100];

           private static Scanner scanner = new Scanner(System.in);

 

           public static void main(String[] args) {

                       boolean run = true;

                       while (run) {

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

                                  System.out.println("1.계좌생성 | 2.계좌목록 | 3.예금 | 4.출금 | 5.종료");

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

                                  System.out.print("선택> ");

 

                                  int selectNo = scanner.nextInt();

 

                                  if (selectNo == 1) {

                                              createAccount();

                                  } else if (selectNo == 2) {

                                              accountList();

                                  } else if (selectNo == 3) {

                                              deposit();

                                  } else if (selectNo == 4) {

                                              withdraw();

                                  } else if (selectNo == 5) {

                                              run = false;

                                  }

                       }

                       System.out.println("프로그램 종료");

 

           }

 

           // 계좌 생성하기

           private static void createAccount() {

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

                       System.out.println("계좌생성");

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

 

                       System.out.print("계좌번호:");

                       String ano = scanner.next();

 

                       System.out.print("계좌주:");

                       String owner = scanner.next();

 

                       System.out.print("초기입금액:");

                       int balance = scanner.nextInt();

 

                       Account2 account = new Account2(ano, owner, balance);

                       for (int i = 0; i < accountArray.length; i++) {

                                  if (accountArray[i] == null) {

                                              accountArray[i] = account;

                                              System.out.println("결과 : 계좌가 생성되었습니다.");

                                              break;

                                  }

                       }

           }

 

           // 계좌 목록 보기

           private static void accountList() {

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

                       System.out.println("계좌목록");

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

 

                       for (int i = 0; i < accountArray.length; i++) {

                                  Account2 account = accountArray[i];

                                  if (accountArray[i] != null) {

                                              System.out.print(account.getAno());

                                              System.out.print("   ");

                                              System.out.print(account.getOwner());

                                              System.out.print("   ");

                                              System.out.print(account.getBalance());

                                              System.out.println();

                                  }

                       }

 

           }

 

           // 예금하기

           private static void deposit() {

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

                       System.out.println("예금");

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

                      

                       System.out.print("계좌번호:");

                       String ano = scanner.next();

 

                       System.out.print("예금액:");

                       int money = scanner.nextInt();

                      

                       Account2 account = findAccount(ano);

                      

                       if(account == null) {

            System.out.println("결과: 계좌가 없습니다.");

            return;

        }

                      

                       account.setBalance(account.getBalance() + money);

                       System.out.println("결과: 입금이 성공되었습니다.");

           }

 

           // 출금하기

           private static void withdraw() {

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

                       System.out.println("출금");

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

                      

                       System.out.print("계좌번호:");

                       String ano = scanner.next();

 

                       System.out.print("출금액:");

                       int money = scanner.nextInt();

                      

                       Account2 account = findAccount(ano);

                       if(account == null) {

            System.out.println("결과: 계좌가 없습니다.");

            return;

        }

                      

                       account.setBalance(account.getBalance() - money);

 

                       System.out.println("결과: 출금이 성공되었습니다.");

           }

 

           // Account 배열에서 ano동일한 Account 객체 찾기

           private static Account2 findAccount(String ano) {

                       Account2 account = null;

                       for(int i = 0 ; i< accountArray.length ;i++) {

                                  if(accountArray[i]  != null) {

                                              if(accountArray[i].getAno().equals(ano)) {

                                                         account = accountArray[i];

                                                         break;

                                              }

                                  }

                       }

                       return account;

           }

}

 

 

반응형

' > 이것이 자바다' 카테고리의 다른 글

08. 인터페이스  (0) 2020.09.30
07. 상속  (0) 2020.09.29
05. 참조 타입  (0) 2020.09.27
04. 조건문과 반복문  (0) 2020.09.26
03. 연산자  (0) 2020.09.24

+ Recent posts