1.  객체 타입 확인

boolean result = 객체 instance of 타입;

 

🚀  매개변수의 다형성에서 실제로 어떤 객체가 매개값으로 제공되었는지 확인할 때 사용

🚀  꼭 매개변수가 아니더라도 변수가 참조하는 객체의 타입을 확인하고자 할 때 instance of 연산자를 사용할 수 있다

  • 좌항에는 객체가 오고 우항에는 타입이 위치
  • 좌항의 객체가 우항의 타입이 일치하면 true를 산출하고 그렇지 않으면 false를 산출
if(parent instance of Child child) {
    // child 변수 사용
}

 

사용 예제

 

public class Person {
	//필드 선언
	public String name;

	//생성자 선언
	public Person(String name) {
		this.name = name;
	}

	//메소드 선언
	public void walk() {
		System.out.println("걷습니다.");
	}
}
public class Student extends Person {
	//필드 선언
	public int studentNo;

	//생성자 선언
	public Student(String name, int studentNo) {
		super(name);
		this.studentNo = studentNo;
	}

	//메소드 선언
	public void study() {
		System.out.println("공부를 합니다.");
	}
}

 

public class InstanceofExample {

	//main() 메소드에서 바로 호출하기 위해 정적 메소드 선언
	public static void personInfo(Person person) {
		System.out.println("name: " + person.name);
		person.walk();

		//person이 참조하는 객체가 Student 타입인지 확인
		/*if (person instanceof Student) {
        
 			//Student 객체일 경우 강제 타입 변환
 			Student student = (Student) person;
            
 			//Student 객체만 가지고 있는 필드 및 메소드 사용
 			System.out.println("studentNo: " + student.studentNo);
 			student.study();
            
 		}*/

		// person이 참조하는 객체가 Student 타입일 경우
		// student 변수에 대입(타입 변환 발생)- java 12~
		if(person instanceof Student student) {
			System.out.println("studentNo: " + student.studentNo);
			student.study();
		}
	}

	public static void main(String[] args) {
		//Person 객체를 매개값으로 제공하고 personInfo() 메소드 호출
		Person p1 = new Person("홍길동");
		personInfo(p1);
		
		System.out.println();

		//Student 객체를 매개값으로 제공하고 personInfo() 메소드 호출
		Person p2 = new Student("김길동", 10);
		personInfo(p2);
	}
    
}

 

 

 

* 내용 참고 - 책 '이것이 자바다'

'Programming Language > JAVA' 카테고리의 다른 글

[Java] 다형성  (0) 2024.08.24
[Java] 타입 변환  (0) 2024.08.24
[Java] final 클래스와 final 메소드 · protected 접근 제한자  (0) 2024.08.23
[Java] 오버라이딩 Overriding  (0) 2024.08.11
[Java] 상속 Inheritance  (0) 2024.08.11


 

1.  다형성  polymorphism

🚀  사용 방법은 동일하지만 실행 결과가 다양하게 나오는 성질을 말함

🚀  객체는 부품과 같아서 프로그램을 구성하는 객체를 바꾸면 프로그램의 실행 성능이 다르게 나올 수 있다.

 

  • 객체 사용 방법이 동일하다는 것은 동일한 메소드를 가지고 있다는 뜻
  • 한국 타이어와 금호 타이어는 모두 타이어를 상속하고 있으므로 부모의 메소드를 동일하게 가지고 있다고 말할 수 있다.
  • 타이어 메소드 호출 시 오버라이딩 된 메소드가 호출되는데, 오버라이딩 된 내용은 두 타이어가 다르기 때문에 실행 결과가 다르게 나옴
  • 이것을 '다형성' 이라고 하는데 다형성을 구현하기 위해서는 자동 타입 변환과 메소드 재정의가 필요하다.


1)  필드 다형성

  👾  필드 타입은 동일하지만(사용 방법은 동일하지만) 대입되는 객체가 달라져서 실행 결과가 다양하게 나올 수 있는 것을 말한다.

 

public class Car {
	//필드 선언
	public Tire tire;

	//메소드 선언
	public void run() {
		//tire 필드에 대입된 객체의 roll() 메소드 호출
		tire.roll();
	}
}
public class Tire {
	//메소드 선언
	public void roll() {
		System.out.println("회전합니다.");
	}
}

 

public class HankookTire extends Tire {
	//메소드 재정의(오버라이딩)
	@Override
	public void roll() {
		System.out.println("한국 타이어가 회전합니다.");
	}
}
public class KumhoTire extends Tire {
	//메소드 재정의(오버라이딩)
	@Override
	public void roll() {
		System.out.println("금호 타이어가 회전합니다.");
	}
}

 

public class CarExample {
	public static void main(String[] args) {
		//Car 객체 생성
		Car myCar = new Car();

		//Tire 객체 장착
		myCar.tire = new Tire();
		myCar.run();

		//HankookTire 객체 장착
		myCar.tire = new HankookTire();
		myCar.run();

		//KumhoTire 객체 장착
		myCar.tire = new KumhoTire();
		myCar.run();
	}
}

 

  • Car 클래스의 run() 메소드는 tire 필드에 대입된 객체의 roll() 메소드를 호출한다.
  • 어떤 타이어를 장착했는지에 따라 roll() 메소드의 실행 결과는 달라지게 된다. 이것이 바로 '필드의 다형성'이라고 함

 

2)  매개변수 다형성

  👾  다형성은 필드보다는 메소드를 호출할 때 많이 발생함

  👾  메소드가 클래스 타입의 매개변수를 가지고 있을 경우, 호출할 때 동일한 타입의 객체를 제공하는 것이 정석이지만 자식 객체를 제공할 수도 있다.

 

public class Driver {
    public void drive(Vehicle vehicle) {
      vehicle.run();
    }
}
  • drive() 메소드는 매개값으로 전달받은 vehicle의 run() 메소드를 호출함
Driver driver = new Driver();
Vehicle vehicle = new Vehicle();
driver.drive(vehicle);

 

  • 일반적으로 drive() 메소드를 호출한다면 위와 같이 Vehicle의 객체를 제공
  • but, 자동 타입 변환으로 인해 매개값으로 Vehicle의 자식 객체도 제공할 수 있음!

  ⚡️  drive() 메소드는 매개변수 vehicle이 참조하는 객체의 run() 메소드를 호출하는데, 자식 객체가 run() 메소드를 재정의하고 있다면 재정의된 run() 메소드가 호출된다.

      ☑️  어떤 자식 객체가 제공하느냐에 따라 drive() 실행 결과는 달라진다. 이것이 '매개변수의 다형성'

 

public class Vehicle {
	//메소드 선언
	public void run() {
		System.out.println("차량이 달립니다.");
	}
}
public class Bus extends Vehicle {
	//메소드 재정의(오버라이딩)
	@Override
	public void run() {
		System.out.println("버스가 달립니다.");
	}
}
public class Taxi extends Vehicle {
	//메소드 재정의(오버라이딩)
	@Override
	public void run() {
		System.out.println("택시가 달립니다.");
	}
}
public class Driver {
	//메소드 선언(클래스 타입의 매개변수를 가지고 있음)
	public void drive(Vehicle vehicle) {
		vehicle.run();
	}
}
public class DriverExample {
	public static void main(String[] args) {
		//Driver 객체 생성
		Driver driver = new Driver();

		//매개값으로 Bus 객체를 제공하고 driver() 메소드 호출
		Bus bus = new Bus();
		driver.drive(bus);

		//매개값으로 Taxi 객체를 제공하고 driver() 메소드 호출
		Taxi taxi = new Taxi();
		driver.drive(taxi);
	}
}

 

 

응용 예제
public class Product {
    int price; // 제품의 가격
    int bonusPoint; // 제품구매 시 제공하는 보너스 점수

    Product(int price){
        this.price = price;
        this.bonusPoint = (int)(price / 10.0); // 보너스점수는 제품가격의 10%
    }
}

 

public class Tv extends Product{
    Tv () {
        // 부모클래스의 생성자 Product(int price)를 호출한다.
        super(100); // Tv의 가격을 100만원으로 한다.
    }

    @Override
    public String toString() {
        return "Tv";
    }
}
public class Audio extends Product{
    Audio() {
        super(50);
    }

    @Override
    public String toString() {
        return "Audio";
    }
}
public class Computer extends Product{
    Computer () {
        super(200);
    }

    @Override
    public String toString() {
        return "Computer";
    }
}

 

1. Object 클래스 상속:
    -  모든 Java 클래스는 자동으로 Object 클래스를 상속받는다. Object 클래스는 모든 클래스의 최상위 부모 클래스이고, 이 클래스에서 제공하는 여러 메서드들이 모든 클래스에서 사용할 수 있게 된다. 그 중 하나가 toString() 메서드

2. toString() 메서드:
    -  Object 클래스에는 이미 toString() 메서드가 정의되어 있기 때문에, 어떤 클래스든 toString() 메서드를 오버라이딩할 수 있다. 따라서, Product 클래스에 따로 toString() 메서드를 정의하지 않더라도, Tv 클래스에서 이 메서드를 오버라이딩하는 것이 가능

 

public class Buyer { // 고객, 물건을 사는 사람
        int money = 1000; // 소유금액
        int bonusPoint = 0; // 보너스점수

        /* Product[] products = new Product[10]; // 구입한 제품을 저장하기 위한 배열
        int i = 0; // Product 배열에 사용될 카운터 */
        
        ArrayList<Product> products = new ArrayList<>();

        void buy (Product product){ // 부모클래스 타입으로 매개변수 받음.
            // 부모 클래스의 필드 사용. price, bonusPoint
            if (money < product.price) {
                System.out.println("잔액이 부족하여 물건을 살 수 없습니다.");
                return;
            }
            money -= product.price;  // 가진 돈에서 구입한 제품의 가격을 뺀다.
            bonusPoint += product.bonusPoint; // 제품의 보너스 점수를 추가한다.
            products.add(product); // 구입한 제품을 ArrayList에 저장한다.
            System.out.println(product + " 을/를 구입하셨습니다.");
        }
        
        void summary () { // 구매한 물품에 대한 정보를 요약해서 보여 준다.
            int sum = 0; // 구입한 물품의 가격합계
            String itemList = ""; // 구입한 물품목록

            if(products.isEmpty()) { // ArrayList가 비어있는지 확인한다.
                System.out.println("구입하신 제품이 없습니다.");
                return;
            }
            // ArrayList의 i번째에 있는 객체를 얻어 온다.
            for(int i =0; i < products.size(); i++) {
                Product product = products.get(i);
                sum += product.price;
                itemList += (i==0) ? "" + product : ", " + product;
            }


          /*  // 반복문을 이용해서 구입한 물품의 총 가격과 목록을 만든다.
            // 1) for 이용
            for (int i = 0; i < products.length; i++) {
                if (products[i] == null)
                    break;
                sum += products[i].price;
                itemList += products[i] + ", ";
            }
            // 2) foreach 사용
            // for(각 요소의 타입과 요소를 담을 변수 : 배열 또는 컬렉션)
            for (Product product : products) {
                if (product == null)
                    break;
                sum += product.price;
                itemList += product + ", ";
            }

            // 3) 반복을 줄이기 위해 인스턴스 변수 사용
            for (int i = 0; i < this.i; i++) {
                sum += products[i].price;
                itemList += products[i] + ", ";
            } */

            System.out.println("구입하신 물품의 총금액은 " + sum + "만원입니다.");
            System.out.println("구입하신 제품은 " + itemList + "입니다.");
        }

        void refund(Product product) { // 구입한 제품을 환불한다.
            if (products.remove(product)) { // 제품을 ArrayList에서 제거한다.
                money += product.price;
                bonusPoint -= product.bonusPoint;
                System.out.println(product + "을/를 반품하셨습니다.");
            } else { // 제거에 실패한 경우
                System.out.println("구입하신 제품 중 해당 제품이 없습니다.");
            }
        }
        
}
public class Test {
    /*
    코딩 순서 : Product -> Tv -> Computer -> Buyer -> Test
     */
    public static void main(String[] args) {
        Buyer b = new Buyer();
        Tv tv = new Tv();
        Computer com = new Computer();
        Audio audio = new Audio();

        b.buy(tv); // Tv 을/를 구입하셨습니다.
        b.buy(com); // Computer 을/를 구입하셨습니다.
        b.buy(audio); // Audio 을/를 구입하셨습니다.
        b.summary(); // 구입하신 물품의 총금액은 350만원입니다. 구입하신 제품은 Tv, Computer, Audio입니다.
        System.out.println(); 
        b.refund(com); // Computer을/를 반품하셨습니다.
        b.summary(); // 구입하신 물품의 총금액은 150만원입니다. 구입하신 제품은 Tv, Audio입니다.
    }
}

 

 

 

 

* 내용 참고 - 책 '이것이 자바다' 및 학원 강의 자료


1.  타입 변환

⚒️  타입을 다른 타입으로 변환하는 것을 말함

⚒️  클래스의 타입 변환은 상속 관계에 있는 클래스 사이에서 발생

 

 

1)  자동 타입 변환  Promotion

부모타입 변수 = 자식타입객체;

 

  📍 자식은 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급될 수 있다.

Cat cat = new Cat();
Animal animal = cat;

  📍  cat과 animal 변수는 타입만 다를 뿐, 동일한 Cat 객체를 참조

cat == animal  // true

class A {
}

class B extends A {
}

class C extends A {
}

class D extends B {
}

class E extends C {
}

public class PromotionExample {
	public static void main(String[] args) {
		B b = new B();
		C c = new C();
		D d = new D();
		E e = new E();

		A a1 = b;
		A a2 = c;
		A a3 = d;
		A a4 = e;
		
		B b1 = d;
		C c1 = e;
		
		// B b3 = e;
		// C c2 = d;
	}
}

 

  • 부모 타입으로 자동 타입 변환된 이후에는 부모 클래스에 선언된 필드와 메소드만 접근이 가능
  • 변수는 자식 객체를 참조하지만 변수로 접근 가능한 멤버는 부모 클래스 멤버로 한정
  • 자식 클래스에서 오버라이딩된 메소드가 있다면 부모 메소드 대신 오버라이딩된 메소드가 호출됨


 

2)  강제 타입 변환  Casting

자식타입 변수 = (자식타입) 부모타입객체;
Parent parent = new Child();   // 자동 타입 변환
Child child = (Child) parent;  // 강제 타입 변환

 

⚒️  부모 타입은 자식 타입으로 자동 변환되지 않는다. 대신 캐스팅 연산자로 강제 타입 변환을 할 수 있다.

⚒️  자식 객체가 부모 타입으로 자동 변환하면 부모 타입에 선언된 필드와 메소드만 사용 가능  

       ➡️  만약 자식 타입에 선언된 필드와 메소드를 꼭 사용해야 한다면 강제 타입 변환을 해서 다시 자식타입으로 변환해야 함

 

 

 

 

 

 

* 내용 참고 - 책 '이것이 자바다'

 


 

1.  final 클래스와 final 메소드

1)  final 클래스

public final class 클래스 { ... }

 

🚀  클래스를 선언할 때 final 키워드를 class 앞에 붙이면 최종적인 클래스이므로 더 이상 상속할 수 없는 클래스가 됨

 

 

2)  final 메소드 

public final 리턴타입 메소드( 매개변수, ...) { ... }

 

🚀  메소드를 선언할 때 final 키워드를 붙이면 이 메소드는 최종적인 메소드이므로 오버라이딩할 수 없는 메소드가 됨

 

 


2.  protected 접근 제한자

 

🚀  같은 패키지에서는 default처럼 접근이 가능하나, 다른 패키지에서는 자식 클래스만 접근을 허용

package package1;

public class A {
	//필드 선언
	protected String field;

	//생성자 선언
	protected A() {
	}

	//메소드 선언
	protected void method() {
	}
}

 

같은 패키지
package package1;

public class B {
	//메소드 선언
	public void method() {
		A a = new A();		//o
		a.field = "value"; 	//o
		a.method(); 			//o
	}
}

 

다른 패키지
package package2;

import package1.A;

public class C {
	//메소드 선언
	public void method() {
		//A a = new A();		//x
		//a.field = "value"; 		//x
		//a.method(); 			//x
	}
}

 

다른 패키지 & 자식 클래스
package package2;

import package1.A;

public class D extends A {
	//생성자 선언
	public D() {
		//A() 생성자 호출
		super();				//o
	}
	
	//메소드 선언
	public void method1() {
		//A 필드값 변경
		this.field = "value"; 	//o
		//A 메소드 호출
		this.method(); 			//o
	}
	
	//메소드 선언
	public void method2() {
		//A a = new A();		//x
		//a.field = "value"; 	//x
		//a.method(); 			//x
	}	
}

 

  ⚡️  new 연산자를 사용해서 생성자를 직접 호출할 수는 없고, 자식 생성자에서 super()로 A 생성자를 호출할 수 있다.

 

 

 

 

 

* 내용 참고 : 책 '이것이 자바다'

'Programming Language > JAVA' 카테고리의 다른 글

[Java] 다형성  (0) 2024.08.24
[Java] 타입 변환  (0) 2024.08.24
[Java] 오버라이딩 Overriding  (0) 2024.08.11
[Java] 상속 Inheritance  (0) 2024.08.11
[Java] Getter와 Setter · 싱글톤 패턴  (0) 2024.08.11

 


1.  객체 지향 프로그래밍  Object Oriented Programming

🚀  소프트웨어를 개발할 때 부품에 해당하는 객체들을 먼저 만들고, 이 객체들을 하나씩 조립해서 완성된 프로그램을 만드는 기법

  ⚒️  객체지향 이론 기본 개념 : 실제 세계는 사물(객체)로 이루어져 있으며, 발생하는 모든 사건들은 사물간의 상호작용.

  ⚒️  발전 단계 : 기본자료형  →  배열  →  구조체  →  클래스

  • 구조체는 서로 다른 타입도 하나에 묶을 수 있도록 함
  • 구조체가 발전된 형태(함수까지 포함)가 클래스
70년대 -  C, 변수와 함수, 구조체
80년대 -  C++, 변수와 함수, 구조체, 클래스
90년대 -  Java, only 클래스만… 하지만 클래스안에 변수와 메서드가 있음

 

 

​  ⚒️  주요특징

 

    1.  캡슐화 Encapsulation

       

        -  객체의 데이터(필드), 동작(메소드)을 하나로 묶고 실제 구현 내용을 외부에 감추는 것

        -  외부 객체는 객체 내부의 구조를 알지 못하며 객체가 노출해서 제공하는 필드와 메소드만 이용할 수 있다

        -  외부의 잘못된 사용으로 인해 객체가 손상되지 않도록 하는 데 의의가 있다

        -  자바 언어는 접근 제한자를 사용하여 캡슐화된 멤버를 노출시킬 것인지 숨길 것인지 결정

 

    2.  상속 Inheritance

 

     

-  부모 객체가 자기가 가지고 있는 필드와 메소드를 자식 객체에게 물려줌

-  코드의 재사용성을 높여준다

-  유지 보수 시간을 최소화 시켜 준다

 

   

 

    3.  다형성 Polymorphism

       

 

-  사용 방법은 동일하지만 실행 결과가 다양하게 나오는 성질을 말함

-  자동 타입 변환과 재정의 기술이 필요함  ➡️  상속과 인터페이스 구현을 통해 얻어짐

 

 

 

 

 


1)  객체란 ?

  👾  물리적으로 존재하거나 개념적인 것 중에서 다른 것과 식별 가능한 것

  👾  객체는 속성과 동작으로 구성   ex. 사람은 이름, 나이 등의 속성과 웃다, 걷다 등의 동작이 있음

         ➡️  자바는 이러한 속성과 동작을 각각 '필드 field' '메소드 method' 라고 부름

  👾  현실 세계의 객체를 소프트웨어 객체로 설계하는 것을 객체 모델링 object modeling 이라고 함

 

객체의 상호작용
  • 현실 세계에서 일어나는 모든 현상은 객체와 객체 간의 상호작용으로 이루어져 있다.
  • 객체 지향 프로그램에서도 객체들은 다른 객체와 서로 상호작용하면서 동작함.
  • 객체들 사이의 상호작용 수단은 메소드. 객체가 다른 객체의 기능을 이용할 때 이 메소드를 호출한다.
// 메소드 호출 형식
메소드(매개값1, 매개값2, ...);
  • 메소드 이름과 함께 전달하고자 하는 데이터를 괄호() 안에 기술하는데, 이러한 데이터를 매개값이라고 함.
  • 리턴값은 메소드의 실행의 결과이며 호출한 곳으로 돌려주는 값

 

객체 간의 관계

 

  1.  집합 관계  -  완성품과 부품의 관계를 말함. 

        ex.  자동차는 엔진, 타이어, 핸들 등으로 구성

  2. 사용 관계  -  다른 객체의 필드를 읽고 변경하거나 메소드를 호출하는 관계

        ex. 사람이 자동차에 달린다, 멈춘다 등의 메소드를 호출

  3. 상속 관계  -  부모와 자식 관계.

        ex. 자동차가 기계의 특징(필드, 메소드)을 물려받는다면 기계(부모)와 자동차(자식)는 상속 관계에 있음


2)  객체와 클래스

🚀  클래스 Class  -  객체를 생성하기 위한 설계도

  • 클래스로부터 생성된 객체를 해당 클래스의 '인스턴스 instance' 라고 부른다
  • 클래스로부터 객체를 만드는 과정을 인스턴스화라고 함
  • 동일한 클래스로부터 여러 개의 인스턴스를 만드는 것 = 동일한 설계도로 여러 대의 자동차를 만드는 것

 ⚒️  ​객체는 모든 인스턴스를 대표하는 포괄적인 의미를 갖고 있으며,  인스턴스는 어떤 클래스로부터 만들어진 것인지를 강조하는 구체적인 의미를 갖고 있다.

 


3)  객체 생성과 클래스 변수 

 🚀  클래스로부터 객체를 생성하려면 객체 생성 연산자인 'new' 가 필요

 🚀  new 연산자 뒤에는 생성자 호출 코드가 오는데, 클래스() 형태를 가진다.

 🚀  객체를 생성시킨 후 객체의 주소를 리턴하기 때문에 클래스 변수에 다음과 같이 대입할 수 있다.

클래스 변수 = new 클래스();

 

사용 예제
  • Student 클래스를 선언하고 StudentExample 클래스의 main() 메소드에서 Student 객체를 생성
public class Student {}
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 객체를 참조합니다.");
    }
}

 

💡  클래스의 두 가지 용도
      - 라이브러리(library) 클래스 : 실행할 수 없으며 다른 클래스에서 이용하는 클래스
      - 실행 클래스 : main() 메소드를 가지고 있는 실행 가능한 클래스
      - Student는 라이브러리 클래스이고 StudentExample은 실행 클래스라고 볼 수 있음. 일반적으로 자바 프로그램은 하나의 실행 클래스와 여러 개의 라이브러리 클래스들로 구성된다. 

 


 4)  클래스의 구성 멤버

🚀  클래스 선언에는 객체 초기화 역할을 담당하는 생성자와 객체에 포함될 필드와 메소드를 선언하는 코드가 포함된다. 

 

  1.  필드 field 

     -  선언 형태는 변수 선언과 비슷하지만 쓰임새는 다름

 

  2. 생성자 constructor 

     -  new 연산자로 객체를 생성할 때 객체의 초기화 역할을 담당.

     -  선언 형태는 메소드와 비슷하지만, 리턴 타입이 없고 이름은 클래스 이름과 동일

 

  3. 메소드 method

     -  다른 프로그램 언어에서는 함수라고 하기도 하는데, 객체 내부의 함수는 메소드라고 부름

     -  메소드는 객체와 객체간의 상호 작용을 위해 호출

 


5)  필드 선언과 사용

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

 

  👾  반드시 클래스 블록에서 선언되어야만 필드 선언이 된다.

  👾  필드명은 첫 문자를 소문자로 하되, 캐멀 스타일로 작성하는 것이 관례.

public class Car {
    String model = "그렌저";  // 고유 데이터 필드
    int speed = 300;        // 상태 데이터 필드
    boolean start = true;   // 상태 데이터 필드
    Tire tire = new Tire(); // 부품 객체 필드
}

 

   👾  초기값을 제공하지 않을 경우 필드는 객체 생성 시 자동으로 기본값으로 초기화된다.

public class Car {
    String model;  // null
    int speed;     // 0
    boolean start; // false
    Tire tire;     // null
}

 

필드 사용

 

   👾  필드를 사용한다는 것은 필드값을 읽고 변경하는 것을 말함

   👾  필드는 객체의 데이터이므로 객체가 존재하지 않으면 필드도 존재하지 않음

   👾  필드는 객체 내부의 생성자와 메소드 내부에서 사용할 수 있고, 객체 외부에서도 접근해서 사용할 수 있다.

 

  ⚡️  객체 내부에서는 단순히 필드명으로 읽고 변경 가능

  ⚡️  외부 객체에서는 참조 변수와 도트(.) 연산자를 이용해서 필드를 읽고 변경해야 함

  ⚡️  도트는 객체 접근 연산자로, 객체가 가지고 있는 필드나 메소드에 접근하고자 할 때 참조 변수 뒤에 붙임

 

💡  참조변수에는 하나의 값(주소)만이 저장될 수 있으므로 둘 이상의 참조변수가 하나의 인스턴스를 가리키는(참조하는) 것은 가능하지만 하나의 참조변수로 여러 개의 인스턴스를 가리키는 것은 불가능

 

필드 VS 변수
구분 필드 (로컬) 변수
선언 위치 클래스 선언 블록 생성자, 메소드 선언 블록
존재 위치 객체 내부에 존재 생성자, 메소드 호출 시에만 존재
사용 위치 객체 내,외부 어디든 사용 생성자, 메소드 블록 내부에서만 사용

 

사용 예제
public class Car {
    boolean powerOn; // 시동
    String color; // 차량의 색상
    int wheel; // 바퀴의 수
    int speed; // 속력
    boolean wiperOn; // 와이퍼

    void power() {
        powerOn = !powerOn; // 시동 메서드
    }
    void speedUp(){
        speed++; // 액셀 메서드
    }
    void sppedDown() {
        speed--; // 브레이크 메서드
    }
    void wiper(){
        wiperOn = !wiperOn; // 와이퍼 메서드
    }
}
public class CarTest {
    public static void main(String[] args) {
        Car mycar; // 클래스의 객체를 참조할 수 있는 참조변수 선언
        mycar = new Car(); // 클래스의 객체를 생성하고 객체의 주소를 참조변수에 저장

        System.out.println("시동 처음 초기화 : " + mycar.powerOn);
        System.out.println("차의 색상 초기화 : " + mycar.color);
        System.out.println("바퀴의 수 초기화 : " + mycar.wheel);
        System.out.println("속력 초기화 : " + mycar.speed);
        System.out.println("와이퍼 작동 초기화 : " + mycar.wiperOn);

        mycar.power(); // 시동 메서드 실행
        System.out.println("시동 메서드 동작 : " + mycar.powerOn);
        mycar.power();
        System.out.println("시동 메서드 다시 동작 : " + mycar.powerOn);

        mycar.color = "black"; // 색상 변수에 black 대입
        System.out.println("현재 차의 색상 : " + mycar.color);

    }
}
시동 처음 초기화 : false
차의 색상 초기화 : null
바퀴의 수 초기화 : 0
속력 초기화 : 0
와이퍼 작동 초기화 : false
시동 메서드 동작 : true
시동 메서드 다시 동작 : false
현재 차의 색상 : black
 
 

 

 

*  내용 참고 - 학원강의 및 책 '이것이 자바다'


1.  Switch 문

🔅 단 하나의 조건식으로 많은 경우의 수를 처리할 수 있고 표현도 간결

수행 절차

 

  • 조건식을 계산한다.
  • 조건식의 결과와 일치하는 case문으로 이동
  • 이후의 문장들을 수행
  • break 문이나 switch문의 끝을 만나면 switch문 전체를 빠져나감
💡  POINT

     -  break문을 생락하면 case문 사이의 구분이 없어지므로 다른 break문을 만나거나 switch문 블럭 {} 끝을 만날 때까지 나오는 모든 문장들을 수행

    -  제약조건
   
   a.
조건식 결과는 정수 또는 문자열

       b. case문의 값은 정수 상수만 가능, 중복 X

    -  if문 처럼 중첩 가능

switch (조건식) {
    case 값1 :
        // 조건식의 결과가 값1과 같을 경우 수행될 문장들
        //...
        break;
    case 값2 :
        // 조건식의 결과가 값2과 같을 경우 수행될 문장들
        //...
        break;
    default :
        // 조건식의 결과와 일치하는 case 문이 없을 때 수행될 문장들
        //...
        break; // 생략가능.
}

 

조건식이 정수인 경우
public static void main(String[] args) {
    // 일년 동안 읽은 책 수에 따라 멘트를 출력합니다.
		
    int book = 5;
    switch (book/10) {
	    case 0 : // 10권 미만
		    System.out.println("조금 더 노력 하세요!");
		    break;
		case 1 : // 10이상 20권 미만
		    System.out.println("책 읽는 것을 즐기는 분이시네요!");
		    break;
		case 2 : // 20이상 30권 미만
		    System.out.println("책을 사랑하는 분이시네요!");
		    break;
		default : // 30권 이상
		    System.out.println("당신은 다독왕입니다!");
		    break; // 생략가능
    }
}

 

조건식이 문자열인 경우
public static void main(String[] args) {
		
    String medal = "Silver";
		
	switch(medal) {
	    case "Gold":
		    System.out.println("금메달 입니다.");
		    break;
		case "Silver":
		    System.out.println("은메달 입니다.");
		    break;
		case "Bronze":
		    System.out.println("동메달 입니다.");
		    break;
		default:
		    System.out.println("메달이 없습니다.");
		    break;
    }
}

 
​응용 예제
public static void main(String[] args) {
		
    Scanner scanner = new Scanner(System.in);
	System.out.print("월을 입력해 주세요 >>> ");
	int month = scanner.nextInt();
	int day;
		
	switch(month) {
//		case 1: case 3: case 5: case 7: case 8: case 10: case 12:
		case 1, 3, 5, 7, 8, 10, 12: // case가 여러가지인 경우 생략 가능.
			day = 31;
		    break;
		case 4: case 6: case 9: case 11:
			day = 30;
			break;
		case 2:
			day = 28;
			break;
		default:
			day = 0;
			System.out.println("존재하지 않는 달 입니다.");
	}
		
	System.out.println(month + " 월은 " + day + " 일까지 있습니다.");
	scanner.close();
}
 
public static void main(String[] args) {
    /* Java 12부터 개선된 switch 문을 지원 */
    Scanner scanner = new Scanner(System.in);
	    
	System.out.print("월을 입력해 주세요 >>> ");
	int month = scanner.nextInt();
	int day;
	    
	switch (month) {
	    
	    case 1, 3, 5, 7, 8, 10, 12 -> day = 31;
	    case 4, 6, 9, 11 -> day = 30;
	    case 2 -> day = 28;
	    default -> {
	    	day = 0;
	    	System.out.println("존재하지 않는 달입니다.");
	        }
	}
	    
	System.out.println(month + "월은 " + day + "일까지 있습니다.");
	scanner.close();
}

 

public static void main(String[] args) {
		/* 사용자에게 성적을 입력받아
		 * switch문을 사용해서 학점을 출력하는 코드를 완성하세요.
		 * 입력은 0 ~ 100까지 입력이 됩니다.
		 * 기준은 아래와 같습니다.
		 * A : 90 ~ 100
		 * B : 80 ~ 89
		 * C : 70 ~ 79
		 * D : 60 ~ 69
		 * F : 0 ~ 59 */
		
		Scanner scanner = new Scanner(System.in);
		int grade;
		String credit;
		
		System.out.print("성적을 입력하세요 >> ");
	    grade = scanner.nextInt();
	    
	    // 'int/int' 결과는 int 이기 때문에 '88/10'은 8.8이 아닌 8이 됨.
	    switch(grade/10*10) {
	    case 90,100: // 90 ~ 100
	        credit = "A";
	        break;
	    case 80:
	    	credit = "B";
	    	break;
	    case 70:
	    	credit = "C";
	    	break;
	    case 60:
	    	credit = "D";
	    	break;
	    default :
	    	credit = "F";
	    	break;	    	    	
	    }
	    
	    System.out.println("입력하신 성적은 " + grade + "점이고, 학점은 " + credit + "입니다.");
	    scanner.close();
		

	}
 


2. 반복문

💡 어떤 작업이 반복적으로 수행되도록 할 때 사용

💡 종류 ; for문, while문, do-while문

💡 조건식의 결과가 true이면 참, false면 거짓으로 간주

 

1) for문

 

✓ 반복 횟수를 알고 있을 때 적합

 

  👾  실수 사용 x 정수만 사용하기 ▶️ 계산이 부정확하기 때문

  👾  초기화, 조건식, 증감식 모두 생략 가능

            ▶️  조건식이 생략된 경우, 참으로 간주되어 무한 반복문이 된다.

            ▶️  대신 블럭{} 안에 if 문을 넣어서 특정 조건을 만족하면 for 문을 빠져 나오게 해야 한다.

 

for문의 구조
for (초기화; 조건식; 증감식) {
    // 조건식이 참일 때 수행될 문장들을 적는다.
}

 

for문 수행 순서

 

  📍  초기화 ▶️ 조건식 ▶️ 수행될 문장 ▶️ 증감식 ▶️ 조건식 ▶️ 수행될 문장 ▶️ 증감식 ...

public class MyFor_02 {
	public static void main(String[] args) {
		/* for문의 순서 */
		int sum = 0; // 총 합을 담을 변수. 초기화가 꼭 필요.
		// for (초기값; 조건식; 증감식)
		for (int i = 1; i > 0; i++) { //1부터 10까지의 합
			System.out.println("i = " + i + " sum = " + (sum += i));
			
			// 1) 초기값 실행
			// 2) 조건식 확인
			// 3) 조건식이 참이면 명령문 실행
			
			// 4) 증감식 실행
			// 5) 조건식 확인
			// 6) 조건식이 참이면 명령문 실행
			// 4) 5) 6) 반복
		}	
			// System.out.println(i); // i는 for문에서만 유효
		{ 
			int tmp = 12;
		    System.out.println(tmp);
		}    	
	}
}
 

    변수 i에 1을 저장한 다음, 매 반복마다 i의 값을 1씩 증가시킨다.

    그러다가 i의 값이 5를 넘으면 조건식 'i <= 5'가 거짓이 되어 반복을 마치게 됨

    i의 값이 1부터 5까지 1씩 증가 하니까 모두 5번 반복한다.

A. 초기화

· 반복문에 사용될 변수를 초기화하는 부분이며 처음에 한번만 수행.

· 둘 이상의 변수가 필요할 때 콤마 ',' 를 구분자로 변수를 초기화 (단, 두 변수의 타입은 같아야)

     ex. for (int i=1, j=0; i <= 10; i++) {...

 

B. 조건식

· 조건식의 값이 참이면 반복을 계속하고, 거짓이면 반복을 중단하고 for문을 벗어난다.

 

C. 증감식

· 반복문을 제어하는 변수의 값을 증가 또는 감소시키는 식.

· 콤마 ',' 를 이용해서 두 문장 이상을 하나로 연결해서 쓸 수 있다.

    ex. for (int i =1, j=10; i <= 10; i++, j--) {...

public class MyFor_03 {

	public static void main(String[] args) {
		/* for문 외부에 변수 선언 할 경우엔 i대신 다른 변수명 사용 */
		int sum = 0;
		int num;
		
		for(num = 0; sum < 100 ; num++) {
			sum += num; // sum = sum + num -> sum을 초기화 하지 않으면 오류가 남.
			System.out.println("num : " + num + " / sum : " + sum);
		}
		
		System.out.println("num : " + num);
		System.out.println("sum : " + sum);

	}
}

 

응용 예제 
public class Ex_02_04 {
	public static void main(String[] args) {
		/* 1부터 100사이의 정수 중에서 3또는 4의 배수의 합을 구하는 코드를 작성 */
		
		int sum = 0;
		for (int i = 1; i <= 100; i++) {
	        if ((i%3==0) || (i%4==0)) {
			sum += i;
	        }
		}
		System.out.println("3 또는 4의 배수의 합 : " + sum );
	}
}

 


 

2)  중첩 for문

 

💡 중첩의 횟수 제한 x.

💡 안쪽 for문의 모든 반복이 끝나고서야 바깥쪽 for문의 다음 반복으로 넘어간다.

 

별 출력
public class Ex_03_03 {
	public static void main(String[] args) {
		/* for문을 이용해서 다음과 같이 *를 출력하는 코드를 작성해보세요. 
		 * 
		 **
		 ***
		 ****
		 */
		
		for (int i=1; i<=4; i++) {
			
			for (int j=1; j<=i; j++) {
				System.out.print("*");
				
			}
			System.out.println();
		}
	}
}

 

구구단 출력
public class MyFor_11 {
	public static void main(String[] args) {
		/* 중첩 for문으로 구구단 출력
		 * for문은 또 다른 for문을 내포할 수 있는데, 이것을 중첩 for문이라고 함.
		 * 이 경우 바깥쪽 for문이 한 번 실핼할 때마다 중첩된 for문은 지정된 횟수만큼
		 * 반복해서 돌다가 다시 바깥쪽 for문이 돌아감.  */
		
		for(int dan = 2; dan <= 9; dan++) { // 바깥 쪽 for문. 8번 반복
			System.out.println("*** " + dan + "단 ***");
			
			for(int times = 1; times <= 9; times++) { // 중첩 for문. 9번 반복
			    System.out.println(dan + " X " + times + " = " + dan * times);
			}
			System.out.println(); // -> 각 단이 끝날 때 넣어줌.
		}
	}
}

 

주사위 게임
public class Ex_03_01 {
	public static void main(String[] args) {
		/* 2개의 주사위를 던지는 게임이 있다고 가정하자.
		 * 중첩 for문을 이용하여 2개의 주사위의 합이 6이 되는 경우를 출력하는 코드 작성.
		   (1,5) (2,4) (3,3) (4,2) (5,1) */
		
		for (int i = 1; i <= 6; i++) {
			
			for ( int j = 1; j <= 6; j++) {
				if (i+j == 6)
				System.out.println("(" + i + ", " + j + ")");
				// 변수 통상적으로 i 다음에 j 씀.
			}
		}
	}
}

 


 

3)  float 타입 카운터 변수

 

  ✓  for문을 작성할 때 주의할 점은 초기화 식에서 루프 카운터 변수를 선언할 때 부동 소수점을 쓰는 float 타입을 사용 x
         ➡️  0.1은 float 타입으로 정확하게 표현할 수 없기 때문에 x에 더해지는 값이 0.1보다 약간 커서, 루프는 9번 실행
         ➡️  float과 double은 계산이 부정확
  ✓  대안으로 정수로 변환 후 계산 결과 값을 실수로 변환 or 자바에서는 정확한 실수 계산을 위해 Decimal 클래스를 제공

public class MyFor_05 {
	public static void main(String[] args) {
		
		for (float x = 0.1f; x <= 1.0f; x += 0.1f) {
			System.out.println(x);
			/* 0.1
			 * 0.2
			 * 0.3
			 * 0.4
			 * 0.5
			 * 0.6
			 * 0.70000005
			 * 0.8000001
			 * 0.9000001 */
		}
	}
}

 


 

4)  for문 동작 시간 구하기


  📍  프로그램의 동작 시간을 구하는 방법은 프로그램 시작 위의 부분에서 시작시간을 구하고, 프로그램이 끝나는 부분에서 종료시간을 구한후 종료시간에서 시작시간을 빼면 프로그램이 동작한 시간을 구할 수 있음

public class MyFor_04 {
	public static void main(String[] args) {
		
	     long startTime = System.currentTimeMillis(); // 시작시간
	     for(int i = 0; i < 1000000000; i++) { // 10억번 반복
	    	 ; // 빈문장 실행
	     }
	     long endTime = System.currentTimeMillis(); // 종료시간
	     
	     System.out.println("시작시간 : " + startTime);
	     System.out.println("종료시간 : " + endTime);
	     System.out.println("소요시간 : " + (endTime - startTime));

	}
}
 

 

 

 

(출처 : 학원강의 및 java의 정석 3rd)

+ Recent posts