🚀 꼭 매개변수가 아니더라도 변수가 참조하는 객체의 타입을 확인하고자 할 때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);
}
}
🚀 객체는 부품과 같아서 프로그램을 구성하는 객체를 바꾸면 프로그램의 실행 성능이 다르게 나올 수 있다.
객체 사용 방법이 동일하다는 것은 동일한 메소드를 가지고 있다는 뜻
한국 타이어와 금호 타이어는 모두 타이어를 상속하고 있으므로 부모의 메소드를 동일하게 가지고 있다고 말할 수 있다.
타이어 메소드 호출 시 오버라이딩 된 메소드가 호출되는데, 오버라이딩 된 내용은 두 타이어가 다르기 때문에 실행 결과가 다르게 나옴
이것을 '다형성' 이라고 하는데 다형성을 구현하기 위해서는 자동 타입 변환과 메소드 재정의가 필요하다.
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();
}
}
☑️ 어떤 자식 객체가 제공하느냐에 따라 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입니다.
}
}
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; // 강제 타입 변환
⚒️ 부모 타입은 자식 타입으로 자동 변환되지 않는다. 대신캐스팅 연산자로 강제 타입 변환을 할 수 있다.
⚒️ 자식 객체가 부모 타입으로 자동 변환하면 부모 타입에 선언된 필드와 메소드만 사용 가능
➡️ 만약 자식 타입에 선언된 필드와 메소드를 꼭 사용해야 한다면 강제 타입 변환을 해서 다시 자식타입으로 변환해야 함
🚀 클래스를 선언할 때 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 생성자를 호출할 수 있다.
동일한 클래스로부터 여러 개의 인스턴스를 만드는 것 = 동일한 설계도로 여러 대의 자동차를 만드는 것
⚒️ 객체는 모든 인스턴스를 대표하는 포괄적인 의미를 갖고 있으며, 인스턴스는 어떤 클래스로부터 만들어진 것인지를 강조하는 구체적인 의미를 갖고 있다.
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
- 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));
}
}