클래스에서의 변수선언 : 전역변수

메소드에서의 변수선언 : 지역변수

 

 

 

클래스에서의 변수

 

변수의 종류

클래스에서의 변수는 아래와 같이 구분한다.

  • 1. 클래스 변수 : static 키워드를 가지고 필드에 선언하는 변수, 메모리의 static영역 사용
  • 2. 멤버 변수(인스턴스 변수) : static 키워드 없이 필드에 선언하는 변수, 메모리의 heap영역 사용
  • 3. 지역 변수 : 메소드, 생성자, 초기화 블록 내부에서 선언하는 변수

 

  • 더이상 참조하지 않는경우 가비지 콜렉터(GC)가 변수를 지워준다.

 

 

class KindsOfVariable
public class KindsOgVariable {

	/* 클래스 영역에 작성하는 변수를 필드라고 한다. */
	
	/* 필드 
	 * == 멤버변수 (클래스가 가지는 멤버라는 의미) 
	 * == 전역변수(클래스 전역에서 아용할 수 있는 변수라는 의미) 
	 * 
	 * */
	
	/* non-static field를 인스턴스 변수라고 한다. 
	 * (인스턴스 생성 시점에 사용가능한 변수라는 의미) */
	private int globalNum;
	
	
	/* static field 를 정적필드(클래스변수)라고 한다. 
	 * (정적 영역에 생성되는 변수라는 의미) 
	 * */
	private static int staticNum;
	
	
	
	public void testMethod(int num) {	// 메소드 영역의 시작
		
		/* 메소드 영역에서 작성하는 변수를 지역변수라고 한다.
		 * 메소드 괄호 안에 선언하는 변수를 매개변수라고 한다.
		 * 매개변수도 일종의 지역변수이다.
		 * 지역변수와 매개변수 모두 메소드 호출 시 stack을 할당받아 stack에 생성된다. 
		 * 호출이 종료되면 할당되었던 공간은 사라진다.
		 * */
		int localNum;
		
		
		
		
		/* 매개변수는 호출시 값이 넘어와서 변경되기 때문에 초기화가 필요없다.
		 * 그러나 지역변수는 선언외에 다시 사용하기 위해서는 반드시 초기화가 되어야 한다. */
		
		System.out.println(num);
		// System.out.println(localNum); // 컴파일 에러가 생긴다. 
		
		// he local variable localNum may not have been initialized
		// 초기화 되지않아서 오류
		// heap영역에 생성된 변수들은 알아서 초기값으로 들어가지만 
		// stack영역의 생성된 지역변수들은 반드시 선언과 동시에 초기화를 해주어야 한다.
		
		System.out.println(globalNum);
		System.out.println(staticNum);
		// 전역 변수(모든영역)
		// 전역 변수는 클래스 전역에서 사용가능하다.
		
		
	} //메소드 영역의 끝
	
	
	public void testMethod2() {
		
		//System.out.println(localNum); //testMethod 내의 지역변수
		System.out.println(globalNum);
		System.out.println(staticNum);
		
		// 지역변수는 해당지역 내에서만 사용가능하다. 지역을 벗어난다면 컴파일 오류
		// 번역 변수는 다른 메소드에서도 사용 가능하다. 
		
		
	}
	
	
	
} // 클래스 영역의 끝

class KindsOfVariable

 

 

 

 

초기화 순서

  • 인스턴스(non-static) 스태틱 키워드가 안붙어있음
  • 클래스변수(static) 스태틱 키워드가 붙음 

 

private int num = 10;
private static int num2 = 20;
클래스 변수의 경우 초기값 외의 정적 초기화, 인스턴스 초기화, 생성자를 생성하게 된다면 그 위에 값을 덮어쓰는 형태가 된다. 

 

 

Application
public class Application {

	public static void main(String[] args) {

		/* 초기화 블럭과 초기화 순서 */
		/* 초기화 블럭
		 * 복잡한 초기화를 수행할 수 있는 블럭을 제공하며, 
		 * 인스턴스 초기화 블럭과 정적초기화 블럭으로 구분된다.
		 * 
		 * 1. 인스턴스 초기화 블럭
		 *  : 인스턴스가 생성되는 시점에 생성자 호출 이전에 먼저 실행이 된다.
		 *    인스턴스를 호출하는 시점마다 호출이 된다.
		 *    인스턴스 변수를 초기화하며 정적 필드에는 실행 시점마다 값을 덮어쓴다.
		 *  
		 *  {
		 *  	초기화 내용 작성
		 *  }
		 * 
		 *  2. 정적 초기화 블럭
		 *    : 클래스가 로드 될 때마다 한번 동작한다.
		 *      정적 필드를 초기화하며, 인스턴스 변수는 초기화 하지 못한다.
		 *      
		 * static {
		 * 			초기화 내용 작성
		 * }
		 * 
		 * 
		 * 
		 *  */
		
		
		
		Product product = new Product();  // 없으므로 마우스오버하여 클래스 생성
		System.out.println(product.getInfomation());
		
//		정적 초기화 블록 동작함...
//		인스턴스 초기화 블록 동작함...
//		기본 생성자 호출함...
//		Product [name=사이언, price=900000, brand=헬지]
		
		
		Product product2 = new Product("대륙폰", 300000, "샤우미");
		System.out.println(product2.getInfomation());
		
//		인스턴스 초기화 블록 동작함...
//		매개변수 있는 생성자 호출됨...
//		Product [name=대륙폰, price=300000, brand=샤우미]
		
		

	}

}

 

 

class Product
public class Product {

	/* 필드를 초기화 하지않으면 jvm이 정한 기본 값으로 객체가 생성된다. */
//	private String name;
//	private int price;
//	private static String brand;
	
	
	/* 명시적인 초기화가 동작함, 기본값을 초기화가 덮어씀 */
	private String name = "갤럭시";
	private int price = 1000000;
	private static String brand = "삼송";
//	기본 생성자 호출함...
//	Product [name=갤럭시, price=1000000, brand=삼송]
	
	
	
	
	/* 인스턴스 초기화 블록 */
	{
		name = "사이언";
		price = 900000;  // 인스턴스 변수
		
		/* 인스턴스 초기화 블록에서는 static 필드를 초기화 할 수 있는 것처럼 보인다.
		 * 하지만 static 초기화 블록은 클래스가 로드 될 떄 이미 초기화를 진행했다. = 헬지
		 * 따라서 인스턴스 초기화 블럭이 동작하는 시점에는 이미 초기화가 진행 된 정적 필드에 = 샘송
		 * 인스턴스 초기화 블럭에서 대입한 값으로 덮어쓰게 되는 것이다. */
		
		brand ="사과";   //클래스 변수
		System.out.println("인스턴스 초기화 블록 동작함...");
		
	}
	
	
	/* static 초기화 블록 */
	static {
		/* static 초기화 블럭에서는 non-static 필드를 초기화 하지 못한다.
		* 정적 초기화 블럭은 클래스 로드시에 동작한다.
		* 따라서 정적 초기화 블럭의 동작 시점에는 인스턴스가 아무것도 존재할 수 없기 때문에,
		* 존재하지 않는 인스턴스 변수에 초기화 하는 것은 시기상으로 불가능하다.
		* 
		*/
		
	//	name = "아이뽕";
	//	price = 1000000; 
		// Cannot make a static reference to the non-static field name
		
		brand = "헬지";
		System.out.println("정적 초기화 블록 동작함...");
		// 왜 static  영역에서 name과 price를 초기화 할 수 없을까?
		// 인스턴스 변수는 객체가 만들어져서 heap영역에 메모리가 할당 됐을때 존재
		// 인스턴스가 생성된 적이 없으므로 초기화 자체가 불가능하다.
	}
	
	
	/* 실행 순서 확인 */
//	정적 초기화 블록 동작함...
//	인스턴스 초기화 블록 동작함...
//	기본 생성자 호출함...
//	Product [name=사이언, price=900000, brand=사과]
	
	
	
	
	
	public Product() {
		System.out.println("기본 생성자 호출함...");
	}
	
	
	
	public Product(String name, int price, String brand) {
		
		this.name = name;
		this.price = price;
		Product.brand = brand;
		System.out.println("매개변수 있는 생성자 호출됨...");
		
//		인스턴스 초기화 블록 동작함...
//		매개변수 있는 생성자 호출됨...
//		Product [name=대륙폰, price=300000, brand=샤우미]
	}
	
	
	
	
	
	public String getInfomation() {
		return "Product [name=" + this.name + ", price=" + this.price + ", brand=" + Product.brand + "]";
	}
	
}

 

 

 

 

 

 

 

 

 

객체배열

 

 

 

 

 

 

객체배열이란?

  • 레퍼런스 변수(주소값이 담김)에 대한 배열
  • 동일한 타입의 여러 인스턴스들을 배열로 관리할 수 있다.

 

 

 

 

 

1. 선언
클래스명[ ] 배열명;
클래스명 배열명[ ];

 

2. 할당
배열명 = new 클래스명[배열크기];

(new 연산자를 써야지만 힙 영역에 할당)

 

 

3. 선언과 동시에 할당
클래스명 배열명[ ] = new 클래스명[배열크기]

 

  • 힙 영역에 객체를 참조할 변수만 생성이 된 상태이다. 
  • 즉, 해당객체가 만들어진게 아니라 그 객체를 모아서 참조할 수 있는 참조변수가 만들어진 상태

 

 

 

 

 

객체배열 선언과 할당

 

인덱스를 이용한 초기화
배열명[ i ] = new 클래스명( );

 

 

선언과 동시에 할당 및 초기화
클래스명 배열명[ ] = {new 클래스명(), new 클래스명()};

 

 

 

 

 

객체배열 저장구조
Example arr[ ] = new Example[2];
  arr[0] = new Example( );      //0x678 주소값 참조
  arr[1] = new Example( );      //0x098 주소값 참조

 

* arr[index]이 하나의 참조형 변수라고 생각

 

 

class Application
public class Application {

	public static void main(String[] args) {

		/* 객체배열은 레퍼런스 변수에 대한 배열이다.
		 * 생성한 인스턴스도 배열을 이용해서 관리하면
		 * 동일한 타입의 여러개 인스턴스를 각각 취급하지 않고 연속 처리할 수 있어서 유용하다.
		 * 또한 반환값은 1개의 값만 반환할 수 있기 때문에
		 * 동일한 타입의 여러 인스턴스를 반환해야 하는 경우 객체배열을 이용할 수 있다. */
		
		
		/* 자동차 5대 인스턴스를 생성 후 모든 인스턴스가 최고 속도로 달리게 한다. */
		
		Car car1 = new Car("페라리", 300);
		Car car2 = new Car("람보르기니", 350);
		Car car3 = new Car("롤스로이스", 250);
		Car car4 = new Car("부가티베이론", 400);
		Car car5 = new Car("포터", 500);
		
		
		car1.driveMaxSpeed();
		car2.driveMaxSpeed();
		car3.driveMaxSpeed();
		car4.driveMaxSpeed();
		car5.driveMaxSpeed();
		
		
		
		/* 동일한 타입의 인스턴스를 여러 개 사용해야 할 때 객체배열을 이용하면
		 * 보다 효율적으로 사용이 가능하다.
		 * Car 타입의 인스턴스 주소를 보관할 5칸 짜리 배열 할당 */
		Car[] carArray = new Car[5];
		
		System.out.println(carArray);
		System.out.println(carArray[0]);
		// carArray[0]객체의 주소 : [Lcom.greedy.section01.init.Car;@3830f1c0
		// 인덱스 0의 값 : null
		
		
		
		/* 각 인덱스에는 기본값 null로 초기화 되어 있기 때문에 
		 * 인덱스별로 인스턴스를 생성해야 한다. */
		
		carArray[0] = new Car("페라리", 300);
		carArray[1] = new Car("람보르기니", 350);
		carArray[2] = new Car("롤스로이스", 250);
		carArray[3] = new Car("부가티베이론", 400);
		carArray[4] = new Car("포터", 450);
		
		
		
		/* 배열이기 때문에 반복문을 활용할 수 있다. */
		for( int i = 0; i <carArray.length; i++ ) {
			carArray[i].driveMaxSpeed();
		}
		/*
		페라리(이)가 최고시속 300km/h로 달려갑니다.
		람보르기니(이)가 최고시속 350km/h로 달려갑니다.
		롤스로이스(이)가 최고시속 250km/h로 달려갑니다.
		부가티베이론(이)가 최고시속 400km/h로 달려갑니다.
		포터(이)가 최고시속 450km/h로 달려갑니다. */
	}
	
	
	
	
	
	/* 객체 배열도 할당과 동시에 초기화 할 수 있다. */
	Car[] carArray2 = {
		new Car("페라리", 300)	
		, new Car("람보르기니", 350)
		, new Car("롤스로이스", 250)
		, new Car("부가티베이론", 400)
		, new Car("포터", 500)
		
	}; 
	
	{
	
	
	
	
	/* 향상된 for문으로도 사용이 가능하다. 
	 * for ( 타입과 변수명 : 배열 ) */
	
	for(Car c:carArray2) {
		c.driveMaxSpeed();
		
	}
	
	
}


}

 

 

class Car
public class Car {

	private String modelName;
	private int maxSpeed;
	
	
	/* 매개변수 생성자 정의 */
	public Car (String modelName, int maxSpeed) {
		this.modelName = modelName;
		this.maxSpeed = maxSpeed;
	}
	
	/* 기능 */
	public void driveMaxSpeed() {
		System.out.println(modelName +"(이)가 최고시속 " + maxSpeed + "km/h로 달려갑니다.");
	}
	
	
	
}

 

 

 

 

 

 

 

 

 

 

 

 

추가 예제 

 

 

Application
import java.util.Scanner;

public class Application {

	public static void main(String[] args) {

		/* 동일한 타입의 여러개의 인스턴스를 인자로 전달하거나 
		 * 리턴 받는 경우에도 객체 배열을 이용할 수 있다. */
		
		/* DTO를 이용한 간단한 회원관리용 프로그램 */
		/* 
		 * 구현기능
		 * 1. 여러명의 회원 정보를 받아 한번에 여러 회원 정보를 등록
		 * 2. 전체 회원 조회 시 여러명의 회원정보를 반환
		 * 
		 *  */
		
		Scanner sc = new Scanner(System.in);
		
		MemberManager memberManager = new MemberManager();
		// 없으므로 생성
		
		
		menu : 
		while(true) {
			
			
			System.out.println("==========회원관리 프로그램==========");
			System.out.println("1. 회원등록");
			System.out.println("2. 회원 전체 조회");
			System.out.println("9. 프로그램 종료");
			System.out.print("메뉴 선택 : ");
			int no = sc.nextInt();
			
			
			switch(no) {
			case 1 : memberManager.signUpMembers(); break;
			case 2 : memberManager.printAllMembers(); break;
			case 9 : System.out.println("프로그램을 종료합니다."); break menu;
			default : System.out.println("잘못 된 번호를 입력하셨습니다."); break;
			
			}
			
			
			
			
		}

	}

}



//==========회원관리 프로그램==========
//1. 회원등록
//2. 회원 전체 조회
//9. 프로그램 종료
//메뉴 선택 : 1
//회원을 등록합니다.
//김영희님은 회원 등록에 성공했습니다.
//홍길동님은 회원 등록에 성공했습니다.
//박진희님은 회원 등록에 성공했습니다.
//이순신님은 회원 등록에 성공했습니다.
//한지희님은 회원 등록에 성공했습니다.
//
//김영희님은 회원 등록에 성공했습니다.
//홍길동님은 회원 등록에 성공했습니다.
//박진희님은 회원 등록에 성공했습니다.
//이순신님은 회원 등록에 성공했습니다.
//한지희님은 회원 등록에 성공했습니다.
//총 5명의 회원 등록에 성공했습니다.
//==========회원관리 프로그램==========
//1. 회원등록
//2. 회원 전체 조회
//9. 프로그램 종료
//메뉴 선택 : 2
//==========가입된 회원 목록==========
//MeberDTO [num=1, id =user01, pwd =pass01, name =김영희, age =20, gender =여]
//MeberDTO [num=2, id =user02, pwd =pass02, name =홍길동, age =22, gender =남]
//MeberDTO [num=3, id =user03, pwd =pass03, name =박진희, age =24, gender =여]
//MeberDTO [num=4, id =user04, pwd =pass04, name =이순신, age =26, gender =남]
//MeberDTO [num=5, id =user05, pwd =pass05, name =한지희, age =28, gender =여]
//MeberDTO [num=1, id =user01, pwd =pass01, name =김영희, age =20, gender =여]
//MeberDTO [num=2, id =user02, pwd =pass02, name =홍길동, age =22, gender =남]
//MeberDTO [num=3, id =user03, pwd =pass03, name =박진희, age =24, gender =여]
//MeberDTO [num=4, id =user04, pwd =pass04, name =이순신, age =26, gender =남]
//MeberDTO [num=5, id =user05, pwd =pass05, name =한지희, age =28, gender =여]
//====================
//총 5명의 회원이 가입되어 있습니다.
//==========회원관리 프로그램==========
//1. 회원등록
//2. 회원 전체 조회
//9. 프로그램 종료
//메뉴 선택 : 4
//잘못 된 번호를 입력하셨습니다.
//==========회원관리 프로그램==========
//1. 회원등록
//2. 회원 전체 조회
//9. 프로그램 종료
//메뉴 선택 : 9
//프로그램을 종료합니다.

 

 

class MemberDTO
public class MemberDTO {

	/* 관리할 회원정보를 추상화해서 필드 작성 */
	private int num;
	private String id;
	private String pwd;
	private String name;
	private int age;
	private char gender;
	
	
	
	/* 아무것도 체크하지않으면 기본생성자 */
	public MemberDTO() {
		super();
	}


	/* 마우스 우클릭 - source - Generate Constructor using Fields */
	/* 모든 필드를 초기화하는 생성자 */
	public MemberDTO(int num, String id, String pwd, String name, int age, char gender) {
		super();
		this.num = num;
		this.id = id;
		this.pwd = pwd;
		this.name = name;
		this.age = age;
		this.gender = gender;
	}


	
	
	/* 마우스 우클릭 - source - Generate Getter and Setter */
	/* 게터세터 생성 */
	
	public int getNum() {
		return num;
	}


	public void setNum(int num) {
		this.num = num;
	}


	public String getId() {
		return id;
	}


	public void setId(String id) {
		this.id = id;
	}


	public String getPwd() {
		return pwd;
	}


	public void setPwd(String pwd) {
		this.pwd = pwd;
	}


	public String getName() {
		return name;
	}


	public void setName(String name) {
		this.name = name;
	}


	public int getAge() {
		return age;
	}


	public void setAge(int age) {
		this.age = age;
	}


	public char getGender() {
		return gender;
	}


	public void setGender(char gender) {
		this.gender = gender;
	}



	
	/* 모든 필드값을 문자열로 반환 */
	public String getInformation() {
		
		return  "MeberDTO [num=" + num + ", id =" + id + ", pwd =" + pwd + ", name =" + name +
				", age =" + age + ", gender =" + gender + "]";
		
	}
	
}

 

 

class MemberInsertManager
public class MemberInsertManager {

	
	/** <pre> 
	 * 여러명의 회원 정보를 한 번에 등록할 수 있는 기능 제공
	 * </pre>
	 * @param members 회원 정보를 객체배열 형태로 전달
	 * */
	
	public void insert(MemberDTO[] members) {
		System.out.println("회원을 등록합니다.");
		
		
		/* 일반 for문 */
		for (int i = 0; i < members.length; i++) {
			System.out.println(members[i].getName() + "님은 회원 등록에 성공했습니다.");
		}
		
		
		System.out.println();
		
		
		
		/* 향상된 for문 */
		/* 타입과 변수:멤버의 이름 */
		for (MemberDTO member:members) {
			System.out.println(member.getName() + "님은 회원 등록에 성공했습니다.");
		}
		
		
		System.out.println("총 " + members.length + "명의 회원 등록에 성공했습니다.");
		
	}

	
	
}

 

 

class MemberManager
public class MemberManager {

	/** <pre>
	 * 여러 명의 회원 정보를 등록
	 *  </pre>
	 *  */
	
	
	public void signUpMembers() {
		
		/* 5명의 회원 정보를 담을 객체배열 생성 */
		MemberDTO[] members = new MemberDTO[5];
		
		
		/* 5명의 회원정보를 각 인덱스에 할당 */
		members[0] = new MemberDTO(1, "user01", "pass01", "김영희", 20, '여');
		members[1] = new MemberDTO(2, "user02", "pass02", "홍길동", 22, '남');
		members[2] = new MemberDTO(3, "user03", "pass03", "박진희", 24, '여');
		members[3] = new MemberDTO(4, "user04", "pass04", "이순신", 26, '남');
		members[4] = new MemberDTO(5, "user05", "pass05", "한지희", 28, '여');
		
		
		/* 회원 정보를 입/출력할 용도의 MemberInsertManager 작성 */
		MemberInsertManager memberInsertManager = new MemberInsertManager();
		// 없으므로 생성 
		memberInsertManager.insert(members); 
		//memberDTO 5개의 참조변수에 대한 주소값을 인자로 전달
		
		
	}

	
	
	
	/** <pre>
	 * 모든 회원 목록을 조회하여 정보를 출력
	 *  </pre>
	 *  */
	
	public void printAllMembers() {
		
		/* MemberSelectManager 클래스 작성 */
		/* 작성한 메소드를 호출하고 반환받은 값을 객체배열 레퍼런스 변수에 저장한다. */
		
		
		MemberDTO[] selectedMembers = new MemberSelectManager().selectAllMembers();
		
		
		
		/* 가입되어 있는 회원 목록을 출력한다. */
		System.out.println("==========가입된 회원 목록==========");
		for (int i = 0; i < selectedMembers.length; i++) {
			System.out.println(selectedMembers[i].getInformation());
		}

		
		for (MemberDTO member : selectedMembers) {
			System.out.println(member.getInformation());
			
		}
		
		System.out.println("====================");
		System.out.println("총 " + selectedMembers.length + "명의 회원이 가입되어 있습니다.");
		
	}

	
	
	/* 클래스를 여러개 작성하는 이유: 클래스는 하나의 기능, 책임만을 가지고 있어야 함 */
	/* 인자로 전달하는 테스트, 리턴받은 테스트를 하기 위함이었다. */
	
	
}

 

 

 

class MemberSelectManager
public class MemberSelectManager {

	/** <pre>
	 * 회원 정보 전체를 반환하는 메소드
	 *  </pre>
	 *  @return 전체 회원 정보 객체 배열로 반환
 	 *  
	 *  */
	
	public MemberDTO[] selectAllMembers() {
		
		/* MemberDTO배열을 리턴하는 메소드 */
		return new MemberDTO[] {
		new MemberDTO(1, "user01", "pass01", "김영희", 20, '여')
		, new MemberDTO(2, "user02", "pass02", "홍길동", 22, '남')
		, new MemberDTO(3, "user03", "pass03", "박진희", 24, '여')
		, new MemberDTO(4, "user04", "pass04", "이순신", 26, '남')
		, new MemberDTO(5, "user05", "pass05", "한지희", 28, '여')
		
		
		};	
	}	
}

 

 

 

 

 

 

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

다형성  (0) 2022.01.05
상속  (0) 2022.01.04
클래스와 객체(3)  (0) 2021.12.30
클래스와 객체(2)  (0) 2021.12.29
배열, 클래스와 객체  (0) 2021.12.28

 

생성자를 이용한 초기화와 설정자를 이용한 초기화 비교
public class Application {

	public static void main(String[] args) {

		/* 생성자를 이용한 초기화(constructor)와 설정자를 이용한 초기화 비교 */
		/*  생성자를 이용한 초기화와 설정자(setter)를 이용한 초기화는 각각의 장단점이 존재한다.
		 * 
		 *  
		 *  1. 생성자를 이용한 초기화
		 *  장점  : setter메소드를 여러 번 호출해서 사용하지 않고 단 한번의 호출로
		 *  인스턴스를 생성 및 초기화 할 수 있다. 
		 *  단점 : 필드를 초기화 할 매개변수의 갯수를 경우의 수 별로 모두 만들어두어야 한다. 
		 *  	  호출시 인자가 많아지는 경우 어떤 값이 어떤 필드를 의미하는지 한 눈으로 
		 *  	  보기 힘들다.
		 *  	
		 *  
		 *  2. 설정자를 이용한 초기화
		 *  장점 : 필드를 초기화 하는 각각의 값들이 어떤 필드를 초기화 하는지 명확하게 볼 수 있다.
		 *  단점 :  하나의 인스턴스를 생성할때 한번의 호출로 끝나지 않는다. 
		 *  
		 *  
		 *  */
		
		
		
		/* 생성자를 이용한 초기화 */
		UserDTO user1 = new UserDTO("greedy", "greedy", "greedy", new java.util.Date());
		System.out.println(user1.getInformation());
// 콘솔		
// User DTO [id=greedy, name=greedy, pwd=greedy, enrollDate=Thu Dec 30 09:37:57 KST 2021]		
		
		
		
		
		/* 기본 생성자와 설정자를 이용한 초기화 */
		UserDTO user2 = new UserDTO();
		user2.setId("greedy");
		user2.setPwd("greedy");
		user2.setName("greedy");
		user2.setEnrollDate(new java.util.Date());
		System.out.println(user2.getInformation());
// 콘솔			
//User DTO [id=greedy, name=greedy, pwd=greedy, enrollDate=Thu Dec 30 09:37:57 KST 2021]	
		
		
		
		
		
		
		

	}

}

 

 

 

public class UserDTO {

		/* 일반적으로 DTO(Data Transfer Object) 목적으로 
		 * 설계된 클래스는 명사 뒤에 DTO를 붙인다. */
		/* UserDTO, MemberDTO, BoardDTO 등...
		 * 참고) VO(Value Object) 라는 용어와 혼용해서 사용하기도 함
		 * 값을 담고있는 객체라고 받아 들여라 
		 * 
		 *  */
	
	
	
		/* 모든 필드를 private 접근제한으로 선언 */
		private String id;
		private String pwd;
		private String name;
		private java.util.Date enrollDate;
	
	
		
		
		/* 필드 아래엔 생성자 작성 
		 * 기본생성자 명시적으로 작성
		 * 매개변수 있는 생성자를 선택적으로 추가할 수 있도록 기본생성자를 
		 * 명시한다.
		 * 명시하지 않고 추후 매개 변수 생성자를 추가할 시 
		 * 에러발생가능성이 있기 때문*/
		public UserDTO() {}
		
		
		
		
		/* 매개 변수 있는 생성자는 선택 사항이다.
		 * 필요에 따라 만들지만 일반적으로 가장 많이 가용 되는 생성자는 
		 * 모든 필드를 초기화 하는 생성자이다.
		 * 
		 * */
		public UserDTO(String id, String pwd, String name, java.util.Date enrollDate) {
			
			this.id = id;
			this.pwd = pwd;
			this.name = name;
			this.enrollDate = enrollDate;
			
		}
		
		
		
		
		
		
		/* 설정자(Setter)와 접근자(Getter) */
		
		/* 설정자(setter) */
		
		public void setId(String id) {
			this.id = id;
		}
		
		public void setPwd(String pwd) {
			this.pwd = pwd;
		}
		
		public void setName(String name) {
			this.name = name;
		}
		
		public void setEnrollDate(java.util.Date enrollDate) {
			this.enrollDate = enrollDate;
		}
		
		
		
		
		
		
		
		
		/* 접근자 (getter) */
		
		public String getId() {
			return id;
		}
		
		public String getPwd() {
			return pwd;
		}
		
		public String getName() {
			return name;
		}
		
		public java.util.Date getEnrollDate() {
			return enrollDate;
		}
		
		
		
		
		/* 접근자로 하나씩 필드 값을 확인해보기 번거롭기 때문에
		 * 모든 필드의 값을 하나의 문자열로 반환하는 메소드를 
		 * 필드값 확인 용으로 많이 사용한다. */
		
		public String getInformation() {
			return "User DTO [id=" + this.id +", name="+ 
            this.name +", pwd="+ this.pwd +", enrollDate="+ this.enrollDate + "]";
					
		}
		
		
		
		
}

 

 

 

 

 

 

 

오버로딩

 

오버로딩(Overloading)이란?
  • 동일한 메소드명으로 다양한 종류의 매개변수에 따라 다르게 처리해야하는 것을 관리하기
    위해 사용하는 기술
  • 동일한 메소드명의 매개변수의 타입, 개수, 순서를 다르게 작성
  • 즉 메소드의 시그니처(Signature)가 다르지만 메소드 명은 같게 함

 

 

 

오버로딩 테스트
public class OverloadingTest {

	/* 생성자 작성시 매개변수 부분의 타입, 갯수, 순서를 다르게 작성하면 
	 * 서로 다른 생성자로 인식해서 동일한 이름이지만 여러 개 작성할 수 있었다. 
	 * => 오버로딩(overloading)
	 * 
	 * 오버로딩의 사용이유
	 * 동일한 기능의 메소드를 매개변수에 따라 다르게 이름을 정의하면 
	 * 복잡하고 관리하기가 어려워진다. 따라서 동일한 이름으로 다양한 종류의 
	 * 매개변수에 따라 처리해야 하는 여러 메소드를 동일한 이름으로 관리하기 위해서 사용한다. 
	 *  
	 *  
	 * 오버로딩의 조건
	 * 동일한 이름을 가진 메소드의 파라미터 선언부에 매개변수의 타입, 갯수, 
     순서를 다르게 작성하며
	 * 한 클래스 내에 동일한 이름의 메소드를 여러개 작성할 수 있도록 한다.
	 * 메소드의 시그니처가 다르면 다른 메소드로 인식하기 때문이다.
	 * 즉, 시그니처 중 메소드 이름은 동일해야 하기 때문에 파라미터 선언부가 
     다르게 작성 되어야 오버로딩이 성립된다.
	 *  
	 *  
	 * 메소드의 시그니처?
	 *  public void     method(int num) {} 
	 * (오버로딩과 무관)     (시그니처)
	 * 메소드의 메소드 명과 파라미터 선언부 부분을 시그니처 라고 부른다.
	 * method (int num) 이 부분이 시그니처이다.
	 * 즉, 접근제한자나 반환형은 오버로딩 성립 요건에 해당하지 않는다. 
	 *  
	 *  
	 *  */
	
	
	
	/* 오버로딩을 이용한 메소드 작성 테스트를 위한 기준이 되는 메소드 */
	public void test() {}

	
	
	
	/* 메소드 시그니처가 동일한 경우 컴파일 에러를 발생시킨다. */
	// public void test() {}
	
	
	
	
	/* 접근 제한자에 따른 오버로딩 성립 확인
	 * -> 접근 제한자는 메소드 시그니처에 해당하지 않는다. */
	//private void test() {}


	/* 반환형에 따른 오버로딩 성립 확인
	 * -> 바환형은 메소드 시그니처에 해당하지 않는다. */
	// publc int test() {return 0;}
	
	
	
	
	/* 매개변수 유무에 따른 오버로딩 성립 확인
	 * -> 파라미터 선언부는 메소드 시그니처에 해당한다. */
	public void test(int num) {}
	
	
	
	/* 매개 변수의 이름은 메소드 시그니처에 영향을 주지 않는다. */
	// public void test(int num2) {}
	
	
	
	/* 매개변수 갯수에 따른 오버로딩 성립 확인 */
	public void test(int num, int num2) {}
	
	
	/* 매개변수 타입 변화에 따른 오버로딩 성립 확인 */
	public void test (int num, String name) {}
	
	
	/* 매개변수 순서에 따른 오버로딩 성립 확인 */
	public void test (String name, int num) {}
	
	
}

 

 

 

 

파라미터

메소드의 파라미터 선언부에는 다양한 종류의 값을 인자로 전달하여 호출 가능

* 가변인자 : 인자가 넘어가는 갯수가 가변적이 되도록 설정할 수도 있다. 

 

 

 

 

 

class Application
public class Application {

	public static void main(String[] args) {
		
		/* 메소드의 파라미터 선언부에는 다양한 종류의 값을 인자로 전달하여 호출할 수 있다.
		 * 
		 *  매개변수(parameter) 로 사용 가능한 자료형
		 *  1. 기본자료형
		 *  2. 기본자료형 배열
		 *  3. 클래스자료형
		 *  4. 클래스자료형 배열
		 *  5. 가변인자
		 *  
		 *   */
		
		ParameterTest pt = new ParameterTest();
		// 컴파일 오류시 클래스 생성 
		
		/* 1. 기본자료형을 매개변수로 전달 받는 메소드 호출 확인 */
		/* 기본자료형 8가지 모두 가능하다. */
		int num = 20;
		pt.testPrimaryTypeParameter(num);
		
		System.out.println("메소드 호출 후 num :" + num);
		
		// 콘솔 // 매개변수로 전달받은 값 : 20
		
//		인자로 전달하는 값 : [I@3830f1c0
//		매개변수로 전달받은 값 : [I@3830f1c0
		                              
		                              
		                              
		
		
		/* 2. 기본자료형 배열을 매개변수로 전달 받는 메소드 호출 확인 */
		int[] iarr = new int[] {1,2,3,4,5};
		System.out.println("인자로 전달하는 값 : " +  iarr);
		pt.testPrimaryTypeArrayParameter(iarr);	// 메소드로 생성
		
		
		/* 메소드 호출 후 값 변경 확인 */
		System.out.print("배열의 값 출력 :");
		for (int i = 0; i < iarr.length; i++) {
			System.out.print(iarr[i] + " ");	
		} 
			System.out.println();
		
// 콘솔		
//		배열의 값 출력 :1 2 3 4 5 
//		배열의 값 출력 :99 2 3 4 5 
//		배열의 값 출력 :99 2 3 4 5 
		
		
		/* 3. 클래스 자료형 */
		/* 사각형의 가로, 세로 길이를 저장할 RectAngle 이라는 클래스를 하나 추가해 보자 */
		
		RectAngle r1 = new RectAngle(12.5, 22.5);		
		// 마우스 오버해서 클래스 생성 
		System.out.println("인자로 전달하는 값 :" + r1);
		pt.testClassTypeParameter(r1);	//메소드 생성
// 인자로 전달하는 값 :com.greedy.section05.parameter.RectAngle@71dac704		
		
		/* 메소드 호출 후 값 변경 확인 */
		System.out.println("메소드 호출 후 사각형의 넓이와 둘레 ==========");
		r1.clacArea();
		r1.clacRound();
		
//		메소드 호출 후 사각형의 넓이와 둘레 ==========
//		이 사각형의 넓이는 10000.0입니다.
//		이 사각형의 둘레는 400.0입니다.
		
		
			// 매개변수에서 클래스를 자료형으로 사용하는 것은 값 변경을 하는 것이다. 
		
		
		
		
		
		
		/* 4. 클래스 자료형 배열은 뒤에서 학습 */
		
		
		/* 5. 가변인자 */
		/* 인자로 전달하는 값의 갯수가 정해지지 ㅇ낳은 경우 가변배열을 활용할 수 있다.  */
		
		//pt.testVariableLengthArrayParameter();
		// 인자가 아무것도 없는 경우 name이 전달되지않아 에러
		
		
		pt.testVariableLengthArrayParameter("홍길동");
		// name에 해당하는 것은 전달해야하지만 ...hobby인 가변인자는 하나도 전달되지않아도 괜찮다. 
		
//		이름 : 홍길동
//		취미의 갯수 : 0
//		취미 : 
		
		
		pt.testVariableLengthArrayParameter("유관순", "축구", "농구", "배구");
		
//		이름 : 유관순
//		취미의 갯수 : 3
//		취미 : 축구 농구 배구
		
		pt.testVariableLengthArrayParameter("신사임당", new String[] {"테니스","서예"}); 
		// 배열도 전달 가능
		
//		이름 : 신사임당
//		취미의 갯수 : 2
//		취미 : 테니스 서예 
		
		
		/* 가변배열을 매개변수로 이용한 메소드는 모호성으로 인해 오버로딩 하지 않는 것이 좋다.  */
		
		
	}
}

 

 

class ParameterTest
public class ParameterTest {

	
	public void testPrimaryTypeParameter(int iarr) {
		System.out.println("매개변수로 전달받은 값 : " + iarr);
	}

	
	
	
	public void testPrimaryTypeArrayParameter(int[] iarr) {
		
		
		/* 배열의 주소가 전달된다.  
		 * 즉 인자로 전달하는 배열과 매개변수로 전달받은 
		 * 배열은 서로 동일한 배열을 가리킨다.(얕은 복사)
		 * 
		 * */
		System.out.println("매개변수로 전달받은 값 : " + iarr);
		
		
		
		
		/* 배열의 값 출력 */
		System.out.print("배열의 값 출력 :");
		for (int i = 0; i < iarr.length; i++) {
			
			System.out.print(iarr[i] + " ");
		} 
		System.out.println();
	
		
		
		
		/* 배열의 0번 인덱스 값 변경 */
		iarr[0] = 99;
 		
		
		
		
	
		/*값 변경 후 배열의 값 출력*/
		System.out.print("배열의 값 출력 :");
		for (int i = 0; i < iarr.length; i++) {
		
		System.out.print(iarr[i] + " ");
		} 
		System.out.println();
		
		
	}



	
	
	

	public void testClassTypeParameter(RectAngle rectAngle) {
		
		/* 인스턴스도 주소가 전달된다.
		 * 즉, 인자로 전달하는 인스턴스와 매개변수로 전달받은 인스턴스는 서로 
		 * 동일한 인스턴스를 가리킨다. (얕은 복사) */
		System.out.println("매개변수로 전달 받은 값 : " + rectAngle);

//인자로 전달하는 값 :com.greedy.section05.parameter.RectAngle@71dac704
//매개변수로 전달 받은 값 : com.greedy.section05.parameter.RectAngle@71dac704
		
		System.out.println("변경 전 사각형의 넓이와 둘레 ==========");
		rectAngle.clacArea();
		rectAngle.clacRound();
		
		
		/* 사각형의 너비와 높이를 변경 */
		rectAngle.setWidth(100);
		rectAngle.setHeight(100);
		
		System.out.println("변경 후 사각형의 넓이와 둘레 ==========");
		rectAngle.clacArea();
		rectAngle.clacRound();
		
//		변경 전 사각형의 넓이와 둘레 ==========
//		이 사각형의 넓이는 281.25입니다.
//		이 사각형의 둘레는 70.0입니다.
//		변경 후 사각형의 넓이와 둘레 ==========
//		이 사각형의 넓이는 10000.0입니다.
//		이 사각형의 둘레는 400.0입니다.
		
		
	}
	
	
	
	
	
	public void testVariableLengthArrayParameter(String name, String... hobby) {
		// 값의 갯수가 여러개일 수 있는데 그것을 hobby 로 받겠다는 의미 
		// 이때 hobby와 name의 순서가 바뀐다면 컴파일 에러가 뜬다.
		// ("name", "hobby1", "hobby2"); 가변인자를 선언할땐 반드시 마지막에 선언해야한다.
		
		
		/* 가변 길이의 배열은 몇 개가 매개변수로 전달될지 모르는 상황이기에 
		 * 이름과구분하기 위해 뒤쪽에 작성해야 한다.
		 * 앞쪽에 작성하는 경우 에러가 발생한다.  */
		
		System.out.println("이름 : " + name);
		System.out.println("취미의 갯수 : " + hobby.length);
		//length 전달시 취미를 몇개 전달했는지 알 수 있음
		System.out.print("취미 : ");
		for (int i= 0; i < hobby.length; i++) {
		System.out.print(hobby[i] + " ");
		}
		
		System.out.println();
		
		
		
	}
	
	
	
	
	//오버로딩 // name만 뺐다.
//	public void testVariableLengthArrayParameter(String... hobby) {
//	
//		System.out.println("취미의 갯수 : " + hobby.length);
//		//length 전달시 취미를 몇개 전달했는지 알 수 있음
//		System.out.print("취미 : ");
//		for (int i= 0; i < hobby.length; i++) {
//		System.out.print(hobby[i] + " ");
//		}
//		
//		System.out.println();
//		
//	}
	
	// 이렇게 작성한 상태에서 어플리케이션에 가보면 컴파일 오류가 나 있다.
	// 전부 스트링 타입이므로, 호출시 굉장한 모호성이 발생할 수 있다. 
	
	
	
	
	
	
}

 

 

 

RectAngle
public class RectAngle {

	private double width;
	private double height;
	
	
	
	/* 기본 생성자로 객체 생성을 막고, 모든 필드를 초기화하는 생성자를 추가하여
	 * 초기값을 입력해서 인스턴스를 생성하도록 제한 */
	// 기본생성자 막음
	public RectAngle(double width, double height) {
		this.width = width;
		this.height = height;
		
	}
	
	/* 생성자와 접근자 */
	public void setWidth (double width) {
		this.width = width;
	}
	
	public void setHeight (double height) {
		this.height = height;
	}
	
	
	public  double getWidth () {
		return width;
	}
	
	public  double getHeight () {
		return height;
	}
	
	
	
	/* 사각형의 넓이를 구하는 메소드 */
	public void clacArea() {
		double area = width * height;
		System.out.println("이 사각형의 넓이는 " + area + "입니다.");
	}
	
	
	/* 사각형의 둘레를 구하는 메소드 */
	public void clacRound() {
		double round = (width + height) *2;
		System.out.println("이 사각형의 둘레는 "+ round + "입니다.");
	}
	
	
	
}

 

 

 

 

 

 

 

 

static

 

 

static이란?
  • 정적 메모리 영역에 프로그램이 start될 시 할당 하고자 할 때 사용하는 키워드
  • static 필드나 메소드는 인스턴스 생성 없이 사용 가능
  • 여러 인스턴스가 공유해서 사용할 목적으로 만드는 것

 

 

두번째static은 필드 마지막static은 메소드

 

heap은 동적인 영역이라고 한다. 프로그램 진행에 따라 생성이 되었다가, 
더이상의 사용이없으면 지워진다.

static은 정적인 영역이라고 한다. 프로그램 시작시 생성되었다가 
프로그램이 종료되는 사라진다.

공간의 사용이 다르고 특성이 다르다. 
stack은 객체 생성시 할당되는 영역이 아니다. 

인스턴스는 각각의 공간이 형성되지만, 
스태틱은 프로그램 시작시 생성되는 하나의 영역에 형성된다.

여러인스턴스가 공유해서 사용할 목적으로 사용

 

 

 

 

 

final

 

final이란?
  • 변경 불가의 의미를 담고 있는 키워드
  • 메소드에서는 종단의 의미를 지님
  • 클래스 필드의 final 변수는 선언과 동시에 초기화 하거나 생성자를 통한 초기화를 해야 함 (그렇지않으면 0.0으로 초기화되는 문제가 발생한다.)

 

첫번째 final은 필드

 

 

 

 

 

 

StaticFieldTest 메인 메소드
public class Application {

	public static void main(String[] args) {
		
		/* static : 정적 메모리 영역에 프로그램이 시작될 시에 할당을 하는 키워드이다. 
		 * 			인스턴스를 생성하지 않고도 사용할 클래스의 멤버(필드, 메소드)에 
		 * 			지정할 수 있다.
		 * 			여러 인스턴스가 공유해서 사용할 목적의 공간이다. 
		 * 			하지만 static  키워드의 남발은 유지보수와 추적이 힘든 코드를 
		 * 			작성하는 방식으로, 명확한 목적이 존재하지 않는이상 static 키워드
		 *  		사용은 자제
		 *    		=> 의도적으로 static키워드를 사용하는 대표적인 예는 
		 *    		singleton 객체를 생성할때
		 *
		 * 
		 * */
		
		
		

		/* static 키워드를 필드에서 사용할 때 */
		StaticFieldTest sft1 = new StaticFieldTest();
		// 클래스 생성
		
		
		
		/* 현재 두 필드가 가지고 있는 값 확인 */
		System.out.println("non-static field : " + sft1.getNonStaticCount());
		System.out.println("static field : " + sft1.getStaticCount());
//		non-static field : 0
//		static field : 0
		
		
		/* 두 필드의 값 1씩 증가 후 다시 값 확인 */
		sft1.increaseNonStaticCount();
		sft1.increaseStaticCount();
		System.out.println("non-static field : " + sft1.getNonStaticCount());
		System.out.println("static field : " + sft1.getStaticCount());
//		non-static field : 1
//		static field : 1
		
		
		/* 새로운 StaticFieldTest 인스턴스 생성 */
		StaticFieldTest sft2 = new StaticFieldTest();
		System.out.println("non-static field : " + sft2.getNonStaticCount());
		System.out.println("static field : " + sft2.getStaticCount());		
//		non-static field : 0
//		static field : 1
		
		
		
		/* 인스턴스 변수의 경우에는 sft1과 sft2 두개의 인스턴스가 
		 * 서로 값을 공유하지못하고 인스턴스를 생성할 때마다 0으로 초기화 되었다.
		 * 하지만 static 필드의 경우에는 클래스 변수 자체가 
		 * 프로그램을 종료할 때까지 유지되고 있기 때문에
		 * 값을 유지하고 있다.
		 * => 여러개의 인스턴스가 같은 공간을 공유할 목적으로 
		 * 필드에 static 키워드를 사용한다. */
		
		
		/* static 키워드를 method에 작성 */
		StaticMethodTest smt = new StaticMethodTest();
		smt.nonStaticMethod();
		
		
		
		/* 클래스명.메소드명으로 인스턴스를 생성하지않고 호출할 수 있다. 
		 * 예: Math클래스의 메소드들
		 * */
		StaticMethodTest.staticMethod(); 
		//이미 프로그램시작시 생성됐던 공간에서 호출가능
		
		
		
		/* static메소드의 경우 인스턴스를 생성하지 않고 
		 * '호출하는 방식'으로 사용해야 한다. */
		smt.staticMethod();
		//경고문구가 뜬다. 권장되는 방식이 아니기 때문이다.
		
		
		
	}

}

 

StaticFieldTest 클래스
public class StaticFieldTest {

	/* non-static 필드와 static 필드 선언 */
	private int nonStaticCount;			//인스턴스 변수
	private static int staticCount;		// 스태틱 변수
	
	public StaticFieldTest() {}
	
	
	/* 두 필드에 대한 값을 확인 */
	public int getNonStaticCount() {
		return this.nonStaticCount;
	}
	
	public int getStaticCount() {
		/* static 필드에 접근하기 위해서는 클래스명.필드명으로 접근한다. */
		return StaticFieldTest.staticCount;
		// 어떤객체의 주소값이 this
	}
	
	

	
	
	
	/* 두 필드 값을 1씩 증가시키기 위한 용도의 메소드 */
	
	public void increaseNonStaticCount() {
		this.nonStaticCount++;
		
		
	}
	
	
	public void increaseStaticCount() {
		StaticFieldTest.staticCount++;
		
	}
	
	
	
	
}

 

 

 StaticMethodTest
public class StaticMethodTest {

	/*필드*/
	private int count;
	
	
	
	
	public void nonStaticMethod() {
		
		this.count++;		
		// 인스턴스 생성 후 사용가능한 메소드이기 때문에 this에는 주소가 들어있을 것이다.
		
		System.out.println("nonStaticMethod 호출됨...");
		
	}
	
	
	
	public static void staticMethod() {
		// this.count++;		
		// 컴파일 에러남. Cannot use this in a static context
		// this 는 객체의 주소값이다. 즉, 인스턴스를 생성했을때의 값
		// 인스턴스를 생성하지않고 사용하는 메소드이기 때문에 this에는 주소가 들어갈 수 없다.
		System.out.println("staticMethod 호출됨...");
		
		
	}
	
}

 

 

 

 

 

 FinalFieldTest 
public class FinalFieldTest {

	
	/* non-static field에 final 사용 */
	
	
	/* final은 변경 불가의 의미를 가진다.
	 * 따라서 초기 인스턴스가 생성되고 나면 기본값 0이 필드에 들어가게 되는게
	 * 그 초기화 이후 값을 변경할 수 없기 때문에 선언하면서 바로 초기화를 해주어야한다.
	 * 그렇지 않으면 컴파일 에러가 발생한다. 
	 * The blank final field nonStaticNum may not have been initialized
	 *  */
	
	// private final int nonStaticNum;
	// 에러발생 0으로 초기화되어 이후 변경 불가능
	
	
	/* 1. 선언과 동시에 초기화 한다. */
	private final int NON_STATIC_NUM =1;
	// 상수는 대문자로 표현하는 것이 관례이므로 언더바로 구분한다.
	
	
	
	
	
	/* 2. 생성자를 이용해서 초기화 함 */
	private final String NON_STATIC_NAME;
	
	
	public FinalFieldTest(String nonStaticName) {
		this.NON_STATIC_NAME = nonStaticName;
		
	}
	
	
	
	
	
	
	
	/* static field에 final 사용 */
	
	/* static 에서도 자바에서 지정한 기본값이 초기에 대입되기 때문에
	 * final키워드 사용시 초기화를 하지않으면 에러가 발생한다. */
	// private static final int STATIC_NUM; 
	// 에러발생 0으로 초기화 되기 때문에 이후 변경 불가능
	
	// 접근제한자와 자료형 사이에 static 과 final 위치
	// 정적메모리영역도 기본값으로 초기화
	
	private static final int STATIC_NUM = 1; 

	
	
	
	/* 생성자를 이용한 초기화는 불가능하다. */
	/* 생성자는 인스턴스가 생성되는 시점에 호출이 되기 때문에 그 전에는 초기화가
	 * 일어나지 못한다. 하지만 static은 프로그램이 시작될 때 할당되기 때문에 초기화가
	 * 되지않은 상태로 선언된 것과 동일하다.
	 *  */
////	private static final double STATIC_DOUBLE;
//	
////	public FinalFieldTest(double staticDouble) {
////		FinalFieldTest.STATIC_DOUBLE = staticDouble;
		
	}

 

 

 

 

 

 

singleton

싱글톤 패턴(singleton pattern)이란?
  • 클래스의 인스턴스 사용시 메모리 공간에 있는 하나의 인스턴스를 공유해서 사용하는 디자인 패턴
    (생성 된 하나의 인스턴스만을 사용) ex: 법인카드를 공유해서 전팀이 사용하는 것

 

Singleton 메인 메소드
public class Application {

	public static void main(String[] args) {
	
		/* static을 이용한 싱글톤 패턴 */
		/* singleton 패턴이란?
		 *  : 애플리케이션이 시작될 때 어떤 클래스가 최초 한 번만 메모리를 할당하고 
		 *  그 메모리에 인스턴스를 만들어서 하나의 인스턴스를 공유해서 사용하여 메모리 낭비를
		 *  방지할 수 있게 함(매번 인스턴스를 생성하지 않음)
		 *  
		 *  
		 *  장점 
		 *  1. 첫 번째 이용 시에는 인스턴스를 생성해야 하므로 속도 차이가 나지 않지만
		 * 	   두 번째 이용시에는 인스턴스 생성시간 없이 사용할 수 있다. 
		 *  2. 인스턴스가 절대적으로 한개만 존재하는 것을 보증할 수 있다. 
		 *  
		 *  
		 *  단점
		 *  1. 싱글톤 인스턴스가 너무 많은 일을 하거나 많은 데이터를 공유하면 결합도가 높아진다.
		 *  	(유지보수와 테스트에 문제점이 있음)
		 *  2. 동시성 문제를 고려해서 설계해야 하기 때문에 난이도가 있다.
		 *  
		 *  */
		
		
		/* 싱글톤 구현방법
		 * 1. 이른 초기화 (Eager Initialization)
		 * 2. 게으른 초기화 (Lazy Initialization)
		 * 
		 * 
		 *  */
		
		
		/* 1. 이른 초기화  */
		
		EagerSingleton eager1 = EagerSingleton.getInstance();
		EagerSingleton eager2 = EagerSingleton.getInstance();
	
		/* 두 인스턴스의 해쉬코드가 같은 것을 알 수 있다.
		 * 즉, 동일한 인스턴스이다. */
		System.out.println("eager1의 hashCode" + eager1.hashCode());
		System.out.println("eager2의 hashCode" + eager2.hashCode());		
		
		/* 반드시 하나의 객체에서, 인스턴스에서 가져오도록 싱글톤으로 보증했으니
		 * 하나의 주소만 나와야 한다. */
//		eager1의 hashCode1227229563
//		eager2의 hashCode1227229563
		
		
		
		/* 게으른 초기화 */
		LazySingleton lazy1 = LazySingleton.getInstance();
		LazySingleton lazy2 = LazySingleton.getInstance();
		
		/* 두 인스턴스의 hashCode가 동일함 */
		System.out.println("lazy1의 hashCode : " + lazy1.hashCode());
		System.out.println("lazy2의 hashCode : " + lazy2.hashCode());
		
//		lazy1의 hashCode : 1910163204
//		lazy2의 hashCode : 1910163204
		
		
		

	}

		
		/* 이른 초기화를 사용하면 클래스를 로드하는 속도가 느려지지만
		 * 처음 인스턴스 반환 요청에서는 속도가 빠르다는 장점을 가진다. 
		 * 
		 * 게으른 초기화를 사용하면 클래스를 로드하는 속도는 빠르지만
		 * 첫번째 요청에 대한 속도가 두번째 요청에 대한 속도보다 느려진다는 
		 * 특징을 가지고 있다. 
		 *  
		 *  */
		
		
		
		
		
}

 

 

EagerSingleton
public class EagerSingleton {

	/* 클래스가 초기화 되는 시점에서 인스턴스를 생성한다. */
	private static EagerSingleton eager = new EagerSingleton();
	
	
	
	/* 싱글톤 패턴은 생성자 호출을 통해 외부에서 인스턴스를 생성하는 것을 제한한다. */
	private EagerSingleton() {}
		// 접근을 못하므로 객체 생성을 못함 
	
	
	
	
	/* 만들어놓은 인스턴스를 반환한다. */
	public static  EagerSingleton getInstance() {
		return eager;
	}	
	// 단하나 생성되는 인스턴스를 퍼블릭으로 반환
	// new 생성이 아니어도 호출 가능 (static)
	
	
	
	
	
}

 

 

LazySingleton
public class LazySingleton {

	/* 클래스가 초기화되는 시점에는 정적 필드를 선언해두고 null로 초기화된다. */
	private static LazySingleton Lazy;
	// 참조 변수이므로 null로 초기화
	
	
	/* 싱글톤 패턴은 생성자 호출을 통해 외부에서 인스턴스를 생성하는 것을 제한한다. */
	private LazySingleton()	{}
	
	
	
	/* 인스턴스를 생성한 적이 없는 경우 인스턴스를 생성해서 반환하고 
	 * 생성한 인스턴스가 있는 경우 만들어둔 인스턴스를 반환한다.
	 *  */
	public static LazySingleton getInstance() {
	
		if(Lazy == null) {
			/* 인스턴스를 생성한 적이 없는 경우 새로운 인스턴스 생성 */
			Lazy = new LazySingleton();
			
		}
		
		return Lazy;
	}
	
	// 이른초기화는 필드선언과 동시에 
	// 게으른 초기화는 필드선언시에는 반환하지않고 호출시에 인스턴스 반환
	// 생성되는 시기에만 차이가 있는 방법일뿐 의도는 동일하다.
	
	
	
}

 

 

 

 

 

 

클래스에서의 변수

 

변수의 종류
  • 클래스에서의 변수는 아래와 같이 구분한다.
  1. 클래스 변수 : static 키워드를 가지고 필드에 선언하는 변수, 메모리의 static영역 사용
  2. 멤버 변수(인스턴스 변수) : static 키워드 없이 필드에 선언하는 변수, 메모리의 heap영역 사용
  3. 지역 변수 : 메소드, 생성자, 초기화 블록 내부에서 선언하는 변수

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

상속  (0) 2022.01.04
객체 배열  (0) 2022.01.03
클래스와 객체(2)  (0) 2021.12.29
배열, 클래스와 객체  (0) 2021.12.28
배열  (0) 2021.12.27

 

 

 

캡슐화

 

 

 

캡슐화(Encapsulation)란?
  • 캡슐화는 결합도를 낮추기 위해 필드의 직접 접근을 제한하고 public 메소드를 이용해서
    간접적으로 접근하여 사용할 수 있도록 만든 기술
  • 유지보수성과 각 클래스간의 결합도를 낮추는데 용이하다.
  • 필드 접근제한자

 

결합도란? 결합은 서로 연결되어있다는 의미. 클래스를 A를 정의하면 또 다른 클래스 B가 그것을 이용할 수 있다. 만약 A의 내용중 일부를 바꾼다면 B에서는 에러가 날것이다. 정의한 클래스에 따라 에러가 많이난다면 '결합도가 높다'고 한다. 직접 접근은 결합도가 높아 에러가 날 확률이 높으며 메소드를 통한 접근은(은닉) 결합도를 낮춘다. 그러한 은닉을 위한 방법중 하나가 캡슐화이다. 정리하면 재사용성과 유지보수성을 위해서 캡슐화가 자주사용되고 결과적으로 결합의 정도를 낮춘다. 

 

 

public class Application4 {

	public static void main(String[] args) {
		/* 여전히 필드에 직접 접근할 수 있는 문제가 있으므로
		 * 필드에 직접 접근을 제한하는 방식으로 Monster 클래스를 다시 작성한다.
		 * 
		 *  
		 *  */

		
		/* 접근제한자 private 를 붙여서 필드에 직접 접근하면 컴파일 에러가 발생한다.
		 * 접근을허용하지 않았기 때문에 직접 접근할 수 없다는 의미이다.
		 * '메소드를 통한 간접 접근을 강제화' 한 것이다. 
		 * */
		
		Monster monster1 = new Monster();
	//	monster1.kinds = "프랑켄슈타인";
		// kinds에 컴파일 에러 발생
		// The field Monster.kinds is not visible
	//	monster1.hp = 200;
		// The field Monster.hp is not visible
		
		
		monster1.setKinds("프랑켄슈타인");
		monster1.setHp(200);
		
		System.out.println(monster1.getInfo());
		
		//콘솔창
		//몬스터의 종류는프랑켄슈타인이고, 체력은 200입니다.
		
		
		/* 선어언한 필드대로 공간은 생성되어 있지만 직접 접근 못하고
		 * public 으로 접근을 허용한 메소드만 이용할 수 있도록 해놓은 것이다.
		 * 이것을 캡슐화(encapsulation) 라고 부른다.
		 * => 캡슐화는 유지보수성 증가를 위해 필드의 직접 접근을 제한하고
		 * public 메소드를 이용해서 간접적으로 접근하여 사용할 수 있도록 만든 기술로
		 * 클래스 작성 시 특벽한 목적이 아닌 이상 캡슐화가 기본 원칙으로 사용되고 있다. 
		 * 
		 *  */
		
		
	}

}

 

클래스
public class Monster {

	/* 접근 제한자
	* 클래스 혹은 클래스의 멤버에 참조연산자로 
	* 접근할 수 있는 범위를 제한하기위한 키워드이다. 
	* 
	* 1. public : 모든 패키지에 접근 허용
	* 2. protected : 동일패키지에 접근 허용. 
	* 				단, 상속관계에 있는 경우 다른패키지에서도 접근가능
	* 3. default : 동일 패키지에서만 접근 허용(작성하지않는 것이 default)
	* 4. private : 해당 클래스 내부에서만 접근허용
	* 
	* 위의 네가지 접근 제한자는 클래스의 멤버 (필드, 메소드)에 모두 사용 가능하다.
	* 단, 클래스 선언시 사용하는 접근 제한자는 public 과 default만 사용 가능하다.
	* 1) 필드, 또는 2) 메소드 앞에서만 사용가능
	* 
	* */
	
	private String kinds;
	private int hp;
	


	/* 간접접근할 수 있는 메소드 작성하기 */
	
	public void setKinds (String kinds) {
		this.kinds = kinds;
	}
	
	
	public void setHp (int hp) {
		if (hp>0) {
			this.hp = hp;
			
		}else {
			this.hp = 0;
		}
	
	}
	
	
	public String getInfo() {
		return "몬스터의 종류는" + this.kinds + "이고, 체력은 " + this.hp + "입니다.";
		}
		// this 객체 자기자신의 주소값을 가지고있는 참조변수
		// 입력받은 문자열을 필드에 대입한다.
		// gerInfo 필드에 직접접근을 못하므로 가진 결과값을 알기위함
	
	
}

 

 

객체 지향 언어

 

객체 지향 언어란?
  • 현실 세계는 사물이나 개념처럼 독립되고 구분되는 각각의 객체로 이루어져 있으며, 발생하는 모든 사건들은 객체 간의 상호작용이다. 이 세계관을 프로그래밍 언어에 도입하여 만들어진 언어가 객체 지향 언어이다.
  • 목표 : 유지보수

 

 

 

 

 

 

 

 

클래스와 인스턴스

 

 클래스(class)란?
  • 객체를 추상화한 것이다. 인스턴스를 생성 할 목적으로 정의 해놓은 소스 코드 작성 단위.
    (자바에서 객체를 구현하기 위한 매커니즘으로 클래스를 사용한다)
    ex) 회원, 자동차, 도서 등

 

 

 

객체(Object)란?
  • 현실에 존재하는 독립적이면서 하나로 취급되는 사물이나 개념
    클래스에 정의된 대로 new 연산자를 통해 heap에 할당된 공간 (== 인스턴스)
클래스 인스턴스화 인스턴스
학생이 가지는 공통적인
기능과 속성을 추상화 하여
클래스를 정의
현실세계에 존재하는
고유 객체를 취급하듯
개별 인스턴스를 메모리에 할당

 

 

 

 

 

객체의 할당
  • new 연산자와 생성자를 사용하여 객체 생성 시 heap 메모리 공간에 서로 다른 자료형의
    데이터가 연속으로 나열/할당 된 인스턴스 공간

 

 

 

 

추상화

추상화(abstraction)란?
  • 유연성을 확보하기 위해 구체적인 것은 제거한다는 의미
    프로그램에서 필요한 공통점을 추출하고, 불필요한 공통점을 제거하는 과정
  • 스포츠카, 택시, 트럭(개개의 구체적인 대상)의 공통점은? '차'(공통점)라는 데에 있음

 

 

행동중심의 추상화 예제

 

import java.util.Scanner;

public class Application {

	public static void main(String[] args) {


		/* 객체 지향 프로그램이란
		 * 현실세계의 모든 시간(event)은 객체와 객체의 상호작용에 의해 일어난다는 세계관을
		 * 프로그램을 만들때 이용하여 새로운 세계를 창조하는 방법론이다. 
		 * 
		 * 이때 객체를 설계하기 위해서는 복잡한 현실세계를 그대로 반영하기에는 너무 방대하고 복잡하기 때문에
		 * 현실세계를 프로그램의 목적에 맞게 단순화하는 추상화라는 기법을 적용하게 된다.
		 * 
		 * 추상화란?
		 * 공통된 부분을 추출하고 공통되지않은 부분은 제거한다는 의미를 가지며, 추상화의 목적은 유연성을 확보하기 위함이다.
		 * 유연성의 확보는 여러곳에 적용될 수 있는 유연한 객체를 의미하며, 즉 재사용성이 높아질 수 있게 한다는 의미이다.
		 * 객체의 재사용성이 증가하면 중복 작성되는 코드를 줄일수 싱ㅆ으며, 오류발생 가능성을 감소시키고 유지보수성을 증가시킨다. 
		 * */
		
		
		/* 만들려고 하는 프로그램
		 * : 카레이서가 자동차를 운전하는 프로그램 
		 * 
		 * 기능을 최대한 단순화 시켜서 프로그램을 만든다.
		 * 1. 자동차는 처음에 멈춘 상태로 대기하고 있는다.
		 * 2. 카레이서는 먼저 자동차에 시동을 켠다. 이미 걸려있는 경우 다시 시동을 걸 수 없다.
		 * 3. 카레이서가 엑셀을 밟으면 시동이 걸린 상태일 경우 자동차는 시속 10km/h 증가하며 앞으로 나간다.
		 * 4. 자동차가 달리는 중인 경우 브레이크를 밟으면 자동차의 시속은 0으로 떨어지며 멈춘다.
		 * 5. 브레이크를 밟을 때 자동차가 달리는 중이 아니라면 이미 멈춰있는 상태라고 안나핸다.
		 * 6. 카레이서가 시동을 끄면 더이상 자동차는 움직이지 않는다.
		 * 7. 자동차가 달리는 중이라면 시동을 끌 수 없다. 
		 * 
		 * */
		
		/* 여기서 필요한 객체는 카레이서와 자동차 객체이다.
		 * 카레이서가 수신할 수 있는 메세지는 카레이서가 할 일과 동일하다.	
		 * //메세지 == 메소드 == 기능
		 * 
		 * 1. 시동을 걸어라
		 * 2. 엑셀을 밟아라
		 * 3. 브레이크를 밟아라
		 * 4. 시동을 꺼라
		 * 
		 * 자동차가 수신할 수 있는 메세지는 자동차가 해야할 일과 동일하다.
		 * 1. 시동을 걸어라
		 * 2. 앞으로 가라
		 * 3. 멈춰라
		 * 4. 시동을 꺼라
		 * 
		 *  */
		
		/* 카레이서 생성 */
		CarRacer racer = new CarRacer();
		// CarRacer cannot be resolved to a type 만든적이 없으니 에러가 뜬다.
		// 마우스 오버하여 생성해준다.
		
		Scanner sc = new Scanner(System.in);
		
		while(true) {
			
			System.out.println("======카레이싱 프로그램======");
			System.out.println("1. 시동걸기");
			System.out.println("2. 전진");
			System.out.println("3. 정지");
			System.out.println("4. 시동끄기");
			System.out.println("9. 프로그램 종료");
			System.out.print("메뉴선택 : ");
			int no = sc.nextInt();
			
			switch(no) {	// 입력한 번호에 따라 스위치 발동
			case 1 : racer.startUp(); 
						break;			// 컴파일 에러에 마우스를 가져다 다면 메소드를 만들 수 있음
			case 2 : racer.stepAccelator(); 
						break;
			case 3 : racer.stepBreak(); 
						break;
			case 4 : racer.turnOff(); 
						break;
			case 9 : System.out.println("프로그램을 종료합니다."); 
						return; 	// 값을 출력
			default : System.out.println("잘못된 번호를 선택하셨습니다.");
						// 1,2,3,4,9 외의 번호를 입력한 경우
			}
			
			
		}
		
		

	}

}

// 프로그램 동작시 콘솔출력내용
//======카레이싱 프로그램======
//1. 시동걸기
//2. 전진
//3. 정지
//4. 시동끄기
//9. 프로그램 종료
//메뉴선택 : 1
//시동을 걸었습니다. 이제 출발할 준비가 완료 되었습니다.
//======카레이싱 프로그램======
//1. 시동걸기
//2. 전진
//3. 정지
//4. 시동끄기
//9. 프로그램 종료
//메뉴선택 : 2
//차가 앞으로 움직입니다.
//현재 차의 시속은 10km/h 입니다.
//======카레이싱 프로그램======
//1. 시동걸기
//2. 전진
//3. 정지
//4. 시동끄기
//9. 프로그램 종료
//메뉴선택 : 3
//브레이크를 밟았습니다. 차를 멈춥니다.
//======카레이싱 프로그램======
//1. 시동걸기
//2. 전진
//3. 정지
//4. 시동끄기
//9. 프로그램 종료
//메뉴선택 : 4
//시동을 끕니다. 다시 운행하려면 시동을 켜주세요.
//======카레이싱 프로그램======
//1. 시동걸기
//2. 전진
//3. 정지
//4. 시동끄기
//9. 프로그램 종료
//메뉴선택 : 9
//프로그램을 종료합니다.

 

CarRacer 예제
public class CarRacer {
	
	/* CarRacer가 상호작용할 Car 클래스를 CarRacer는 알고있어야 한다.
	 * 알고 있다는 의미는 필드에 가지고 있다는 것을 의미한다.
	 *  */
	
	private Car car = new Car(); 
	// 마우스를 올려 에러를 해결
	// 컴파일 오류 : Car cannot be resolved to a type
	
	
	

	public void startUp() {
		car.starUp();
		//컴파일 오류, 한번더 마우스를 올려 메소드 생성
	}

	public void stepAccelator() {
		car.go();
		//컴파일 오류, 한번더 마우스를 올려 메소드 생성
		
	}

	public void stepBreak() {
		car.stop();
		//컴파일 오류, 한번더 마우스를 올려 메소드 생성
		
	}

	public void turnOff() {
		car.turnOff();
		//컴파일 오류, 한번더 마우스를 올려 메소드 생성
		
	}

	
	
}

 

Car 예제
public class Car {

	/* 시동을 켜거나 끄거나, 앞으로 가거나 멈추거나 하는 행동은 
	 * 시동이 걸려있는지의 상태를 확인해야한다.
	 * 즉, 메소드간에 서로 공유하는 속성이 존재한다.
	 * 그러한 속성을 필드에 작성한다.
	 *  */
	
	/* 각각의 메소드 별로 상태가 공유되는 부분이 있어야한다.
	 * 필드에 작성되어있는 각 메소드들이 공통적으로 공유하는 내용 */
	private boolean isOn; 		//  초기에는 시동이 꺼진 false 상태
	private int speed;			//	초기에는 속도 0
	
	
	
	public void starUp() {
		/* 시동이 걸려있는 상태인 경우에는 할 일이 없고,
		 * 시동이 걸려있지 않은 경우에만 시동을 켤 것이다. */
		if (isOn) {		
			System.out.println("이미 시동이 걸려있습니다.");
		} else {
			this.isOn = true;	//필드에 트루값 반환
			System.out.println("시동을 걸었습니다. 이제 출발할 준비가 완료 되었습니다.");		
		}
		
	}

	
	
	
	public void go() {
		if (isOn) {
			/* 가속을 할 때마다 속도를 10 km/h 씩 증가시킬 것이다. */
			System.out.println("차가 앞으로 움직입니다.");
			this.speed += 10;	// 차의 속도에 10이라는 값을 누적연산
			System.out.println("현재 차의 시속은 " + this.speed + "km/h 입니다.");
			
		} else {
			System.out.println("차의 시동이 걸려있지 않았습니다. 시동을 먼저 걸어주세요.");
		}
		
	}

	
	
	
	
	public void stop() {
		if (isOn) {
			/* 차가 시동이 걸려있는지 먼저 확인 */
			if(speed > 0) {
				/* 달리고 있는 상태인 경우 */
				speed = 0;
				System.out.println("브레이크를 밟았습니다. 차를 멈춥니다.");
			} else {
				System.out.println("차는 이미 멈춰있는 상태입니다.");
			}
			
		} else {
			System.out.println("차의 시동이 걸려있지 않았습니다. 시동을 먼저 걸어주세요.");
		}

	}
	
	
	
	
	

	public void turnOff() {
		if(isOn) {
			if(speed > 0) {
				System.out.println("달리는 상태에서 시동을 끌 수 없습니다. 차를 우선 멈춰주세요.");
			} else {	//speed = 0;
				isOn = false;	// 시동을 끄는 행위
				System.out.println("시동을 끕니다. 다시 운행하려면 시동을 켜주세요.");
			}
			
		} else {
			System.out.println("이미 시동이 꺼져있는 상태입니다. 시동 상태를 확인해주세요.");
		}
		
	}



}

 

 

 

 

 

 

 

 

 

 

 

getter와 setter

 

 

  • 세터 작성 규칙
public void set필드명(매개변수) {	
	 필드 = 매개변수;				
     
     
     * 메소드의 이름은 카멜케이스 적용
     * 필드명과 매개변수 명은 같아야 한다.

 

 

  • 게터 작성 규칙
public 반환형 get필드명() {
 		return 반환값;
 }
 
 
	* [작성예시]
	 public String getName() {
		return this.name;			
        
                                    
                                    
   * this는 필수가 아니다. 왜냐하면 구분지어줘야 할 변수명이 없기 때문
   * boolean 타입은 get필드명() 이 아니라 is필드명()으로 작성한다.

 

 

 

속성 관점의 추상화 예시
public class MemberDTO {

	
	/* 취급하려고 하는 회원 정보를 구상해서 필드를 먼저 작성한다.
	 * 회원번호, 회원명, 나이, 성별, 키, 몸무게, 회원탈퇴여부(활성화여부)를 관리할것이다.
	 * 값 객체가 가지는 속성(필드)를 추출하는 과정 또한 추상화라고 볼 수 있다. 
	 *  
	 *  */
	// 캡슐화의 원칙 : 직접 접근불가, 세터와 게터
	private int number;				// 회원번호
	private String name;			// 회원명
	private int age; 				// 나이
	private char gender;			// 성별
	private double height;			// 키
	private double weight;			// 몸무게
	private boolean isActivated; 	// 회원 탈퇴여부(활성화여부)
	
	
	/* private로 만들면 필드에 직접 접근이 제한되므로 public 으로 접근을 허용하는
	 * 설정자/접근자를 통해 간접 접근할 수 있도록 한다.
	 *  */
	
	
	/* 설정자(setter)/접근자(getter)의 경우 실무에서 암묵적으로 통용되는 작성규칙이 존재한다.
	 * 외우고 숙지할 내용이다 *
	 * 
	 * 설정자 (setter) 작성규칙
	 *  : 필드 값을 변경할 목적의 매개변수를 변경하려는 필드와 같은 자료형으로 선언하고
	 *    호출당시 전달되는 매개변수의 값을 이용하여 필드의 값을 변경한다.
	 * 
	 * [표현식]
	 * public void set필드명(매개변수) {	// 메소드의 이름은 카멜케이스 적용
	 * 		필드 = 매개변수;				// 필드명과 매개변수 명은 같아야 한다.
	 * {
	 * 
	 * [작성예시]
	 * public void setName(String name) {
	 * 		this.name = name;			// 필드와 매개변수의 이름이 같을때 
	 * 									// 주소값인 this를 붙여 name이 전역변수임을 알게한다.
	 * 									// 값을 설정하는 메소드이므로 돌려줄 값이 없으니 void이다.
	 *									// 매개변수에서 전달받은 값을 필드에 설정하는게 목표인 식 
	 * }
	 * 
	 * 
	 * 
	 * 접근자(getter) 작성규칙
	 *  : 필드의 값을 반환받을 목적의 메소드 집합을 의미한다.
	 *	  각 접근자는 하나의 필드에만 접근하도록 한다.
	 * 	  필드에 접근해서 기록 된 값을 return을 이용하여 반환하며, 
	 *    이 때 반환 타입은 변환하려는 값의 자료형과 일치시킨다. 
	 * 
	 * [표현식]
	 * public 반환형 get필드명() {
	 * 		return 반환값;
	 * }
	 * 
	 * [작성예시]
	 * public String getName() {
	 * 		return this.name;			// 여기서 this는 필수가 아니다.
	 * 									// 왜냐하면 겹치는(동일해서 구분지어줘야할)
	 * 									// 변수명이 있는게 아니기때문
	 * 
	 * }
	 * 
	 *  */
	
	
	
	
	/* 설정자(setter) 메소드 */
	//값설정이 목적이므로 반환형 없음 = void
	// 매개변수명과 필드명이 동일해야하고 구분을 위한 this가 필요
	
	
	public void setNumber(int number) {
		
		this.number = number; 			// 필드와 받아온 값명 동일
		
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	
	public void setAge(int age) {
		this.age = age;
	}
	
	public void setGender(char gender) {
		this.gender = gender;
	}
	
	public void setHeight(double height) {
		this.height = height;
	}
	
	public void setWeight(double weight) {
		this.weight = weight;
	}
	
	public void setActivated(boolean isActivated) {
		this.isActivated = isActivated;
	}
	

	
	
	/* 접근자(getter) 메소드 */
	public int getNumber() {
		return number; 			
		// this가 없는 이유: 
		// 혼동되는 지역변수가 없기때문에 바로 필드값으로 인식할 수 있다. 
	}
	
	
	public String getName() {
		return name;
	}
	
	public int getAge() {
	return age;
	}
	
	public char getGender() {
		return gender;
	}
	
	public double getHeight() {
		return height;
	}
	
	public double getWeight() {
		return weight;
	}
	
	
	/* boolean타입의 접근자는 get으로 시작하지않고 is로 시작하는 것이 일반적인 관계이다. */
	public boolean isActivated() {
		return isActivated;
	}
	
	
	
}

 

 

메인메소드
public class Application {

	public static void main(String[] args) {

		/* 앞서 추상화를 이용해 객체를 설계하고 클래스를 이용해 프로그래밍 해보았다. 
		 * 하지만 추상화라고 하는 것은 매우 어려운 작업이다.
		 * 캡슐화의 원칙에 일부 어긋나긴 하지만 매번 추상화를 하지 않아도 되는 객체도 존재한다.
		 * 행위 위주가 아닌 데이터를 하나로 뭉치기 위한 객체 (Date Transfer Object)의 경우이다. 
		 * 
		 * 데이터를 전송하기 위한 객체 - dto
		 * 값 객체를 설계할 때는 행위가 아닌 데이터가 위주이며, 캡슐화의 원칙을 준수하여
		 * 모든 필드를 private 로 직접 접근을막고, 
		 * 각 필드값을 변경하거나 반환하는 메소드를 세트로 미리 작성해준다.(캡슐화의 원칙)
		 * 
		 * private 필드와 필드값을 수정하는 설정자 (setter), 필드에 접근하는 접근자 (getter)들로 구성된다.
		 * 
		 * 
		 * */
		
		/* 설정된 값 전달 */
		MemberDTO member =  new MemberDTO();
		member.setNumber(1);	//설정자 이용
		member.setName("유관순");
		member.setAge(16);
		member.setGender('여');
		member.setHeight(160.5);
		member.setWeight(55.5);
		member.setActivated(true);
		
		/* 값 확인 */
		System.out.println("회원번호 : " + member.getNumber());
		System.out.println("회원명 : " + member.getName());
		System.out.println("나이 : " + member.getAge());
		System.out.println("성별 : " + member.getGender());
		System.out.println("키 : " + member.getHeight());
		System.out.println("몸무게 : " + member.getWeight());
		System.out.println("회원 활성화 상태 : " + member.isActivated());
		
		
// 콘솔창 출력		
//		회원번호 : 1
//		회원명 : 유관순
//		나이 : 16
//		성별 : 여
//		키 : 160.5
//		몸무게 : 55.5
//		회원 활성화 상태 : true
		
		
        
        
		/* 캡슐화 원칙에 따라 작성하기는 했지만 실제로는 캡슐화가 의미가 없을 정도로
		 * 필드명을 그대로 사용한 설정자와 접근자로 인해 캡슐화 효과가 없다.
		 * 하지만 데이터를 주로 다루는 객체의 경우 행위를 추상화 하지않고
		 * 미리 모든 필드에 접근 가능성을 염두에 두고 작성해두는 관례로 인해 현재도 많이 사용되도 있다.
		 * DTO의 작성법은 익숙해져야 한다. */
		
		
        
        
	}

}

 

 

 

 

 

 

생성자

MemberDTO member = new Member( )
        생성자

 

 

생성자(Constructor)란?
  • 객체가 new 연산자를 통해 Heap 메모리 영역에 할당될 때 "1회성으로 호출되는 리턴타입이 없는 메소드"
  • 반환형이 없으며, 클래스 명을 동일하게 작성하고 메소드 정의하듯이 정의된다.
  • 즉, 생성자는 메소드작성에서 리턴타입만 빠진 형태이다. 
  • 인스턴스 생성 시 생성자를 이용해 필드에 값을 부여해 초기화 할 수 있다. 

 

생성자 작성 규칙
  • 생성자의 선언은 메소드 선언과 유사하지만 반환값이 없음 (void도 작성하지않는다.)
  • 생성자명은 클래스명과 동일해야 함*

 

 

 

생성자 표현식

 

 

 

 

 

 

 

this

 

 

this란?
  • 모든 인스턴스의 메소드에 숨겨진 채 존재하는 레퍼런스 변수로, 할당된 인스턴스의 주소가 저장된다.

* 위와 같이 매개변수를 가지는 생성자에서 매개변수 명이 필드명과 같은 경우
: 매개변수의 변수명이 우선이므로 this를 이용하여 '필드'라는 것을 구분해 줌

 

 

 

 

 

생성자 예문
public class Application {

	public static void main(String[] args) {


		/* 지금까지 우리가 객체를 생성할 때
		 * 클래스명 레퍼런스변수 = new 클래스명(); 이라고 작성했으나
		 * new 뒤의 클래스 명은 사실 생성자(Constructor) 라 불리는 
		 * 메소드를 호출하는 구문이다. 
		 * 정확히 말하지면 클래스명 레퍼런스변수 = new 생성자(); 라고 표현한다.
		 * 즉, 클래스 =/= 생성자 && 클래스명 == 생성자명
		 * 
		 * */
		
		/* 생성자란?
		 * 인스턴스를 생생할 때 초기 수행할 명령이 있는 경우 미리 작성해두고, 
		 * 인스턴스를 생성할 때 호출된다.
		 * 생성자 함수에 매개변수가 없는 생성자를 기본생성자(default Constructor) 라고 하며,
		 * 기본 생성자는 compiler에 의해 자동으로 추가되었기 때문에 
		 * 지금까지 명시적으로 작성하지 않고 사용할 수 있었다. 
		 * 
		 * -> 매개변수 있는 생성자가 한개라도 존재하는 경우 컴파일러는 기본생성자를 
		 * 자동으로 추가해주지않으니 사용시 주의
		 * 
		 * new Member(); : 매개변수가 없는 기본생성자, 작성하지않아도 사용가능
		 * 
		 * 기본 생성자를 통해 인스턴스를 생성하게 되면 자료형별 초기값을 이용해 필드를 초기화 한다.
		 * 필드의 초기값을 사용자가 원하는 대로 설정하고 싶은 경우 생성자의 호출시 인자로 값을 전달하려 호출할 수 있다.
		 * 이러한 인자를 받아 필드를 초기화 할 목적의 생성자를 매개변수 있는 생성자라고 한다. 
		 * 즉 생성자의 목적: 매개값을 전달해 필드를 초기화 하는 것
		 * 
		 *  */
		
		
		
		
		/* 기본 생성자 호출 */
		User user1 = new User();
		System.out.println(user1.getInformation());
//콘솔		
//		User 클래스의 기본 생성자 호출함...
//		User [id = null, pwd = null, name = null, enrollDate = null
		
		
		
		
		/* id, pwd, name 초기화 하는 매개변수 생성자 호출 */
		User user2 = new User("user01", "pass01", "유관순");
		System.out.println(user2.getInformation());
//콘솔		
//		User 클래스의 id, pwd, name을 초기화하는 생성자 호출함...
//		User [id = user01, pwd = pass01, name = 유관순, enrollDate = null
		
	
		
		
		/* 모들 필드를 초기화하는 생성자 호출 */
		User user3 = new User("user01", "pass01", "홍길동",  new java.util.Date());
		System.out.println(user3.getInformation());
		
		// 유틸 데이트의 기본생성자를 호출해서 값을 전달해주어야 한다.
		// 내가 생성한 시점의 시간을 반환한다. 
		
//콘솔
//		User 클래스의 모든 필드를 초기화 하는 생성자 호출함...
//		User [id = user01, pwd = pass01, name = 홍길동, enrollDate = Wed Dec 29 14:16:02 KST 2021
		

		
		
		/* 복사 생성자 호출 */
		User user4 = new User(user3);
		System.out.println(user4.getInformation());
		
// 콘솔 : 이전에 호출된 this 때문에 결과값이 일부 쌓임
//		User 클래스의 id, pwd, name을 초기화하는 생성자 호출함...
//		User 클래스의 모든 필드를 초기화 하는 생성자 호출함...
//		User 클래스의 복사 생성자 호출함...
//		this의 hashCode : 88558700
//		otherUser의 hashCode :1265210847
//		User [id = user01, pwd = pass01, name = 홍길동, enrollDate = Wed Dec 29 14:18:56 KST 2021
		
		
        /* 정의되지 않은 형식의 생성자는 호출불가 */
		// User user5 = new User("user03", "pass03");
		// 이렇게 매개변수 목록을 허용하는 생성자는 없으므로 컨파일 오류가 뜸
		
		
		/* 인스턴스를 생성할 수 있는 다양한 방법을 제공하며, 
		 * 제공되는 생성자 외에는 인스턴스를 생성하는 방법을 제한한다. 
		 * 또한 여러개의 setter 메소드를 호출한 것과 같은 효과를 가질 수 있다. 
		 * (한번에 여러개의 필드 초기화)
		 * 
		 * 
		 * */
        
        
        
		
	}

}

 

 

public class User {

	
	/* 필드 */
	/* 관리해야할 속성 추상화 */
	private String id;
	private String pwd;
	private String name;
	
	private java.util.Date enrollDate; 
	// 가입일자
	// 자바.유틸에 수많은 클래스가 있다. 스캐너, 랜덤, 데이트 등
	
	
	
	/* 생성자의 작성위치
	 * 작성위치는 문법적으로 클래스 내부에 작성하면 되지만,
	 * 통상적으로 필드 선언부와 메소드 선언부 사이에 작성하는 것이 관례이다. */
	
	
	/* 생성자의 사용목적
	 * 1. 인스턴스 생성 시점에 수행할 명령이 있는 경우 사용한다.
	 * 2. 매개변수 있는 생성자의 경우 매개변수로 전달받은 값으로 
	 * 	  필드를 초기화하여 인스턴스를 생성할 목적으로 주로 사용한다. 
	 * 3. 작성한 생성자 외에는 인스턴스를 생성하는 방법을 제공하지 않는다는 의미를 가진다.
	 * 	  따라서, 인스턴스를 생성하는 방법을 제한하기 위한 용도로 
	 * 	  사용할 수도 있다. (초기값 전달 강제화, 즉 지정된 값을 모두 전달하지않으면 불가)
	 * 
	 *  */
	
	
	/* 생성자 작성 방법
	 * [표현식]
	 * 접근제한자 클래스명(매개변수) {
	 * 		인스턴스 생성 시점에 수행할 명령 기술(주로 필드 초기화)
	 *		this.필드명 = 매개변수;
	 * 	} 	
	 * // 설정자(setter) 여러개의 기능을 한번의 호출로 수행할 수 있다. 
	 * 
	 * 
	 * 
	 * 
	 *  */
	
	/* 기본 생성자(default constructor) */	
	//리턴값없음, 클래스명과 동일
	public User() {  //기본생성자, 아무런 매개값도 전달 받지않는다. 컴파일러 자동생성
		 System.out.println("User 클래스의 기본 생성자 호출함...");
	}
	
	
	
	
	/* 매개변수가 있는 생성자 */
	/* 초기화 할 필드가 여러개인 경우, 초기화하고 싶은 필드의 갯수별로 생성자를
	 * 여러 개(단, 타입은 상이해야함) 만들 수 있다. */
	public User(String id, String pwd, String name) {

		/* 매개변수 있는 생성자의 주 목적은 인스턴스 생성 시점에 
		 * 매개변수로 전달받은 값을 이용해서 필드를 초기화 한다. */
		this.id = id;
		this.pwd = pwd;
		this.name = name;
		
		System.out.println("User 클래스의 id, pwd, name을 초기화하는 생성자 호출함...");
		
	}
	//매개변수가 있는 생성자로 작성시 같은 생성자명 가능
	
	
	/* 모든 필드를 초기화 하는 생성자 */
	public User (String id, String pwd, String name, java.util.Date enrollDate) {
		
//		this.id = id;
//		this.pwd = pwd;			// 위와 중복되는 코드이다.
//		this.name = name;
		
		
		/* 중복코드를 다음과같이 작성해볼 수도 있다. */
		/* this()는 동일 클래스 내에 작성한 다른 생성자 메소드를 호출하는 구문이다.
		 * 괄호안에 매개변수의 타입, 갯수, 순서에 맞는 생성자를 호출하고 복귀한다. (메소드와 동일)
		 * this()는 *가장 첫 줄*에 선언해야 하며, 그렇지 않은 경우 Compile error가 발생한다. */
	
		this(id,pwd,name);	// 생성자 내에서 생성자 호출시 반드시 첫줄에 작성
		this.enrollDate = enrollDate;
		
		// 목적 :  전달받은 값을 필드 초기화에 쓰겠다.
		// 매개변수부를 어떻게 구성하느냐에 따라 여러개를 만들 수 있다. 단, 중복되지않는다는 가정하에
		// 매개변수의 타입, 갯수, 순서가 모두 달라야 한다.
		
		
		System.out.println("User 클래스의 모든 필드를 초기화 하는 생성자 호출함...");

	}
	
	
	/* 복사 생성자 */
	/* 이미 만들어진 동일한 타입의 인스턴스가 가지는 필드 값을 이용해서 
	 * 새로운 인스턴스 생성시 초기화 값으로 이용할 수 있다.
	 * 동일한 값을 가지지만 새롭게 할당 되는 인스턴스 이기 때문에 
	 * 서로 다른 주소값을 가지게 된다. (깊은 복사)
	 *  
	 *  
	 *  */

	public User (User otherUser) {
		
//		this.id = otherUser.id;
//		this.pwd = otherUser.pwd;
//		this.name = otherUser.name;
//		this.enrollDate = otherUser.enrollDate;
		this(otherUser.id, otherUser.pwd, otherUser.name, otherUser.enrollDate);
		// 이게 어떻게 대입이 되는지? 
		
		System.out.println("User 클래스의 복사 생성자 호출함...");
		
		
		/* this의 주소와 otherUser의 주소가 서로 다른지 확인 */
		System.out.println("this의 hashCode : " + this.hashCode());
		System.out.println("otherUser의 hashCode :" + otherUser.hashCode());
	
		
		
		
	}
	
	
	public String getInformation() {
		
		return "User [id = " + this.id + ", pwd = " + this.pwd + ", name = " + this.name + ", enrollDate = " + this.enrollDate;
		
	}
	
	
	
}

 

 

 

 

 

 

 

 

 

 

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

객체 배열  (0) 2022.01.03
클래스와 객체(3)  (0) 2021.12.30
배열, 클래스와 객체  (0) 2021.12.28
배열  (0) 2021.12.27
반복문  (0) 2021.12.24

 

 

 

 

배열 복사

- 얕은 복사와 깊은 복사

 

 

 

 

 

(1) 얕은 복사

객체의 주소 값만 가져와 참조형 변수에 저장하고 하나의 객체를 두 변수가 참조하는 것

 

 

 

 

 

 

 

(2) 깊은 복사

새로운 배열 객체를 생성하여 기존 배열의 데이터를 복사하는 것
  • (1) clone
  • (2) arraycopy

 

 

배열의 복사
public class Application1 {

	public static void main(String[] args) {

		
		/* 배열의 복사 */
		/* 배열의 복사에는 크게 두가지 종류가 있다.
		 * 1. 얕은 복사(shallow copy) : stack의 주소값만 복사
		 * 2. 깊은 복사(deep copy) : heap 의 배열에 저장된 값을 복사
		 *  */
		
		/* 얕은 복사는 stack에 저장되어 있는 배열의 주소값만 복사한다는 것이다.
		 * 따라서 두개의 레퍼런스 변수는 동일한 배열의 주소값을 가지고 있다.
		 * 하나의 레퍼런스 변수에 저장된 주소값을 가지고 배열의 내용을 수정(값변경)하게되면
		 * 다른 레퍼런스 변수로 배열에 접근했을때도 종일한 배열을 가리키고 있기 때문에
		 * 변경된 값이 반영되어 있다. */
		
		/* 얕은 복사를 확인할 원본배열 생성 */
		int[] originArr = {1,2,3,4,5};
		
		/* 원본배열을 복사 배열에 복사 */ 
		//originArr에 저장된 배열의 주소를 copyArr에도 저장
		int[] copyArr = originArr;
		
		/* hashCode를 출력해보면 두 개의 레퍼런스 변수는 동일한 주소를 가지고 있는것 확인가능 */
		System.out.println(originArr.hashCode());
		System.out.println(copyArr.hashCode());
		
		
		/* 원본 배열과 복사본 배열의 값 출력 */
		for (int i =0; i < originArr.length; i ++) {
			 System.out.print(originArr[i] + " ");
		}
		
		System.out.println();
		
		for (int i =0; i < copyArr.length; i ++) {
			 System.out.print(copyArr[i] + " ");
		
		}
		
		System.out.println();

		/* 두개 배열은 동일한 값을 가지고 있다. */
		
		/* 복사본 배열에 값을 변경한 뒤 다시 같은 값을 확인해보면
		 * 복사본 배열만 변경했음에도 원본 배열에 영향을 미침을 알 수 있다.
		 * 서로 같은 배열을 가리키고 있기 때문이다.(현재존재하고 있는 배열은 하나뿐이다.) */
		 
		copyArr[0] = 99;
		
		for (int i =0; i < originArr.length; i ++) {
			 System.out.print(originArr[i] + " ");
		}
		
		System.out.println();
		
		for (int i =0; i < copyArr.length; i ++) {
			 System.out.print(copyArr[i] + " ");
		
		}
		
	}

}

// 콘솔창 출력
//		123961122
//		123961122
//		1 2 3 4 5 
//		1 2 3 4 5 
//		99 2 3 4 5 
//		99 2 3 4 5

 

 

얕은 복사
public class Appication2 {

	public static void main(String[] args) {

		/* 얕은 복사의 활용 */
		/* 얕은 복사를 활용하는 것은 주로 메소드 호출시 인자로 사용하는 경우의
		 * 리턴값으로 동일한 배열을 리턴해주고 싶은 경우 사용한다.
		 *  */
		
		String[] names = {"유관순", "홍길동", "신사임당"};
		
		System.out.println("name의 hashCode : " + names.hashCode());
	
		/* hashCode가 동일한 것을 확인할 수 있다.
		 * 이처럼 다른 메소드에서 동일한 배열(객체)를 사용하도록 
		 * 하고 싶은 경우 얕은 복사를 이용한다. */
		
		/* 인자와 매개변수로 활용 */
		print(names);
		
		/* 리턴값으로 활용 */
		String[] animals = getAnimals();
		
		/* 리턴받은 결과 값도 얕은 복사인 것을 알 수 있다. */
		System.out.println("리턴받은 animals의 hashCode : " + animals.hashCode());
		
	}

	
	
	/* 배열을 매개변수로 받아 모든 인덱스에 저장 되어 있는 값을 
	 * 출력하는 기능을 제공하는 메소드 */
	
	public static void print(String[] sarr) {
		
		/* 전달 받은 배열의 hashCode 출력 */
		System.out.println("sarr의 hashCode : " + sarr.hashCode());
		
		
		/* 전달 받은 배열의 값 출력 */
		for (int i = 0; i <sarr.length; i++) {
			System.out.print(sarr[i] + " ");
		}
		
		System.out.println();
		
	}
	
	
	/* 동물 종류로 생성 된 문자열 배열을 반환하는 메소드 */
	public static String[] getAnimals() {
		
		
		String[] animals = new String[] {"낙타", "호랑이", "나무늘보"};
		
		System.out.println("새로만든 animals의 hashCode : " + animals.hashCode());
		
		return animals;
		
		
		
		
		
	}
	
	
//	name의 hashCode : 123961122
//	sarr의 hashCode : 123961122
//	유관순 홍길동 신사임당 
//	새로만든 animals의 hashCode : 942731712
//	리턴받은 animals의 hashCode : 942731712
	
	
	
}

 

 

 

깊은 복사
import java.util.Arrays;

public class Application3 {

	public static void main(String[] args) {

		/* 깊은 복사는 heap영역에 생성 된 배열이 가지고 있는 값을
		 * 또 다른 배열에 복사 해 놓은 것이다.
		 * 서로 같은 값을 가지고 있지만, 두 배열은 서로 다른 배열이기에
		 * 하나의 배열을 변경하더라도 다른 배열에는 영향을 주지 않는다.
		 *  */
		
		/* 깊은 복사를 하는 방법은 4가지가 있다.
		 * 1. for문을 이용한 동일한 인덱스의 값 복사
		 * 2. Object의 clone ()을 이용한 값 복사
		 * 3. System의 arraycopy() 를 이용한 복사
		 * 4. Arrays의 copyOf()를 이용한 복사
		 * 
		 * 이 중 가장 높은 성능을 보이는 것은 순수배열의 복사를 위해 만들어진 
		 * arraycopy() 메소드이며 가장 많이 사용되는 방식은 좀 더 유연한 방식인
		 * copyOf () 메소드이다.
		 * 
		 *  clone()은 이전 배열과 같은 배열밖에 만들 수 없다는 특징을 가지고,
		 *  그 외 3가지 방법은 복사하는 배열의 길이를 마음대로 조절할 수 있다는 특징을 
		 *  가지고 있다.
		 *  
		 *  */
		
		
		
		/* 원본 배열 할당 및 초기화 */
		int[] originArr = new int[] {1,2,3,4,5};
		
		/* 별도의 출력 메소드로 호출해서 확인 */
		print(originArr);
		
		/* 1. for문을 이용한 동일한 인덱스 값 복사 */
		int[] copyArr1 = new int[10];
		
		for(int i = 0; i < originArr.length; i++) {
			copyArr1[i] = originArr[i];
		}
		
		/* 원본 배열과 복사한 값은 같은 값을 가지고 
		 * 나머지 인덱스는 다른값, 다른 주소를 가지고 있다. */
         
		print(copyArr1);
		
	
		
		
		
		/* 2. Object의 clone()을 이용한 복사 */
		int[] copyArr2 = originArr.clone();
		
		/* 동일한 길이, 동일한 값을 가지는 배열이 생성되어 복사되며,
		 * 다른 주소를 가지고 있다. */
		print(copyArr2);
		
		
		
		
		/* 3. System의 arraycopy()를 이용한 복사 */
		int[] copyArr3 = new int[10];
		
		//원본배열, 복사를 시작할 인덱스, 복사본 배열, 복사를 시작할 인덱스, 복사할 길이의 의미
		//System.arraycopy(src,srcPos,dest,destPos,length);
		System.arraycopy(originArr,0,copyArr3,3,originArr.length);
		
		/* 복사한 만큼의 값은 같지만 길이도 다르고 주소도 다르다. */
		print(copyArr3);
		
		
		
		
		/* 4. Arrays의 copyOf()를 이용한 복사 */
		/* 시작 인덱스부터 원하는 길이만큼만 복사해서 사용가능하다. */
		int[] copyArr4 = Arrays.copyOf(originArr,7);
		//뒤의 숫자는 복사할 갯수
		
		/* 복사한 만큼의 값은 같지만 길이도 다르고 주소도 다르다. */
		print(copyArr4);
		
		
		
	}
	
	/* 배열을 매개변수로 전달 받아 모든 인덱스에 저장되어있는 
	 * 값을 출력하는 기능을 제공하는 메소드 */
	
	public static void print(int[] iarr) {
		
		/* 전달 받은 배열의 hashCode 출력 */
		System.out.println("iarr의 hashCode : " + iarr.hashCode());
		
		/* 전달 받은 배열의 값 출력 */
		for (int i = 0; i < iarr.length; i++) {
			System.out.print(iarr[i] + " ");
			
		}
		System.out.println();
	}
	
	
	
	
	
	
//	콘솔
//	iarr의 hashCode : 123961122
//	1 2 3 4 5 
//	iarr의 hashCode : 942731712
//	1 2 3 4 5 0 0 0 0 0 
//	iarr의 hashCode : 971848845
//	1 2 3 4 5 
//	iarr의 hashCode : 1910163204
//	0 0 0 1 2 3 4 5 0 0 
//	iarr의 hashCode : 305623748
//	1 2 3 4 5 0 0 

	

}

 

 

 

향상된 for문
public class Application4 {

	
	public static void main(String[] args) {

		/* 두 개의 같은 값을 가지는 배열을 만든다. */
		int[] arr1 = {1,2,3,4,5};
		int[] arr2 = arr1.clone();
		
		/* 각 배열의 인덱스에 10씩 누적 증가 시킴 */
		for(int i = 0; i < arr1.length; i++) {
			arr1[i] += 10;
			
		}
		
		/* 반복문을 이용한 값 출력 */
		for(int i = 0; i < arr1.length; i++) {
			System.out.print(arr1[i] + " ");	
			//정상적으로 10씩 증가된 값을 가지고 있다.
		}
		
		System.out.println();
		
		
		
		
		
		/* 향상된 for문 : jdk 1.5버전부터 추가
		 * 배열 인덱스에 하나씩 차례로 접근해서 
		 * 담긴 값을 임시로 사용할 변수에 담고 반복문을 실행한다. */
		
		for(int i : arr2) {
			System.out.print(i + " ");
			// i는 임시변수
			// 조건이 인덱스를 가지고있을때 사용가능(나중에 컬렉션+)
		}
		
		
		/* 향상된 for문을 이용해 값 증가 시키기 */
		for (int i : arr2) {
			i += 10;
			
		}
		
		/* 증가 되었는지 출력 확인 */
		for(int i : arr2) {
			System.out.print(i + " ");
			
			// 증가되지 않고 있다. 인덱스에 접근해서 값을 변경한게 아니고 
			// 꺼낸 값을 복사해서 쓴것이다.
		}
		
		/* 주의: 향상된 for문은 배열 인덱스에 차례로 접근할때는 편하게 사용할 수 있지만 
		 * 값을 변경할 수는 없다. 대신 변경하는 것이 아닌 사용에 목적이 있다면 
		 * 조금더 편하게 사용할 수 있다.  */
		
		
		/* 향상된 for문의 i는 임의의 공간을 만든것이다. 원하는 복사배열을 오른쪽에선언
		 * i가 순차적으로 접근해서 임시로 사용할 변수를 복사 해서 담음
		 * 다만 증감이나 변경은 불가능하고 그저 복사해오는 것만 가능하다. */
		
		
	}

}

 

 

 

 

 

 

 

 

 

 

 

정렬

값을 서로 변경하기
  • 변수는 하나의 값만 저장 가능 하므로 값을 대입하면 이전의 값은 소멸된다는 단점이 있다.
  • 때문에 임시 변수를 하나 만든 후 옮겨놓아 기존의 값을 따로 보관하는 대입 작업이 필요하다.
  • 이러한 추가된 임시변수에 옮겨 보관을 통해 값을 서로 변경할 수 있음

 

public class Application1 {

	public static void main(String[] args) {

		/* 변수의 두 값 변경하기 */
		int num1 = 10;
		int num2 = 20;
		
		
		/* 변경 전 값 출력 */
		System.out.println("num1 : " + num1);
		System.out.println("num2 : " + num2);

		
		
		/* 두 변수의 값을 바꾸기 위해 다른 변수 한개가 더 필요하다. */
		int temp;
		temp = num1; // temp에 10을 보관
		num1 = num2; // num1위에 덮어씀
		num2 = temp; // 아까 옮겨둔 temp 속 10을 num2에 덮어씀
		
		
		
		/* 변경 후 값 출력 */
		System.out.println("num1 : " + num1);
		System.out.println("num2 : " + num2);
		
		
		
		/* 배열의 인덱스에 있는 값도 서로 변경할 수 있다. */
		int[] arr = {2,1,3};
		
		int temp2 = arr[0]; 	//2를 임시변수에 저장
		arr[0] = arr[1]; 		//1번 인덱스를 덮어씀 {1,1,3}인상황
		arr[1] = temp2;			//다시 두번째 자리에 2를 덮어줌
		
		// 저장된 값만 확인하므로 향상된 for문 사용
		for(int num : arr) {
			System.out.print(num + " ");
			
		}
		
		
	}
	

}

//num1 : 10
//num2 : 20
//num1 : 20
//num2 : 10
//1 2 3

 

 

 

순차정렬
  • 배열의 처음과 끝을 탐색 하면서 차순대로 정렬하는 가장 기초적인 정렬 알고리즘
  • 순차정렬을 위한 값끼리의 대소 비교 필요

초록색이 각 회차의 기준

 

 

import java.util.Arrays;

public class Application2 {

	public static void main(String[] args) {

		/* 초기 배열 선언 및 초기화 */
		int[] iarr = {2,5,4,6,1,3};
		
		/* copy 배열 */
		int[] copy = iarr.clone();
		Arrays.sort(copy);
		System.out.println("copy : " + Arrays.toString(copy));
		
		// 0번째가 아닌 1번째 인덱스부터 비교, 1번~ 마지막까지의 반복
		
		
		/* 인덱스를 한개씩 증가시키는 반복문
		 * 첫 번째 인덱스는 비교할 필요 없어서 1번 인덱스부터 비교 시작 */
		
		for (int i = 1; i < iarr.length; i++) {
			
			
		/* 인덱스가 증가할때마다 처음부터 해당 인덱스 -1까지의 값을 비교하는 반복문 */
			for (int j = 0; j < i; j++) {
				/* 오름 차순 정렬을 위한 처리
				 * 내림차순 부등호 방향을 반대로 처리
				 * */
			
			if (iarr[i] < iarr[j]) { 
				/* 오름차순 기준으로 j가 커야 값을 바꿈, 내림차순이면 반대 */
				/* 값 위치 변경 */
				int temp;
				temp = iarr[i];
				iarr[i] = iarr[j];
				iarr[j] = temp;
			}
			
			}
		
		
		}
		
		/* 결과 출력 */
		for(int i =0; i < iarr.length; i++) {
			System.out.print(iarr[i] + " ");
			
		}
		

	}

}


//copy : [1, 2, 3, 4, 5, 6]
//1 2 3 4 5 6

 

 

 

 

 

 

클래스

클래스는 서로 다른 자료형의 데이터들을 사용자(개발자) 정의로 하나로 묶어 새로운 타입을 정의
  • 배열과 달리 다른 자료형들의 값을 하나로 묶을 수 있음\
  • 클래스 : 사용자정의 자료형
  • 지금까지 배운 저장 공간으로는 하나의 값을 하나의 공간에 담을 수 있는 변수, 같은타입끼리 모인 조건하에 원하는 만큼 공간을 묶어서 사용하는 배열이 있었다. 
  • 클래스라는 것은 결국 타입, 즉 자료형이다. 서로 다른 자료형의 데이터를 하나의 정의로 사용할 수 있게 한다.
  • 사용자 정의 자료형을 클래스를 통해 만들 수 있다. 
  • 다른 곳에서 클래스의 필드에 접근하기 위해 ‘.'(참조연산자)의 활용

 

 

public class Application {

	public static void main(String[] args) {

		/* 지금까지는 자바에서 제공되는 자료들을 취급하는 자료형에 대해 학습했다. */
		/* 이제 조금 더 복잡한 자료들을 취급할 수 있는 방법을 생각해보자
		 * 회원 정보를 관리하기 위해 회원의 여러정보
		 * (아이디, 비밀번호, 이름, 나이, 성별, 취미)
		 * 를 취급하여 관리하려고 한다.
		 *  */
		
		String id = "user01";
		String pwd = "pass01";
		String name = "홍길동";
		int age = 20;
		char gender = '남';
		String[] hobby = {"축구", "볼링", "테니스"};
		
		System.out.println("id : " + id);
		System.out.println("pwd : " + pwd);
		System.out.println("name : " + name);
		System.out.println("age : " + age);
		System.out.println("gender : " + gender);
		System.out.println("hobby : ");
		for(int i = 0; i < hobby.length; i++) {
			System.out.println(hobby[i] + " ");			
		}
		System.out.println();
		
		// method(id, pwd, name, age, gender, hobby)
		/* 이렇게 각각의 변수로 관리하게 되면 여러가지 단점이 있다.
		 * 1. 변수명을 다 관리해야 하는 어려움이 생긴다.
		 * 2. 모든 회원 정보를 인자로 메소드 호출시 전달해야하면 너무 많은 값들을
		 * 	  인자로 전달해야하기에 한 눈에 안들어 온다. 
		 * 3. 리턴은 1개의 값만 가능하기 때문에 회원 정보를 묶어서 리턴 값으로 
		 * 	  사용할 수 없다.
		 * 
		 * => 그래서 서로 다른 자료형의 데이터를 사용자(개발자) 정의로 하나로 묶어서
		 * 새로운 타입을 정의할 수 있는 방법을 제공한다.
		 * 	  Member(회원정보) 라고하는 새로운 타입을 정의해보자.
		 * */
		
		
		/* 사용자 정의 자료형 사용하기 */
		/* 1. 변수선언 및 객체생성 */
		/* 자료형 변수명 = new 클래스명(); 
		 * <= 지금까지 사용한 이 구문은 객체(instance)를 생성하는 구문이다.
		 * 객체를 생성하게 되면 클래스에 정의한 필드와 메소드 대로 객체(instance)가 생성된다.
		 * 아이디, 비밀번호, 이름, 나이, 성별, 취미를 연속된메모리 주소에서 사용하도록
		 * heap에 공간을 만들었다.
		 * */
		
		Member member = new Member();
		// member는 레퍼런스 변수, 참조변수
		// new를 사용하면 heap영역에 객체가 생성되어 저장되며 참조변수를 통해 
		// 그 주소를 참조한다.
		
		/* 이렇게 객체를 생성하고 나면 서로 다른 자료형들을 하나의 member라는 이름으로
		 * 관리할 수 있도록 공간을 생성한 것이다.
		 * heap에 생성되기 때문에 jvm기본값으로 초기화 된다. ex: int 일시 0 */
		/* 필드에 접근하기 위해서는 레퍼런스명.필드명 으로 접근한다.
		 * '.'은 참조 연산자라고 하는데, 레퍼런스변수가 참조하고 있는 
		 * 주소로 접근한다는 의미를 가진다.
		 * 각 공간을 필드명으로 접근한다. (배열은 인덱스로 접근, 객체는 필드명으로 접근)
		 *  */
		
		System.out.println("member.id : " + member.id);
		System.out.println("member.pwd : " + member.pwd);
		System.out.println("member.name : " + member.name);
		System.out.println("member.age : " + member.age);
		System.out.println("member.gender : " + member.gender);
		System.out.println("member.hobby : " + member.hobby);
		
//콘솔출력
//		id : user01
//		pwd : pass01
//		name : 홍길동
//		age : 20
//		gender : 남
//		hobby : 
//		축구 
//		볼링 
//		테니스 
//
//		member.id : null
//		member.pwd : null
//		member.name : null
//		member.age : 0
//		member.gender : 

		
		/* 2. 필드에 접근해서 변수 사용하듯 사용할 수 있다. */
		member.id = "user01";
		member.pwd = "pass01";
		member.name ="홍길동";
		member.age = 20;
		member.gender = '남';
		member.hobby = new String[] {"축구", "볼링", "테니스"};

		
		
		/* 값이 변경되었는지 다시 확인 */
		System.out.println("member.id : " + member.id);
		System.out.println("member.pwd : " + member.pwd);
		System.out.println("member.name : " + member.name);
		System.out.println("member.age : " + member.age);
		System.out.println("member.gender : " + member.gender);
		// System.out.println("member.hobby : " + member.hobby);	
		// member.hobby : [Ljava.lang.String;@3830f1c0   
		// 위와 같이 출력시 주소값 출력
		
		System.out.print("member.hobby : " ); 
		for (int i = 0; i < member.hobby.length; i++) {
			System.out.print(member.hobby[i] + " ");
		}
		
		// 콘솔
		// member.hobby : 축구 볼링 테니스 
		
		
	}


}

<클래스>

public class Member {

	/* 지금까지는 클래스 내부에 메소드만 작성해보았지만
	 * 클래스 내부에는 메소드를 작성하지 ㅇ낳고 바로 변수를 선언할 수도 있다.
	 * 이것을 전역변수(필드 == 인스턴스 변수(객체) == 속성)라고 부른다.
	 *  */

	String id;
	String pwd;
	String name;
	int age;
	char gender;
	String[] hobby;
	// 위치가 클래스 내부, 메소드 외부에 있다.
	// 왜 속성인가? 클래스를 회원정보로 치면 
	// 위의 변수들은 회원정보가 가진 속성으로도 볼 수 있기 때문
	// 클래스의 전역변수로서 선언된것
		
		
		

	

}

 

 

 

 

 

 

필드에 직접 접근 시 문제점1. 
public class Application {

	public static void main(String[] args) {
		
		/* 필드에 바로 접근할 때 발생할 수 있는 문제점1
		 * => 필드에 올바르지 않은 값이 들어가도 통제가 불가능하다.
		 *  */
		
		
		

		/* 1번 몬스터 생성 */
		Monster monster1 = new Monster();
		
		/* 몬스터의 이름과 체력 변경 */
		monster1.name = "두치";
		monster1.hp = 200;
		
		/* 몬스터 정보 출력 */
		System.out.println("monster1 name : " + monster1.name);
		System.out.println("monster1 hp : " + monster1.hp);
		
		
		/* 2번 몬스터 생성 */
		Monster monster2 = new Monster();
		
		/* 몬스터의 이름과 체력변경 */
		monster2.name = "뿌꾸";
		monster2.hp = -200;		//monster2의 체력을 음수로 지정하였다.
		
		/* 몬스터 정보출력 */
		System.out.println("monster2 name : "  + monster2.name);
		System.out.println("monster2 hp : " + monster2.hp);
		
		
// 콘솔출력		
//		monster1 name : 두치
//		monster1 hp : 200
//		monster2 name : 뿌꾸
//		monster2 hp : -200
		
		
		
		
		
		
		
		/* =============================================== */
		/* sepHp를 만들고 난 뒤 테스트 */
		
		/* 3번 몬스터 생성 */
		Monster monster3 = new Monster();
		monster3.name = "드라큘라";
		monster3.setHp(200);
		
		System.out.println("monster3 name : " + monster3.name);
		System.out.println("monster3 hp : " + monster3.hp);
		
		
		
		/* 4번 몬스터 생성 */
		Monster monster4 = new Monster();
		monster4.name = "프랑켄슈타인";
		monster4.setHp(-1000);
		
		System.out.println("monster4 name : " + monster4.name);
		System.out.println("monster4 hp : " + monster4.hp);
		
		
// 콘솔출력
//		양수 값이 입력되어 몬스터의 체력을 입력한 값으로 변경합니다.
//		monster3 name : 드라큘라
//		monster3 hp : 200
//		0보다 작거나 같은 값이 입력되어 몬스터의 체력을 0으로 변경합니다.
//		monster4 name : 프랑켄슈타인
//		monster4 hp : 0
		

		
		
		/* 잘못된 값을 검증하여 필드 값을 수정하는 메소드 =setHp()를 작성하여
		 * 위에서 발생한 문제를 해결하였다. = */
		
		
	}

}

 

<클래스> 

public class Monster {

	/* 필드로 몬스터 이름과 체력을 저장할 공간을 선언한다. */
	String name; 	// 몬스터 이름
	int hp; 		// 몬스터 체력
	
	/* hp에 음수가 저장되는 것을 방지하고자 
	 * hp가 양수인 경우에만 입력하는 hp 로 변경하고,
	 * 0보다 작은 경우 0으로 변결할 수 있도록 기능을 작성한다. 
	 * => 메소드를 작성한다. (= 기능작성)
	 *  */
	
	
	
	/**<pre>
	 * 매개변수로 전달받은 정수를 이용해 hp의 값을 변경해주는 메소드
	 * 단, 매개변수로 전달받은 값이 양수인 경우에만 전달받은 값으로 변경하고,
	 * 0보다 작거나 같은 경우에는 0으로 변경한다.
	 * </pre>
	 * @param hp
	 * */
	
	public void setHp(int hp) {
		
		if (hp > 0) {
			/* this란? this는 인스턴스가 생성되었을 때 자신의 주소를 저장하는 레퍼런스 
			 * 변수이다. 지역변수와 전역변수의 이름이 동일한경우 지역변수를 우선적으로 접근
			 * 하기 때문에 전역변수에 접근하기 위해서 this. 를 명시해야 한다. 
			 * == 자기자신의 주소
			 * */
			System.out.println("양수 값이 입력되어 몬스터의 체력을 입력한 값으로 변경합니다.");
			this.hp = hp; 
			//지역변수가 우선순위가 높기때문에 this를 지우면 if 내 hp를 의미하게 된다.
			// this를 붙이면 필드에있는 전역변수라는 뜻이다.
			
		} else {
			System.out.println("0보다 작거나 같은 값이 입력되어 몬스터의 체력을 0으로 변경합니다.");
			this.hp = 0;
		}
		
	}
	
	
	
	
}

 

 

 

 

필드에 직접 접근 시 문제점2. 
public class Application {

	public static void main(String[] args) {
	


		/* 필드에 바로 접근할때 발생할 수 있는 문제점2 
		 * 
		 * */
		
		/* monster 3 마리 추가 */
//		Monster monster1 = new Monster();
//		monster1.name = "드라큘라";
//		monster1.hp = 200;
//		
//		Monster monster2 = new Monster();
//		monster2.name = "프랑켄슈타인";
//		monster2.hp = 300;
//		
//		Monster monster3 = new Monster();
//		monster3.name = "드라큘라";
//		monster3.hp = 400;
//		
//
//	 System.out.println("monster1 name : " + monster1.name);
//	 System.out.println("monster1 hp : " + monster1.hp);
//	 System.out.println("monster2 name : " + monster2.name);
//	 System.out.println("monster2 hp : " + monster2.hp);
//	 System.out.println("monster3 name : " + monster3.name);
//	 System.out.println("monster3 hp : " + monster3.hp);
	 
		
		
		
		
		/* name -> kinds 로 변경했기 때문에 직접 name 필드에 접근하는 
		 * 코드는 전부 컴파일 에러를 발생시킨다. 즉, Monster 클래스의 일부를 
		 * 수정한 것이데 사용하는 곳에서는 전부 함께 수정을 해야하는 부담이 생긴다.
		 * 이것은 유지보수에 악영향을 미친다. 
		 * */
		
		
		
		
		
		
	
	}
}

 

<클래스>

public class Monster {


		//  사용자 정의 자료형 = 클래스
		
//		String name;
//		int hp;
		
	/* 버전이 변경되면서 몬스터의 이름이 아니라 종류에 
	 * 해당하는 내용을 저장하도록 필드가 변경되었다. */
		String kinds;
		int hp;

	

}

 

 

 

 

필드에 직접 접근 시 문제점3. 
public class Application3 {

	public static void main(String[] args) {


		/* 앞에서 작성한 두가지 문제점을 해결해보자 */
		/* 필드에 직접 접근하지 않고 메소드를 이용하여 간접 접근하도록 하면
		 * 올바르지 않은 범위의 값으로 변경되는 것도 막을 수 있고
		 * 필드 값의 변경이 발생하더라도 사용자는 코드를 변경하지 않아도 된다.
		 *  */
		
		Monster monster1 = new Monster();
		monster1.setInfo("드라큘라");
		monster1.setHp(100);
		
		Monster monster2 = new Monster();
		monster2.setInfo("프랑켄슈타인");
		monster2.setHp(200);
		
		Monster monster3 = new Monster();
		monster3.setInfo("미이라");
		monster3.setHp(300);
		
		System.out.println(monster1.getInfo());
		System.out.println(monster2.getInfo());
		System.out.println(monster3.getInfo());
		
//		몬스터의 이름은 드라큘라이고, 체력은 100입니다.
//		몬스터의 이름은 프랑켄슈타인이고, 체력은 200입니다.
//		몬스터의 이름은 미이라이고, 체력은 300입니다.
		
        
        /* ----------------------------------------------- */
		
		
		/* 하지만 여전히 필드에 직접 접근할 수 있다. */
		monster3.kinds = "두치";
		monster3.hp  = -500;
		
		System.out.println("monster3 kinds : " + monster3.kinds);
		System.out.println("monster3 hp" + monster3.hp);
		
        
//		몬스터의 이름은 드라큘라이고, 체력은 100입니다.
//		몬스터의 이름은 프랑켄슈타인이고, 체력은 200입니다.
//		몬스터의 이름은 미이라이고, 체력은 300입니다.
//		monster3 kinds : 두치
//		monster3 hp-500
        
        
        
        
	}

}

 

<클래스>

public class Monster {

	
	
	//String name;
	String kinds;
	int hp;
	
	
	
	/**<pre>
	 * 몬스터의 정보를 입력 받아서 몬스터의 이름에 
	 * 해당하는 필드값을 변경해주는 메소드
	 * </pre>
	 * @param name 몬스터의 이름입력
	 * 
	 *   */
	public void setInfo (String info) {
		
		/* 수정 전 */
		//this.name = name;	//필드에 대입	
		
		/* 수정 후 */
		this.kinds = info;	
		
		
	}
	
	
	
	
	
	
	/**<pre>
	 * 몬스터의 체력정보를 입력받아서 몬스터의 체력에
	 * 해당하는 필드값을 변경해주는 메소드
	 * </pre>
	 * @param hp 몬스터의 체력입력
	 * 
	 *   */
	
	public void setHp (int hp) {

		if(hp > 0) {
			this.hp = hp;
		} else {
			this.hp = 0;
		}
		
	}
	

	
	
	
	/**<pre>
	 * 몬스터의 정보를 입력받아서 모든 필드의 내용을 
	 * 문자열로 되돌려주는 메소드
	 * </pre>
	 * @return 모든 필드의 정보를 문자열 합치기하여 반환
	 * 
	 *   */
	
	public String getInfo() {
		
		
		/* 수정 전 */
		// return "몬스터의 이름은 " + this.name + "이고, 체력은 " + this.hp + "입니다.";
		
		/* 수정 후 */
		return "몬스터의 이름은 " + this.kinds + "이고, 체력은 " + this.hp + "입니다.";
		
	}
	
	
	
	/* name -> kinds로 변경할 경우 setInfo, getInfo 메소드는 변경해주어야 하지만
	 * 사용자(클라이언트)의 호출 코드는 변경하지 않아도 된다.
	 *  */
	
}

 

 

 

 

 

 

 

 

 

 

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

클래스와 객체(3)  (0) 2021.12.30
클래스와 객체(2)  (0) 2021.12.29
배열  (0) 2021.12.27
반복문  (0) 2021.12.24
스캐너와 조건문  (0) 2021.12.23

 

배열

같은 자료형의 변수들을 하나의 묶음으로 다루는 것
  • 배열은 저장된 값 마다 인덱스 번호가 부여됨. (0부터 시작)
  • 이름은 하나지만 저장공간은 여러개

 

 

 

 

 

배열 선언과 할당

배열 선언
자료형[ ] 배열명;
자료형 배열명[ ];

 

 

 

 

배열 할당
배열명 = new 자료형[배열크기];

 

 

 

배열 선언과 할당
자료형[ ] 배열명 = new 자료형[배열크기];
자료형 배열명[ ] = new 자료형[배열크기];

 

 

 

 

배열 초기화
  • index가 순차적으로 증가함에 따라 초기화 할 리터럴 값이 규칙적이라면 반복문을 통해 배열 초기화 가능

 

  • 인덱스를 이용한 초기화

 

 

 

  • for문을 이용한 초기화

 

 

 

 

  • 선언과 동시에 초기화

 

 

 

 

 

 

배열 저장구조
  • 배열은 참조 변수로 Heap영역에 할당되며 배열 공간의 주소를 저장
  • 배열 공간의 주소를 이용해 인덱스를 참조하는 방식으로 값 처리
  • int[ ] arr = new int[4];

 

  1. 숙지할 포인트 : 참조변수, 참조변수는 배열의 주소를 저장, 인덱스를 기준으로 참조
  2. 주소값 : heap영역의 주소를 저장

 

 

 

public class Application1 {

	
	public static void main(String[] args) {
		
		
		/* 배열이란?
		 * 동일한 자료형의 묶음(연속된 메모리 공간에 값을 저장하고 사용하기 위한 용도) 이다.
		 * 배열은 heap영역에 new 연산자를 이용하여 할당한다. 
		 * */
		
		/* 배열의 사용 이유
		 * 만약 배열을 사용하지 않는다면 변수를 여러개 사용해야 한다.
		 * 1. 연속된 메모리 공간으로 관리할 수 없다. (모든 변수의 이름을 사용자가 관리해야한다.)
		 * 2. 반복문을 이용한 연속 처리가 불가능하다.  
		 * */
		
		/* 변수 5개에 값을 저장한다.
		 * 이 때 사용자(개발자)는 변수의 이름을 모두 알아야 한다.
		 *  */
		
		int num1 = 10;
		int num2 = 20;
		int num3 = 30;
		int num4 = 40;
		int num5 = 50;
		
		/* 변수의 합을 저장하기 위한 용도의 변수 */
		int sum = 0;
		
		/* 반복문을 사용하지 못하고 일일히 더해줘야 한다. */
		sum += num1;
		sum += num2;
		sum += num3;
		sum += num4;
		sum += num5;
		
		System.out.println("sum : " + sum);
		
		/* 배열을 이용해보자 */
		/* 배열의 선언 및 할당 */
		int[] arr = new int[5];
		//new  연산자 + 내가 할 당하고싶은 크기
		
		/* 하나의 이름으로 관리되는 연속된 메모리 공간이고, 
            * 공간마다 찾아갈 수 있는 번호(인덱스)를 이용해 접근한다. 
		 * 연속된 패턴이 있다면 반복문을 이용할 수 있다.*/
		arr[0] = 10;
		arr[1] = 20;
		arr[2] = 30;
		arr[3] = 40;
		arr[4] = 50;
		
		/* 값을 대입할 때도 반복문을 사용할 수 있다. */
		for(int i = 0, value = 0; i < arr.length; i++) {
		//초기값을 반드시 하나만 지정할 필요는 없다. 콤마로 나열 가능
		//콤마는 같은 타입선언을 의미한다.
		//배열이름.length = 배열이 가지고있는 길이를 알려준다. 
			arr[i] = value += 10;
			
		}
		
	
		/* 배열의 값을 누적해서 담을 변수 선언 */
		int sum2 = 0;
		
		/* 일반적인 변수처럼 사용할 수 있다. */
		sum2 += arr[0];
		sum2 += arr[1];
		sum2 += arr[2];
		sum2 += arr[3];
		sum2 += arr[4];
		
		System.out.println("sum2 : " + sum2);
		
		/* 배열의 값을 반복문을 이용해서 누적하여 담을 변수 */
		int sum3 = 0;
		
		for(int i = 0; i < arr.length; i++) {
			sum3 += arr[i];
			
		}
		System.out.println("sum3 : " + sum3);
		
		
	}
	

}


//콘솔창
//sum : 150
//sum2 : 150
//sum3 : 150

 

 

import java.util.Scanner;

public class Application2 {

	public static void main(String[] args) {


		/* 배열의 사용 방법 */
		
		/* 배열의 선언 */
		/* 자료형[] 변수명;
		 * 자료형 변수명[]; 두가지로 선언할 수 있다.
		 * 
		 *  */
		
		/* 선언이란 : stack에 배열의 주소를 보관할 수 있는 공간을 만드는 것이다. 
		 * 즉, 실제값이 담기는 공간이 아니라 '주소'가 담기는 공간인 것*/
		
		int[] iarr;
		char carr[];
		
		/* 선언한 레퍼런스 변수에 배열을 할당하여 대입할 수 있다.
		 * new 연산자는 heap 영역에 공간을 할당하고 발생한 주소값을 반환하는 연산자이다.
		 * 발생한 주소를 레퍼런스 변수(참조할 변수)에 저장하고 이것을 참조하여 사용하기 때문에 참조자료형(reference type) 
		 * 이라고 한다. 즉, 힙영역에 주소값을 가지고있는 변수 */
		
		/* 배열을 할당할 시에는 반드시 배열의 크기를 지정해주어야 한다. */
		//iarr = new int[];
		//크기 기입이 누락됐다면 컴파일 에러가 뜬다.
		iarr = new int[5];
		carr = new char[10];
		// 변수 = new 타입[크기];
		
		
		/* 위의 선언과 할당을 동시에 할 수도 있다. */
		int[] iarr2 = new int[5];
		char carr2[] = new char[10];
		//타입[] 변수 = new 타입[];
		
		
		/* heap 메모리는 이름으로 접근하는 것이 아닌 주소로 접근하는 영역이다.
		 * stack에 저장된 주소로 heap에 할당 된 배열을 찾아갈 수 있다. */
		System.out.println("iarr : " + iarr);
		System.out.println("carr : " + carr);

		//콘솔
//		iarr : [I@7637f22
//		carr : [C@3830f1c0
		
		
		/* hashcode() : 일반적으로 객체의 주소값을 10진수로 변환하여 생성한 객체의 고유한 정수값을 반환한다.
		 * 동일 객체인지 비교할 때 사용할 목적으로 쓰여지며, 동등객체를 동일객체(주소가 같은지) 
		 * 취급하기 위한 용도로 overriding 에서 사용한다. 
		 * 이 부분은 뒤에서 다루게 되니, 그 전까지는 쉽게 주소값이라고 생각하고 사용하면 된다.
		 *  */
		
		System.out.println("iarr의 hashcode : " + iarr.hashCode());
		System.out.println("iarr의 hashcode : " + carr.hashCode());
		//해쉬코드 : 배열 주소를 10진수로 변환하는 메소드라고 생각할것 
//		iarr의 hashcode : 123961122	//콘솔
//		iarr의 hashcode : 942731712 //콘솔
		
		
		/* 배열의 길이를 알 수 있는 기능을 필드로 제공하고 있다.
		 * 필드 또한 뒤에서 다루게 될 것이다. (일종의 변수)
		 * 참고로 String의 문자열 길이는 메소드로 제공하고 있기 때문에 length로 사용한다. */
		
		System.out.println("iarr2의 길이 : " + iarr2.length);
		System.out.println("iarr2의 길이 : " + carr2.length);
		
//		iarr2의 길이 : 5
//		iarr2의 길이 : 10
		// 혼동주의
		// 스트링에서 메소드로 제공했던것은 length()였지만, 
		// 배열의 길이를 알아올때는 배열이름.length 방법으로 받아와야한다.
		
		
		/* 스캐너를 통해 입력 받은 정수로 배열 길이를 지정하여 배열을 할당할 수 있다. */
		Scanner sc = new Scanner(System.in);
		
		System.out.print("새로 할당할 배열의 길이를 입력하세요 : ");
		int size = sc.nextInt();
		
		double[] darr = new double[size];
		
		System.out.println("darr의 hashCode : " + darr.hashCode());
		System.out.println("darr의 길이 : " + darr.length);
		
//		darr의 hashCode : 1170794006
//		darr의 길이 : 15
		
		
	
		/* 한 번 지정한 배열의 크기는 변경하지 못한다. */
		
		/* 배열의 사이즈를 변경한 것이 아니고, 새로운 배열을 생성하여(new) 그 주소값을 레퍼런스 변수에 덮어쓴것이다. 
		 * 기존의 값이 아닌 더 큰값이 필요하다면 덮어 쓰도록 한다.*/
		darr = new double[30];
		
		/* hashCode 를 보면 다른 값을 가지고 있는 것을 확인할 수 있다. */
		System.out.println("수정 후 darr의 hashCode : " + darr.hashCode());
		System.out.println("수정 후 darr의 길이 : " + darr.length);
		
//		수정 후 darr의 hashCode : 1289479439
//		수정 후 darr의 길이 : 30
		
		/* 한 번 할당된 배열은 지울 수 없다.
		 * 다만 레퍼런스 변수를 null로 변경하면, 더 이상 주소가 참조되지 않는 배열은 
		 * 일정 시간이 지난 후 heap의 old 영역으로 이동하여 GC(가비지 컬렉터) 가 삭제시킨다.
		 * 한번 찾아갈 수 있는 주소값을 잃어버린 배열은 다시 참조 불가능하다. 
		 * null : 아무것도 참조하고있는게 없으며(쓰이지 않음), 비웠다. 는 의미
		 * */
		darr = null;
		
		
		/* java.lang.NullPointerException */
		/* 아무것도 참조하지 않고 null이라는 특수한 값을 참조하고 있는 도중에 
		 * 참조연산자를 사용하게 될 때 발생하는 에러이다. */
		System.out.println("삭제 후 darr의 길이 : " + darr.length);
		//NullPointerException 발생, 원인 : 참조변수가 null 즉, 아무객체도 참조하고있지않기 때문
		
		
		
		
		
	}

}

 

 

 

 

 

 

 

배열 저장구조
  • Heap 영역은 값이 없는 공간이 존재 할 수 없으므로 처음 배열 선언 시 자료형별 기본값으로 초기화 됨

 

 

 

public class Application3 {

	public static void main(String[] args) {

		/* 기본적으로 배열을 선언하고 할당하게 되면
		 * 배열의 각 인덱스에는 자바에서 지정한 기본값으로 초기화 된 상태가 된다.\
		 * heap영역은 값이 없는 빈 공간이 존재할 수 없다.
		 *  */
		
		/* 값의 형태별 기본값
		 * 정수 : 0
		 * 실수 : 0.0
		 * 논리 : false
		 * 문자 : \u0000
		 * 참조 : null
		 * */
		
		int[] iarr = new int[5];
		
		/* int의 기본 값인 0으로 초기화 되어있다. */
		for (int i = 0; i < iarr.length; i++) {
			System.out.println("iarr[" + i + "]의 값 : " + iarr[i]);
		
//			콘솔창
//			iarr[0]의 값 : 0
//			iarr[1]의 값 : 0
//			iarr[2]의 값 : 0
//			iarr[3]의 값 : 0
//			iarr[4]의 값 : 0
		}
			
			/* 지정한 기본 값 외의 값으로 초기화를 하고싶은 경우 블럭을 이용한다.
			 * 블럭을 사용하는 경우에는 new를 사용하지 않아도 되며, 값의 개수만큼 자동으로 크기가 설정된다. 
			 * */
			int[] iarr2 = {11, 22, 33, 44, 55};
			
			/* 이러한 형식으로도 사용가능하다. */
			int[] iarr3 = new int[] {11, 22, 33, 44, 55};
			
			System.out.println("iarr2의 길이 : " + iarr2.length);
			System.out.println("iarr3의 길이 : " + iarr3.length);
			
//			콘솔
//			iarr2의 길이 : 5
//			iarr3의 길이 : 5
			
			
			/* 초기화 값 확인 */
			for(int i = 0; i < iarr2.length; i++) {
				System.out.println("iarr2[" + i + "]의 값 : " + iarr2[i]);
			}
			
			for(int i = 0; i < iarr3.length; i++) {
				System.out.println("iarr3[" + i + "]의 값 : " + iarr3[i]);
					
			}
			
			/* 문자열 배열로도 사용할 수 있다. */
			String[] sarr = {"apple", "banana", "grape"};
			
			for(int i = 0; i < sarr.length; i++)
			System.out.println("iarr3[" + i + "]의 값 : " + sarr[i]);
				
//			iarr3[0]의 값 : apple
//			iarr3[1]의 값 : banana
//			iarr3[2]의 값 : grape
				
			
		}
		

}

 

 

import java.util.Scanner;

public class Application4 {

	public static void main(String[] args) {

		/* 배열을 이용한 예제 */
		/* 5명의 자바 점수를 정수로 입력 받아서 합계와 평균을 실수로 구하는 프로그램을 만들어 보세요 */
		
		/* 5명의 자바점수를 저장할 배열 할당 */
		int[] scores = new int[5];
		
		Scanner sc = new Scanner(System.in);
		
		/* 반복문을 이용하여 배열 인덱스에 하나씩 접근해서 점수를 입력 받는다 */
		for (int i=0; i < scores.length; i++) {
			System.out.print((i +1) + "번 째 학생의 자바 점수를 입력해주세요 : ");
			scores[i] = sc.nextInt();		//?? 
		
		}

		/* 합계와 평균을 구한다. */
		double sum = 0.0;
		double avg = 0.0;
		
		/* 합계는 모든 인덱스의 값을 sum 변수에 누적해서 담아준다. */
		/* 배열의 인덱스 범위를 넘어가는 호출을 했을경우 out of bounds exception 에러가 발생 */
		for (int i = 0; i < scores.length; i++) {
			sum += scores[i];
			//i <= scores.length;로 범위를 입력해선 안된다. 범위를 넘어가기에 에러발생
			
		}
		
		/* 평균은 합계를 구한 값에서 배열의 길이(갯수)로 나눈다. */
		avg = sum / scores.length;
		
		System.out.println("sum : " + sum);
		System.out.println("avg : " + avg);
		
/* 콘솔창
		1번 째 학생의 자바 점수를 입력해주세요 : 100
		2번 째 학생의 자바 점수를 입력해주세요 : 90
		3번 째 학생의 자바 점수를 입력해주세요 : 80
		4번 째 학생의 자바 점수를 입력해주세요 : 70
		5번 째 학생의 자바 점수를 입력해주세요 : 60
		sum : 400.0
		avg : 80.0
	*/	
		
		
		
		
		
		
	}

}

 

 

public class Application5 {

	public static void main(String[] args) {
		
		/* 랜덤한 카드를 한장 뽑아서 출력해보자 */
		/* 먼저 모양과 카드 숫자별로 값을 저장할 두 종류의 배열을 만들자 */
		
		String[] shapes = {"SPADE", "CLOVER", "HEART", "DIAMOND"};
		String[] cardNumbers = {"2", "3", "4", "5", "6", "7", "8", 
        		"9", "10", "JACK", "QUEEN", "KING", "ACE"};
		
		/* 배열 인덱스 범위의 난수발생 */
		int randomShapeIndex = (int)(Math.random() * shapes.length);
 		int randomCardNumbers = (int)(Math.random() * cardNumbers.length);
 		
 		System.out.println("당신이 뽑은 카드는 " + shapes[randomShapeIndex] + " " 
			+ cardNumbers[randomCardNumbers] + "카드입니다.");

	}

}

 

 

 

 

2차원 배열

2차원 배열은 1차원 배열들의 묶음
  • 자료형이 같은 1차원 배열들의 묶음
  • 2차원 배열은 할당 된 공간 마다 인덱스 번호 두 개 부여 (앞 번호는 행, 뒷 번호는 열)

 

 

2차원 배열 선언과 할당

 

배열 선언
1) 자료형[ ][ ] 배열명;
2) 자료형 배열명[ ][ ];
3) 자료형[ ] 배열명[ ];

 

 

배열 할당
자료형[ ][ ] 배열명 = new 자료형[행크기][열크기];

 

 

배열의 선언과 할당
자료형[ ][ ] 배열명 = new 자료형[행크기][열크기];
자료형 배열명[ ][ ] = new 자료형[행크기][열크기];
자료형[ ] 배열명[ ] = new 자료형[행크기][열크기];
  • 인덱스는 0부터 시작한다.
  • 첫번째 칸이 행에 해당, 두번째 칸이 열에 해당
  • 선언은 [4][4]로 하지만 그 인덱스가 가질 수 있는 가장 마지막 배열은 [3][3]이 된다. 

 

 

2차원 배열 구조
  • int[ ][ ] arr = new int[2][4];

  1. 2차원 배열은 각각의 1차원 배열을 묶어서 저장해주어야 하기 때문에 하나의 공간이 더 생긴다.
  2. 그 하나의 공간(0x123)은 1차원 배열을(0x678) 참조하고 있는 또하나의 참조변수이다. 

 

 

 

 

2차원 배열 초기화

 

  • 인덱스를 이용한 초기화

 

 

  • for문을 이용한 초기화

  1. 반복문이 중첩되어야 행과 열에 해당하는 인덱스에대한 처리를 할 수 있다.
  2. 행에대한 부분은 외부 for 문으로, 열에대한 부분은 내부 for문으로

 

 

  • 선언과 동시에 초기화

 - 'arr[1][1] 은 6에 해당한다' 등으로 알아볼 수 있다. 

 

 

public class Application1 {

	public static void main(String[] args) {
		
		/* 다차원 배열
		 * 다차원 배열은 2차원 이상의 배열을 의미한다.
		 * 배열의 인덱스마다또 다른 배열의 주소를 보관하는 배열을 의미한다.
		 * 즉, 2차원 배열은 1차원 배열 여러개를 하나로 묶어서 관리하는 배열을 의미한다.
		 * 더 많은 차원의 배열을 사용할 수 있지만 일반적으로 2차원 배열보다 더 높은 차원의 배열은 사용 빈도가 현저히 적다. 
		 * */

		/* 1. 배열의 주소를 보관할 레퍼런스 변수 선언(stack) */
		int[][] iarr1;
		int iarr2[][];
		int[] iarr3[];
		
		/* 2. 여러개의 1차원 배열의 주소를 관리하는 배열을 생성(heap) */
		/* heap에 공간을 할당할 때는 new연산자를 이용한다.
		 * 배열의 주소를 관리하는 배열의 길이는 앞 부분에 정수형으로 표하며 반드시 크기를 지정해주어야 한다. */
		
		// iarr1 = new int[][];		//크기를 지정하지않으면 컴파일 에러 발생
		// iarr1 = new int[][4];	
		//주소를 묶어서 관리할 배열의 크기를 지정하지않으면 에러 발생
		// 다차원배열에서 참조변수 두개가 있는데 그 중 가운데 참조배열을 선언하지 않은 것과 마찬가지이다. 
		iarr1 = new int[3][];
		
		
		/* 3. 주소를 관리하는 배열의 인덱스마다 배열을 할당한다(heap) */
		iarr1[0] = new int[5];
		iarr1[1] = new int[5];
		iarr1[2] = new int[5];
		
		/* 참고 : 위에서 진행한 2,3번을 동시에 진행 할 수도 있다.
		 * 앞 부분 정수는 주소를 관리하는 배열의 크기, 뒷부분 정수는 각 인덱스에 할당하는 배열의 길이이다.
		 * 관리하는 여러개의 배열의 길이가 동일한 경우 아래와 같이 한번에 할당할 수도 있다.
		 * 하지만 여러개의 배열의 길이가 각각 다른경우 위에서 했던 방식처럼 인덱스별로 배열을 따로 할당해 주어야 한다.
		 * 서로 같은 길이의 여러개 배열을 하나로 묶어 관리하는 2차원 배열을 "정변배열"이라고 하며,
		 * 서로 길이가 같지않은 여러개의 배열을 하나로 묶어 관리하는 2차원 배열을 "가변배열"이라고 한다. 
		 *  */
		
		iarr2 = new int[3][5];
		
		/* 4. 각 배열의 인덱스에 차례로 접근해서 값 출력 */
		/* 할당 후에 아무 값을 대입하지 않아도 heap 영역에는 값이 없는 상태로 
		 * 공간을 생성할 수 없기 때문에 기본 값이 들어있다. */
		
		/* 4-1. 배열 하나씩 접근해서 출력하기 */
		
		/* 0번 인덱스의 배열 값 출력 */
		for (int i = 0; i < iarr1[0].length; i++) {
			System.out.print(iarr1[0][i] + " ");
		}	//0 0 0 0 0 출력
		
		System.out.println();
		
		/* 1번 인덱스의 배열 값 출력 */
		for (int i = 0; i < iarr1[1].length; i++) {
		System.out.print(iarr1[1][i] + " ");		
		}	// 0 0 0 0 0 출력

		System.out.println();
		
		/* 2번 인덱스의 값 출력 */
		for (int i =0; i < iarr1[2].length; i++) {
			System.out.print(iarr1[2][i] + " ");
		}
		
		System.out.println();	//위에가 print이므로 개행
		
		
		/* 4-2. 중첩 for문을 이용해서 배열의 값 출력 */
		for(int i =0; i < iarr1.length; i++) {
			
			
			for (int j = 0; j < iarr1[i].length; j++) {
				
				System.out.print(iarr1[i][j] + " ");
			}
			System.out.println();
			
		}
		// 콘솔창 출력
		//		0 0 0 0 0 
		//		0 0 0 0 0 
		//		0 0 0 0 0 
		//		0 0 0 0 0 
		//		0 0 0 0 0 
		//		0 0 0 0 0 
		
		
		
}

}

 

 

 

 

 

 

public class Application2 {

	public static void main(String[] args) {


		/* 2차원 정변 배열을 선언 및 할당하고 차례로 값을 대입해서 출력해보자 */
		
		/* 1. 배열의 선언 및 할당
		 * 정변 배열의 경우 각 인덱스별 배열을 따로 할당할 수도 있지만
		 * 선언과 동시에 모든 배열을 할당할 수 있다.
		 * 자료형[][] 변수명 = new 자료형[할당할 배열의 갯수][할당할 배열의 길이] 
		 * */

		int[][] iarr = new int[3][5]; 	
		// 길이 5의 배열을 3개 할당하고 그 주소를 묶어 관리하는 배열의 주소를 stack의 iarr에 저장한다.
		
		/* 2. 각 배열의 인덱스에 접근해서 값 대입 후 출력 */
		// 1 2 3 4 5
		// 6 7 8 9 10
		// 11 12 13 14 15 
		
		
		/* 배경에 저장하기 위한 하나씩 증가하는 값을 저장할 변수 */
		int value = 1;	
		// 1을 대입한 이후는 가장 처음인 [0][0]의 시작이 1이기 때문이다. 
		// 그래야 순차적으로 2,3,4,5가 나오기 때문
		
		/* 배열의 갯수만큼 반복적으로 접근하기 위한 용도의 반복문 */
		for(int i = 0; i < iarr.length; i++) {
			/* 하나의 배열의 0번부터 마지막 인덱스까지 차례로 접근해서 값을 대입하는 용도의 반복문 */
			for(int j = 0; j < iarr[i].length; j++) {
				iarr[i][j] = value++;
				// 후위연산자 덕분에 대입을 먼저한 후 증가를 시킨 2값을 위로 돌려줄 수 있다.
				
				// iarr을 통해서 행의 상태를 알 수 있고 
				// iarr[i]을 통해서 0번행을 기준으로 열의 상태를 알수있다. 
				
			}
		}
		
		/* 값 출력 */
		for ( int i = 0; i < iarr.length; i++ ) {
			
			for ( int j = 0; j < iarr[i].length; j++ ) {
				System.out.print(iarr[i][j] + " ");		//하나의 행은 같은 열에 출력
			}
			System.out.println();						//한 행이 끝나면 다음줄로 바뀜
		}
		
//		1 2 3 4 5 
//		6 7 8 9 10 
//		11 12 13 14 15 
		
		
	}

}

 

 

 

public class Application3 {

	public static void main(String[] args) {


		/* 2차원 가변 배열을 선언 및 할당하고 차례로 값을 대입해서 출력해보자. */
		

		/* 1. 배열의 선언 및 할당
		 * 가변 배열의 경우 각 인덱스별 배열을 따로 할당 해야 한다.
		 * 선언과 동시에 모든 배열을 할당할 수 없으며, 할당할 배열의 갯수만 지정하고 각 인덱스에 서로다른
		 * 길이의 배열을 따로 할당해야 한다.
		 * 자료형[][] 변수명 = new 자료형 [할당할 배열의 갯수][];
		 * 변수명[배열 인덱스] = new 자료형[배열의 길이] 
		 *  */
		
		/* 1-1. 주소를 관리하는 배열의 주소를 보관하기 위한 변수 선언 */
		int[][] iarr = new int[3][];
		
		/* 1-2. 주소를 관리하는 배열의 각 인덱스마다 배열을 할당하여 주소값 대입 */
		iarr[0] = new int[3];
		// iarr[1] = new char[2]; //자료형이 다른 배열은 하나로 묶어서 관리할 수 없다.
		iarr[1] = new int[2];
		
		int[] arr = new int[5];
		iarr[2] = arr;			  // 미리 할당해둔 배열을 이용해서도 활용할 수 있다. 
		// 레퍼런스변수는 주소값을 받는 변수이므로 주소값을 대입할시 똑같은 주소를 참조하는 셈이 된다. 
		
		
		
		
		/* 2. 각 배열의 인덱스마다 접근하여 값 대입 후 출력 */
		/* 값대입 */
		iarr[0][0] = 1;
		iarr[0][1] = 2;
		iarr[0][2] = 3;
		// iarr[0][3] = 4;
		// java.lang.ArrayIndexOutOfBoundsException 발생
		// 존재하지 않는 인덱스에 접근하는 경우 발생하는 에러
		
		iarr[1][0] = 4;
		iarr[1][1] = 5;
		
		
		iarr[2][0] = 6;
		// iarr[2] = arr; 을 주석 처리후 이것을 작동하면 아래와같은 에러가 발생한다.
		// java.lang.NullPointerException
		iarr[2][0] = 6;
		iarr[2][1] = 7;
		iarr[2][2] = 8;
		iarr[2][3] = 9;
		iarr[2][4] = 10;
		
		// iarr[3][0] = 11;	
		// 존재하지 않는 배열에 접근하는 경우게도 ArrayIndexOutOfBoundsException 발생
		
		
		/* 가변 배열 역시 반복문을 이용해서 값을 대입하고 출력할 수 있다. */
		
		/* 반복문을 이용한 값 대입 */
		
		/* 배열 인덱스마다 저장할 값이 보관될 변수 선언 */
		int value = 0;
		/* 모든 배열에 순차적으로 접근하는 반복문 */

		for( int i = 0; i < iarr.length; i++ ) {	//행이몇개있냐에 따라 반복
			/* 배열마다 인덱스에 차례로 접근하는 반복문 */
			for (int j = 0; j < iarr[i].length; j++) {
				iarr[i][j] = ++value;

			}
		}
		
		
		/* 반복문을 이용한 값 출력 */
		for ( int i = 0; i < iarr.length; i++ ) {
			for (int j = 0; j < iarr[i].length; j++ ) {
				System.out.print(iarr[i][j] + " ");
			}
			System.out.println();
		}
	}
}




/*
1 2 3 
4 5 
6 7 8 9 10 */

 

 

 

public class Application4 {

	public static void main(String[] args) {

		/* 2차원 배열도 할당과 동시에 기본값 외의 값으로 초기화 하고 싶은 경우 리터럴을 이용할 수 있다. */
		
		/* 선언과 할당을 하며 초기화 */
		/* 정변배열 */

		int[][] iarr = { {1,2,3,4,5}, {6,7,8,9,10}, {11,12,13,14,15} };
		
		/* 반복문을 이용한 값 출력 */
		
		
		for (int i = 0; i < iarr.length; i++) {
			
			for (int j = 0; j < iarr[i].length; j++) {
				System.out.print(iarr[i][j] + " ");
			}
			System.out.println();
		}
	/*	
		1 2 3 4 5 
		6 7 8 9 10 
		11 12 13 14 15 */
		
		System.out.println();
		
		
		/* 가변 배열 */
		int[][] iarr2 = { {1,2,3}, {4,5,6,7}, {8,9,10,11,12} };
		
		
		/* 반복문을 이용한 값 출력 */
		for (int i = 0; i < iarr2.length; i++) {
			
			for (int j = 0; j < iarr2[i].length; j++) {
				System.out.print(iarr2[i][j] + " ");
			}
			System.out.println();
		}

		
		System.out.println();
		
		
		/* 미리 할당한 배열을 이용한 방식 */
		int[] arr1 = {1,2,3,4,5};
		int[] arr2 = {6,7,8,9,10};
		
		int [][] iarr3 = {arr1, arr2};	// 변수를 대입함으로서 값도 대입
		
		/* 반복문을 이용한 값 출력 */
		for ( int i = 0; i < iarr3.length; i++ ) {
			
			for ( int j = 0; j < iarr3[i].length; j++ ) {
				System.out.print(iarr3[i][j] + " ");
			}
			System.out.println();
			
		}
		/*
		1 2 3 4 5 
		6 7 8 9 10 
		*/
		
	}

}

 

 

 

 

 

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

클래스와 객체(2)  (0) 2021.12.29
배열, 클래스와 객체  (0) 2021.12.28
반복문  (0) 2021.12.24
스캐너와 조건문  (0) 2021.12.23
메소드  (0) 2021.12.22

 

 

 

 

 

반복문

 

  • 프로그램 수행 흐름을 바꾸는 역할을 하는 제어문 중 하나로 특정 문장들을 반복해서 수행하도록 한다.
  • 대부분 특정 조건이 만족되는 동안 반복을 시행 함 (조건이 만족되는 동안 반복)
  • 반복문의 종류 
  1. for
  2. while
  3. do-while

 

 

 

반복문(1) for

 

 

1. for문

 

  • 1회전 : 초기식 확인 후 조건식 확인 조건식이 true면 문장 수행 조건식이 false면 수행하지 않음
  • 2회전 : 증감식 연산 후 조건식 확인 조건식이 true면 문장 수행 조건식이 false면 수행하지 않음

     * 2회전 이상부터는 모두 2회전과 동일하고 조건식이 false가 나올 때까지 문장 주행

 

 

for문의 공식
for (초기식; 조건식; 증감식)  {

출력할 조건

}

 

 

[혼동했던 점]

  • if 문에서 조건식을 추가할 수는 없다. if 문은 범위만을 지정한다.
  • 고로 if (dan >=2 && dan >= 9 && dan++) 하는 식은 만들 수 없음. for문과 혼동 주의!
package com.greedy.section02.loop_statement;

import java.util.Scanner;

public class A_for {

	
	/* for문 표현식 
	 * for (초기식; 조건식; 증감식) { 
	 * 	조건을 만족하는 경우 수행할 구문(반복할 구문);
	 * 
	 * }
	 * */
	
	//증감식 뒤에, 소괄호 뒤에 세미콜론을 찍지않는다.
	
	public void testSimpleForStatement() {
		
		/* 1부터 10까지 증가시키면서 (10번) i값을 출력하는 기본 반복문 */
		for (int i = 1; i <= 10; i += 2) {
			System.out.println(i);
			
		}
	
		//증감식이 없다는건? 조건을 계속 출력하겠다는  뜻
		//조건식이 없다는건? for문을 멈추지않는다는 뜻
		//초기, 조건, 증감 모두 작성하지않는다면 무한루프에 걸린다.
		
	
	}
	
	
	public void testForExample1() {
		
		/* 10명의 학생 이름을 입력받아 이름을 출력해보자 */
		
		Scanner sc = new Scanner (System.in);
		
		System.out.print("1번째 학생의 이름을 입력해주세요 : ");
		String student1 = sc.nextLine();
		System.out.println("1번째 학생의 이름은 " + student1 + "입니다.");
		
		System.out.print("2번째 학생의 이름을 입력해주세요 : ");
		String student2 = sc.nextLine();
		System.out.println("2번째 학생의 이름은 " + student2 + "입니다.");
		
		System.out.print("3번째 학생의 이름을 입력해주세요 : ");
		String student3 = sc.nextLine();
		System.out.println("3번째 학생의 이름은 " + student3 + "입니다.");
		
		System.out.print("4번째 학생의 이름을 입력해주세요 : ");
		String student4 = sc.nextLine();
		System.out.println("4번째 학생의 이름은 " + student4 + "입니다.");
		
		System.out.print("5번째 학생의 이름을 입력해주세요 : ");
		String student5 = sc.nextLine();
		System.out.println("5번째 학생의 이름은 " + student5 + "입니다.");
		
		System.out.print("6번째 학생의 이름을 입력해주세요 : ");
		String student6 = sc.nextLine();
		System.out.println("6번째 학생의 이름은 " + student6 + "입니다.");
		
		System.out.print("7번째 학생의 이름을 입력해주세요 : ");
		String student7 = sc.nextLine();
		System.out.println("7번째 학생의 이름은 " + student7 + "입니다.");
		
		System.out.print("8번째 학생의 이름을 입력해주세요 : ");
		String student8 = sc.nextLine();
		System.out.println("8번째 학생의 이름은 " + student8 + "입니다.");
		
		System.out.print("9번째 학생의 이름을 입력해주세요 : ");
		String student9 = sc.nextLine();
		System.out.println("9번째 학생의 이름은 " + student9 + "입니다.");
		
		System.out.print("10번째 학생의 이름을 입력해주세요 : ");
		String student10 = sc.nextLine();
		System.out.println("10번째 학생의 이름은 " + student10 + "입니다.");
		

		

		
		// 위에서 한 것 처럼 하드코딩 하지않고 for문으로 작성하면 보다 간단하게 작성할 수 있다. 
		
	for (int i = 1; i <= 10; i++) {
		
		System.out.println(i + "번쨰 학생의 이름을 입력해주세요 : ");
		String student = sc.nextLine();
		System.out.println(i + "번째 학생의 이름은 " + student + "입니다.");
		
	}
		
		/* for문의 이점
		 * 1. 보다 간결하게 작성되었다. (가독성)
		 * 2. 학생 이름뿐아니라 성적도 입력하는 기능이 추가된다면? 학생의 인원이 늘어난다면? (유지보수성)
		 * 
		 *   */
		

		
	}
	
	
	
	public void testForExample2() {
		
		/* 1 ~ 10까지의 합계를 구하시오 */
		
		/* 1부터 10까지를 변수에 저장 */
		int num1 = 1;
		int num2 = 2;
		int num3 = 3;
		int num4 = 4;
		int num5 = 5;
		int num6 = 6;
		int num7 = 7;
		int num8 = 8;
		int num9 = 9;
		int num10 = 10;
		
		
		/* 결과를 누적시켜 담아줄 변수 선언 */
		int sum = 0;
		
		/* sum 변수에 값 하나씩 담기 */
		sum += num1;
		sum += num2;
		sum += num3;
		sum += num4;
		sum += num5;
		sum += num6;
		sum += num7;
		sum += num8;
		sum += num9;
		sum += num10;
		
		/* sum에 저장된 값 출력 */
		System.out.println("sum : " + sum);
	
		
		
		/* 개선해보자 */
		int sum2 = 0; 					//담아줄 변수는 반복문 밖에서 선언되어야 한다.
		
		for(int i = 1; i <= 100; i++) {
		sum2 += i;
			
		}
		
		System.out.println("sum2 : " + sum2);
		
		/* 콘솔창 출력 
		sum : 55
		sum2 : 5050 */
		
		
	}
	
	
	public void testForExample3() {
		
		
		/* 5~10사이에 난수를 발생시켜서
		 * '1에서부터' 발생한 '난수까지의' 합계를 구해보자 */
	
		
		int random = (int) (Math.random() * 6) + 5;
		System.out.println("random : " + random);
		
		int sum = 0; //합계를 구한다는 건 무언가 누적될 공간이 필요한다는 뜻
		
		for(int i = 1; i <= random; i++) {
			
			sum += i;
		}
		
		System.out.println("1부터 " + random + "까지의 합계는 " + sum + "입니다." );
		
	}
	
	
	public void testForExample4() {
		
		/* 숫자 두개를 입력 받아 작은 수에서 큰수까지의 합계를 구하세요 
		 * 단, 두 숫자는 같은 숫자를 입력하지 않는다는 가정으로 해결해본다. 
		 * */
		
		
		Scanner sc = new Scanner(System.in);
		System.out.print("첫번째 정수 입력 : ");
		int first = sc.nextInt();
		System.out.print("두번째 정수 입력 : ");
		int second = sc.nextInt();
		
		int sum = 0;
		
		/* first와 second중 어느 것이 더 큰 수 인지 확인하면 작은 수에서 
		 * 시작해서 큰 수 까지의 합계를 구하는 반복문을 잘성할 수 있다. 
		 * */
		
		
		int min = 0;
		int max = 0;
		
		if (first >  second) {
			/* 처음 입력한 숫자가 더 크면 first가 max, 자동으로 second는 min */
			max = first;
			min = second;
			
		} else {
			/* 처음 입력한 숫자가 더 작으면 first가 min, 자동으로 second는 max */
			max = second;
			min = first;
			
		}
		
		for (int i = min; i <= max; i++) {
			
			sum += i;
		}
		
		System.out.println(min + "부터 " + max + "까지의 합은 " + sum + "입니다.");
		
	}
	
	
	
	public void printSimpleGugudan() {
		
		/* 키보드로 정수 값을 입력 받아
		 * 2-9사이의 값인 경우 해당 단의 구구단을 출력하고
		 * 그렇지 않은 경우 "반드시 2-9사이의 양수를 입력해야 합니다." 출력 */
		
		Scanner sc = new Scanner(System.in);
		System.out.println("출력할 구구단의 단 수를 입력하세요 : ");
		int dan = sc.nextInt();
		
		
		//반복문 이전에 조건을 먼저 생각해보자
		/* 입력한 숫자가 2~9 사이인지 조건 확인 */
		if (dan >= 2 && dan <= 9) {
			
			// 2 * 1 = 2
			// 2 * 2 = 4
			// . . . 
			// 2 * 9 = 18
			
			for (int su = 1; su <= 9; su++) {
				
				System.out.println(dan + " * " + su + " = " + (dan * su));
			}
			
			
			
		} else {
			System.out.println("반드시 2~9 사이의 양수를 입력해야 합니다.");
			
		}
		
		
		
		
		
	}
	
	
	
}

 

 

이를 메인메소드에서 실행 
package com.greedy.section02.loop_statement;

public class Application {

	public static void main(String[] args) {
		
		A_for a = new A_for();
		//a.testSimpleForStatement();
		//a.testForExample2();
		//a.testForExample3();
		//a.testForExample4();
		a.printSimpleGugudan();
		

	}
}

 

 

 

 

 

중첩 반복문

 

 

  • for문에 진입하면 수행 될 문장1을 먼저 수행하고 두 번째 for문에 진입하면 조건식2가 false가 될 때 까지 수행 될 문장2를 수행 한다.
  • 조건식2가 false가 되어 반복문을 빠져 나오면 수행 될 문장3을 수행하고 조건식1로 돌아와 true면 다시 반복을 한다.
  • 똑같은 변수는 선언할 수 없다. 외부 반복문에서 작성한 변수명을 내부 반복문에도 똑같이 사용할 수 없다.
외부 for문 (int i = 1; i <=10; i++) {} 이고 내부반복문이 (int j =1; j <=10; j++){} 라 가정하면 외부 반복이 10번 반복될때 내부는 100번 돈다. 

 

중첩 반복문 코드


public class B_nestedFor {

	public void printGugudanFromTwoNine() {
		
		/* for문 안에서 for문을 이용할 수 있다. */
		
		//2 * 1 = 2
		//2 * 2 = 4
		// ...
		//2 * 9 = 19
		//3 * 1 = 3
		// ....
		//3 * 9 = 27
		// ...
		//9 * 9 = 81
		
		//외부for문이 '단'에대한 부분을 컨트롤, 내부for문에 '수'에대한 컨트롤을 해야한다.
		
		/* 2단부터 단을 1씩 증가시키는 반복문 */
		
		
		
		for(int dan = 1; dan < 10; dan++) {
			
			System.out.println("=====" + dan + "단======");
			
			/* 단이 1개씩 증가하는 동안 수행할 내용은 해당 단의 구구단을 출력하는 것 */
			for (int su = 1; su < 10; su ++) {
				
				System.out.println(dan + " * " + su + " = " + (dan*su));
				
			}
			System.out.println();   //아무것도 작성하지않으면 그냥 '개행' 처리 된다. 
			
			
			//어디를 반복해야하는지 반복패턴을 잘 파악하고
			//조건문을 잘 생각해봐야한다. 
		}
		
		
		
		
		
	}
	
	
}

 

 

 

이를 메인 메소드에서 실행 

public class Application {

	public static void main(String[] args) {
		
		B_nestedFor b = new B_nestedFor();    	//객체 생성
		b.printGugudanFromTwoNine();

	}
}

 

 

 

별찍기 
import java.util.Scanner;

public class B_nestedFor {

	public void printGugudanFromTwoNine() {
		
		/* for문 안에서 for문을 이용할 수 있다. */
		
		//2 * 1 = 2
		//2 * 2 = 4
		// ...
		//2 * 9 = 19
		//3 * 1 = 3
		// ....
		//3 * 9 = 27
		// ...
		//9 * 9 = 81
		
		//외부for문이 '단'에대한 부분을 컨트롤, 내부for문에 '수'에대한 컨트롤을 해야한다.
		
		/* 2단부터 단을 1씩 증가시키는 반복문 */
		
		
		
		for(int dan = 1; dan < 10; dan++) {
			
			System.out.println("=====" + dan + "단======");
			
			/* 단이 1개씩 증가하는 동안 수행할 내용은 해당 단의 구구단을 출력하는 것 */
			for (int su = 1; su < 10; su ++) {
				
				System.out.println(dan + " * " + su + " = " + (dan*su));
				
			}
			
			
			System.out.println();   //아무것도 작성하지않으면 그냥 '개행' 처리 된다. 
			
			
			//어디를 반복해야하는지 반복패턴을 잘 파악하고
			//조건문을 잘 생각해봐야한다. 
		}
		
		
	}
	
	
	
	public void printUpgradeGugudanFromTwoToNine() {
		
		/* 단을 2단부터 9단까지 하나씩 증가시킨다. */
		for (int dan = 2; dan < 10; dan++)
			/* 한단씩 구구단을 출력하는 메소드를 호출하며 인자로 단을 전달한다. */
			printGugudanOf(dan);
	
	}
	
	
	
	
	public void printGugudanOf(int dan) {
		
		/* 매개 변수로 전달 받은 단을 1~9까지 곱한 내용을 출력해준다. */
		for (int su = 1; su < 10; su++) {
			System.out.println(dan + " * " + su + " = " + (dan*su) );
			
			
		}

	}
	
	
	
	
	
	
	
	public void printStarInputRowTimes() {
		
		/* 키보드로 입력받은 정수만큼 행으로 별을 출력하는 메소드 */
		Scanner sc = new Scanner(System.in);
		System.out.print("출력할 행의 수를 입력하세요 : ");
		int row = sc.nextInt();
		
		// 다섯행 출력하며 그 행당 다섯개의 별을 찍는 행위도 컨트롤 해야한다.
		/* 입력한 행만큼 반복 */
		
		for(int i = 1; i <= row; i++) {
			
//			/* 별을 5개 출력하는 것을 반복 */
//			for (int j =1; j < 6; j++) {
//				System.out.print("*");   
			//println으로 하면 개행이 돼 버리므로 print로만 쓴다. 
            //다섯개를 다 출력하면 개행되어야 한다.
//				
//			}
			
			
			/* 위 기능을 수행하는 메소드 추가해서 호출로 변경 */
            
			printStar(10);	
            
			// 매개 변수를 바꾸면 그 만큼 가로로 찍힌 별의 개수가 늘어난다. 
			// 이렇게 작성하는 것의 이점 : 동작적인 기능은 같지만, 구조적인 이점이 다르다.
			// 메소드를 분리해주는 작업을 해준다면 추후 유지보수성이 올라간다.
			// 정확하게 기능단위로 분리 시켜주면 추후 수정이 필요할때 이점이 분명해진다.
			
			
			
			/* 한 행에 대해서 별을 출력하고 난 뒤 줄바꿈 처리 */
			System.out.println();
		}
		
	}
	
	
	
	public void printStar (int times) {
		/* 매개변수로 전달받은 횟수만큼 줄을 바꾸지 않고별을 출력하는 기능 */
		
		for (int i = 1; i <= times; i++) {
			System.out.print("*");
			
		}
		
		
	}
	
	
	
	// 행을 입력하는 반복문은 똑같지만, 행이 1일때는 별이 1개, 행이 2일때는 별이 2개... 
	// 총 행의 수만큼 별을 출력하여 직각삼각형을 만드는 작업 
	
	public void printTriangleStar() {
		
		/* 키보드로 입력받은 정수행만큼 별을 삼각형 모양으로 출력한다. */
		Scanner sc = new Scanner(System.in);
		System.out.println("출력할 줄 수를 입력하세요 : ");
		int row = sc.nextInt();
		
		for( int i = 1; i <= row; i++ ) {
			
			/* 행의 수만큼만 별을 출력하는 반복문 */
//			for (int j = 1; j <= i; j++) {
//				System.out.print("*"); 	//개행하지않아야 하므로 print
//				
//			}
			
			
			/* 위에서 따로 뺴서 정의해놓은 메소드 호출해서 재사용, 호출을 해오자는 것 */
			printStar(i);
			
			System.out.println(); 	//한줄 출력후에는 다음줄로 넘어가야 하므로 println
		}
		
		
		
	}
	
	
}

 

 

 

메인 메소드
public class Application {

	public static void main(String[] args) {
		
		A_for a = new A_for();
		//a.testSimpleForStatement();
		//a.testForExample2();
		//a.testForExample3();
		//a.testForExample4();
		//a.printSimpleGugudan();
		
		B_nestedFor b = new B_nestedFor();
		//b.printGugudanFromTwoNine();
		//b.printUpgradeGugudanFromTwoToNine();
		//b.printStarInputRowTimes();
		b.printTriangleStar();
	
	}
}

// 이전 메소드 호출문을 주석처리 하는 이유
// : 주석처리하지않으면 사용해보려고 하는 메소드 이전의 메소드를 모두 한번씩 출력해봐야 한다.

 

 

 

 

 

 

 

 

while문

 

 

  • 조건식이 true일 때 반복문 진입하여 수행될 문장이 끝나면 조건식을 다시 확인한다.
  • 조건식이 true면 반복문에 다시 진입하여 수행될 문장을 수행하고, 조건식이 false가 될 때 까지 반복한다.

 

- for문은 정해진 횟수를 반복하는 상황에 필요
- while은 특정 상황이 true일때 반복
- 어떠한 결과를 담는 변수는 <while문 이전에> 선언되어야 한다. 
- 초기식은 처음에, 조건식은 괄호안에, 증감식은 중괄호 안에 존재해야.
- 선언과 증감식이 따라 필요하다고 생각 해야 한다. 
* {} 안에 조건을 벗어나게 할 연산(증감식,분기문) 필요

 

 

 

while문
import java.util.Scanner;

public class C_while {

	/* [while] 
	 * 
	 * 초기식;		// 먼저 선언
	 * while(조건식) {
	 * 		조건식을 만족하는 경우 수행할 구문(반복할 구문);
	 * 		증감식;
	 *  }
	 * 
	 * */
	
	public void testSimpleWhileStatement() {
		
		/* 1부터 10까지 1씩 증가하면서 i값을 출력하는 기본 반복문 */
		
		
		int i = 1;					// 변수 선언과 초기화
		while( i <=10 ) {			//while같은 경우는 조건식을 작성하지않으면 문법적으로 컨파일에러가 뜬다.
			System.out.println(i);  
			i++; 					// 증감식을 작성하지않으면 1이 무한히 출력된다. 무한루프에 걸린다.
			
		}
		
	}
	

	
	
	
	
	public void testWhileExample() {
		
		/* 입력한 문자열의 인덱스를 이용하여 문자 하나씩 출력해보기  */
		

	
	Scanner sc = new Scanner(System.in);
	System.out.println("문자열 입력 : ");
	String str = sc.nextLine();
	
	
	/* charAt(0) : 문자열에서 인덱스에 해당하는 문자를 char형으로 반환하는 기능 */
	/* length() : string 클래스의메소드로 문자열의 길이를 int형으로 반환하는 기능*/
	/* index는 0부터 시작하고 마지막 인덱스는 하상 길이보다 1작은 수를 가진다.
	 * 만약 존재하지 않는 인덕스에 접근하게 되면 에러가 발생한다.
	 * 조건식이 i <= str.length()가 될 경우 */
	
	
	System.out.println("=======for문=======");
	for (int i = 0; i < str.length(); i++) {
		char ch = str.charAt(i);
		System.out.println(i + " : " + ch);
		
		
	}
	
	System.out.println("=======while문=======");
	int index = 0;
	while(index < str.length()) {
		
		char ch = str.charAt(index);
		System.out.println(index + " : " + ch);
		index++;
		
	}
		
}
	
	
	public void testWhileExample2() {
		
		/* 정수 하나를 입력 받아 1부터 입력 받은 정수까지의 합계를 구한다. */
		Scanner sc = new Scanner(System.in);
		System.out.print("정수를 하나 입력하세요 : ");
		int num = sc.nextInt();
		
		int sum = 0;
		int i = 1;			//초기식
		while(i <= num) {
			
			sum += i;		//i의 누적연산
			
			i++;			//i의 증감식
		}
		
		System.out.println("1부터 입력받은 정수 " + num + "까지의 합은 " + sum + "입니다.");
	}
	
	
	
	public void testWhileExample3() {
		
		/* 중첩 while문을 이용한 구구단 출력하기 */
		
		int dan = 2;
		while ( dan < 10 ) { // dan은 9단까지
			
			int su = 1;		// 만약 이 초기화식이 바깥while문으로 빠지면 su는 10이 돼버려서 2단까지만 출력후 더이상 출력되지않는다.
			while( su < 10 ) {
				
				System.out.println(dan + " * " + su + " = " + (dan*su));
				
				su++;

			}
			//여기에서 su는 10이 된 후(++때문) 다시 int su = 1; 초기식으로 돌아간다. 
			
			System.out.println();  		//아무것도 작성하지 않을시 개행
			dan++;
		}
	
		
		
		
	}

 

 

 

 

 

do while

 

 

  • do 안의 내용 먼저 실행 조건식 확인 후 true면 문장 수행, false면 종료
  • while 뒤에 ; 꼭* 필요 
  • * { } 안에 조건을 벗어나게 할 연산(증감식,분기문) 필요
  • * while과 do~while의 차이점
(1) do~while은 조건문이 true가 아니더라도 무조건 한 번 이상 수행
(2) while뒤에 꼭 세미콜론이 들어감

 

 

do while 문 공식
초기식

do {



출력문

증감식

}  while(조건식);

 

 

 

do-while문 예제
import java.util.Scanner;

public class D_doWhile {

	/* [do-while문 표현식]
	 * 
	 * 초기식;
	 * do {
	 * 			1회차에는 무조건 실행하고, 이후에는 조건식을 확인하여 
	 * 			조건을 만족할 경우 수행할 구문(반복할 구문)
     
	 * 			증감식;
	 * 
	 * 		} while(조건식);
	 * 
	 * 
	 * */
	
	
	
	public void testSimPleDoWhileStatement() {
		
		
		/* 조건을 false로 두고 실행 되는지 테스트 */
		
		do {			
			System.out.println("최소 한 번 동작함...");

		} while (false);
		
		// 출력문을 한번 출력후 더이상 출력하지않음
		
	}
	
	
	
	public void testDoWhileExample2() {
		
		/* 키보드로 문자열 입력 받아 반복적으로 출력
		 * 단, exit가 입력되면 반복문을 종료한다.
		 * 
		 *  */
		
		Scanner sc = new Scanner(System.in);
		String str = "";
		do {
			System.out.print("문자열을 입력하세요 : ");
			str = sc.nextLine();
			System.out.println("입력한 문자 : " + str);
			
			/* 문자열은 == 비교가 불가능하다. 
            * String 클래스에서 제공하는 equals() 메소드를 통해 비교하자.
            */
            
		} while ( !str.equals("exit") );		//반복을 그만 할 상황입력
		
		// 문자열은 같다/같지않다를 비교할 수 없다. 왜냐면 string이 참조형이기 때문
		// String 타입에서 제공하는 equals 메소드로 비교
		// str == "exit" 하면 비교못함 
		
		System.out.println("프로그램을 종료합니다. ");
	}
	
	
}

 

 

 

 

 

 

분기문

 

분기문의 종류

  • (1) break
  • (2) continue

 

 

분기문(1) break

break 반복문에서 break문은 자신이 포함 된(혹은 break가 포함된) 가장 가까운 반복문을 빠져나간다.

(주의* 가장 가까운 반복문=if, while 등임, 가장 가까운 중괄호를 나가는 게 아님) 

 

 

 

중첩 반복문에서의 break

 

  • 두 번째 for문에 break를 만날 경우 반복문을 나가 수행 될 문장3을 수행 후 다시 첫 번째 for문을 실행하지만 마지막 break가 있다면 수행 될 문장3을 수행 후 for문을 완전히 빠져나감

 

 

 

break 예시
package com.greedy.section03.branching_statement;

public class A_break {

	/* break문은 반복문(for, while) 내에서 사용한다.
	 * 해당 반복문을 빠져나올 때 사용하며, 반복문의 조건문 판단 결과와 상관없이 
	 * 반복문을 빠져나올 때 사용하다.
	 * 일반적으로 if(조건식) {break;}  처럼 사용된다. 
	 * 단, switch문은 반복문이 아니지만 예외적으로 사용된다. 
	 * switch 문의 break는 case를 멈추기 위해서 사용하는 것이다.(별도로 생각)
	 * */
	
	
	public void testSimpleBreakStatement() {
		
		
		/* break문을 이용하여 무한 루프를 활용한 1~100까지 합계 구하기 */
		
		int sum = 0;
		int i = 1;
		while(true) {
	
			sum += i;
			
			/* 반복문 조건과 별개로 반복문을 빠져나오기 위한 조건을 다시 작성 
			 * 빠져나가는 것은 if가 아니라 while문이다. 왜냐면 if는 조건문이지 반복문이 아니기 때문ㅇ*/
			if (i==100) {
				break;	
			}
			
			i++;
			
			
		}
		
		System.out.println("1부터 100까지의 합은 " + sum + "입니다.");
		// break문을 주석처리하면 해당 출력문은 컴파일 에러가 뜬다. 
		//왜냐면 무한 루프가 되기 때문에 그 뒤에 코드는 도출할 수가 없기 때문 
		
		
		
		}
	
	
	
	public void testSimpleBreakStatement2() {
		
		
		/* 중첩 반복문 내에 분기문의 흐름 */
		/* break 문은 모든 반복문을 종료하는 것이 아니라 자신에게 가장 인접한 반복문 실행만 멈춘다. */
	
		
		/* 구구단 출력 
		 * 단, 각 단의 수가 5보다 큰 경우는 출력을 생략한다.
		 * */
		
		for (int dan = 5; dan <10; dan++) {
			
			/* 여기ㅣ까지만 빠져나옴 */
			for(int su = 1; su < 10; su++) {
				
			
				if(su > 5) {
					/* su가 5보다 큰 경우 해당 반복문을 빠져나온다. */
					break;			// target of break
				}
				
				/* 반복문을 빠져나오지 않는 경우 구구단을 출력 */
				System.out.println(dan + " * " + su + " = " + (dan*su));
			}
			
			System.out.println(); 	// 아무것도 작성하지 않을시 한번 개행
		}
	
		
	}
	
	
	public void testJumpBreak() {
		
		
		/* 네이밍: 중첩 반복문 내에서 분기문을 이용하여 한번에 여러개의 반복문을 중지 시키기 */
		/*  */
		
		label:
		for(;;) {			//while(true)와 같다. 
			for(int i = 0; i <10; i++) {
				System.out.println(i);
				
				if(i==3) {
					break label;		// 내부 for문만 빠져나감, 즉 0123이 무한히 반복
										// break을 감싸는 반복문의 외부 반복문을 빠져나가려면 
										// 외부반복문 시작 전 label이라는 이름을 부여, 빠져나갈 위치를 지정해준다.
				}
				
			}
		
		}
		
	
		
	}
	
	
	
}

 

 

 

 

 

 

 

분기문(2) continue

continue 반복문 내에서만 사용 가능하며 반복문 실행 시 continue 아래 부분은 실행하지 않고 반복문을 다시 실행한다.
  • for문의 경우 증감식으로 이동, while(do~while)문의 경우 조건식으로 이동
  • 전체 반복 중에 특정 조건을 만족하는 경우를 제외하고자 할 때 유용하다.

 

 

 

 

continue문 예시
package com.greedy.section03.branching_statement;

public class B_continue {

	
	
	/* continue문은 반복문 내에서 사용한다. (분기문은 반복문 내에서)
	 * 해당 반복문의 반복 회차를 중간에 멈추고 다시 증감식(while경우 조건식)으로 넘어가게 해준다.
	 * 일반적으로 if(조건식) {continue;} 처럼 사용된다.
	 * 보통 반복문 내에서 특정 조건에 대한 예외를 처리하고자 할 때 자주 사용된다.
	 * 
	 *  */
	
	
	
	public void testSimpleContinueStatement() {
		
		/* 1부터 100사이의 4의 배수이면서 5의 배수인 값 출력 */
		
		
		for ( int i = 1; i <=100; i++ ) {
			
			/* 4와 5의 공배수가 아닌 경우 아래 출력문을 출력하지 않고 증감식으로 넘어감 */
			if(!( i % 4 == 0 && i % 5 ==0)) {
				continue;
			}
			System.out.println(i);
			
			//20
			//40
			//60
			//80
			//100

		}
		
		
	}
	
	
	
	public void testSimpleContinueStatement2() {
		
		/* 중첩 반복문 내에서 분기문의 흐름 */
		/* continue는 모든 반복문을 건너 뛰는 것이 아닌, 자신에게 가장 인접한 반복문 실행만 건너뛴다. */
		
		/* 구구단 2~9단 출력
		 * 단, 각 단의 수가 짝수인 경우 출력을 생략한다. 
		 * */
		
		for ( int dan = 2; dan < 10; dan++ ) {
			
			for (int su = 1; su < 10; su++ ) { 			// Target of 'continue;'
				
				if ( su % 2 == 0 ) {
					/* su가 짝수인 경우 해당 회차 반복 내용을 건나 뛰고 증감식으로 이동 */
					continue;			
				}
				
				
				System.out.println(dan + " * " + su + " = " + (dan*su));
			}
			
		}
		
		
	}
	
	
	
	
	
	
	
	public void testJumpContinue() {
	
	/* 위에서 테스트 해본 예제를 이용하여 한 번에 모든 반복문의 회차를 건너뛰기 테스트 */
		
		label:
		for ( int dan = 2; dan < 10; dan++ ) {
			
			for (int su = 1; su < 10; su++ ) { 			// Target of 'continue;'
				
				if ( su % 2 == 0 ) {
					/* su가 짝수인 경우 해당 회차 반복 내용을 건너 뛰고 이름이 부여된 반복문의 증감식으로 이동 */
					continue label;			
				}
				
				
				System.out.println(dan + " * " + su + " = " + (dan*su));
			}
			
		}
		
		
	}
	
	
	
}

 

 

 

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

배열, 클래스와 객체  (0) 2021.12.28
배열  (0) 2021.12.27
스캐너와 조건문  (0) 2021.12.23
메소드  (0) 2021.12.22
연산자  (0) 2021.12.21

 

 

 

Scanner

 

Scanner Class 란?
  • 사용자로부터 입력되는(키보드로부터) 정수, 실수, 문자열을 처리하는 클래스
  • import 작성
  • Scanner 작성
  • 키보드 입력 값 받기
  1.  정수 : sc.nextInt();
  2.  실수 : sc.nextFloat(); 또는 sc.nextDouble();
  3.  문자열 : sc.next(); 또는 sc.nextLine();

 

* next( )는 공백문자 미포함
* nextLine( )은 공백문자 포함

 

흐름 순서 :
1. 스캐너 클래스의 객체를 생성하여 (임포트후) 받아오기 
2. 그 객체를 통해 스캐너 클래스가 가지고 있는 nextLine() 메소드 불러오기 

 

 

java.util.Scanner를 이용한 다양한 자료형 값 입력받기
import java.util.Scanner;

public class Application1 {

	public static void main(String[] args) {
	
		
		/* java.util.Scanner를 이용한 다양한 자료형 값 입력받기
		 * 콘솔 화면에 값을 입력 받아 출력 해보기
		 * 이런 어려운 기능 또한 미리 JDK를 설치하면 손쉽게 사용할 수 있도록 구현 해 놓았다.
		 *  */
		
		/* Scanner 객체 생성 */
		// java.util.Scanner sc = new java.util.Scanner(System.in);
		//System.in이란? 키보드로부터 입력받을때 반드시 전달해줘야하는 매개변수
		//임포트 구문 추가시 java.util.Scanner라는 풀네임을 안적어도 된다.
		
		Scanner sc = new Scanner(System.in);
		// 패키지를 포함한 이름을 지우고 에러부분에 마우스 오버를 하면 임포트 할 수 있다.
		
		
		/* 자료형 별 값 입력 받기 */
		/* 다음 줄에 입력을 대기시키지 않기 위해 println이 아닌 print 사용 */
		
		/* 2-1. 문자열 입력 받기 */
		/* nextLine() : 입력받은 값은 문자열로 반환해줌*/
		System.out.print("이름을 입력하세요 : ");
		String name = sc.nextLine();
		System.out.println("입력하신 이름은 " + name + "입니다.");
		
		//스캐너는 다양한 메소드가 있는데 자료형 별로 입력받는 메소드 보유
		//print 메소드는 입력값을 기다리므로 콘솔창에 빨간줄이 써 있을때 콘솔창에 입력가능
		// 이때 print가 아닌 println이라면 개행이 돼 버리므로 이름이 다음줄로 내려간다.
		//sc.nextLine 이 대기를 받는 메소드
		
		/* 2-2. 정수형 값 입력 받기 */
		/* nextInt() : 입력받은 값을 int형으로 반환해줌 */
		/* 숫자가 아닌 값을 입력하게 되면 java.util.InputMismatchException이 발생 */
		/* int 범위를 초과한 값을 입력하게 되면 역시 InputMismatchException이 발생 */
		System.out.print("나이를 입력하세요 : ");
		int age = sc.nextInt();
		System.out.println("입력하신 나이는 " + age + "입니다.");
		// 숫자값이 아니라 문자열을 입력하면 런타임 오류가 난다.
		// input mismatch exception 오류
		
		
		
		/* nextLong() : 입력 받은 값을 long 형으로 반환한다. 
		 * nectInt 와 Exception이 발생하는 이유는 동일하다.*/
		System.out.print("금액을 입력해주세요 : " );
		long money = sc.nextLong();
		System.out.println("입력하신 금액은 " + money + "원 입니다. " );
		
		
		
		/* 2-3. 실수형 값 입력 받기 */
		/* nextFloat() : 입력받은 값을 float 형으로 반환한다. */
		/* 숫자가 아닌 값의 경우 InputMismatchException 발생
		 * 정수 입력시 실수로 변환 후 정상 동작하며 길이를 길게 입력하면 유효자리 숫자까지만 표현 */
		System.out.print("키를 입력해주세요 : ");
		float height = sc.nextFloat();
		System.out.println("입력하신 키는 " + height + "cm 입니다.");
		
		
		/* nextDouble() : 입력 받은 값을 double 형으로 반환한다. */
		System.out.print("원하는 실수를 입력해주세요 : ");
		double number = sc.nextDouble();
		System.out.println("입력하신 실수는 " + number + "입니다. ");
		
		
		
		/* 2-4. 논리형 값 입력 받기 */
		/* nextBoolean() : 입력받은 값을 boolean 형으로 반환한다. */
		/* true or false 이외의 다른 값을 입력하면 오류가 발생한다. */
		System.out.print("참과 거짓중에 한가지를 true or false로 입력 해주세요 : ");
		boolean isTrue = sc.nextBoolean();
		System.out.println("입력하신 논리값은 " + isTrue + "입니다. ");
		
		
		
			
		
		/* 2-5. 문자형 입력 받기 */
		/* 아쉽게도 문자열은 가능해도 문자를 직접 입력 받는 기능은 제공하지 않는다. 
		 * 따라서 문자열로 입력을 받고, 입력받은 문자에서 원하는 순번쨰 문자를 분리해서 사용해야 한다.
		 * java.lang.String에 charAt(int index) 를 사용한다.
		 * index를 정수형으로 입력하면 문자열에서 해당 인덱스에 있는 한 문자를 문자형으로 반환해주는 기능을한다.
		 * index는 0부터 시작하는 숫자 체계이며 컴퓨터에서 주로 사용되는 방식이다.
		 * 만약 존재하지않는 인덱스를 입력하게 되면? 
		 * java.lang.StringIndexOutOfBoundException이 발생한다.

		 * 
		 * */
		
		sc.nextLine(); // 뒤에서 설명
		System.out.print("아무 문자나 입력 해주세요 : ");
		char ch = sc.nextLine().charAt(0);
		System.out.println("입력하신 문자는 " + ch + "입니다." );
		//charAt(0); 0부터 시작하여 n번쨰 중 하나를 추출할떄 해당번호를 넣는다.
		//charAt(0); 은 뭘 대상으로 하는가? java.lang.String.charAt 에 정의돼있는 메소드
		
		
		
	}

}



//콘솔창

//이름을 입력하세요 : 임수연
//입력하신 이름은 임수연입니다.
//나이를 입력하세요 : 27
//입력하신 나이는 27입니다.
//금액을 입력해주세요 : 678000
//입력하신 금액은 678000원 입니다. 
//키를 입력해주세요 : 170
//입력하신 키는 170.0cm 입니다.
//원하는 실수를 입력해주세요 : 0.123
//입력하신 실수는 0.123입니다. 
//참과 거짓중에 한가지를 true or false로 입력 해주세요 : true
//입력하신 논리값은 true입니다.
//아무 문자나 입력 해주세요 : hello
//입력하신 문자는 h입니다.

 

 

 

Scanner의 nextLine( )과 next( )
import java.util.Scanner;

public class Application2 {

	public static void main(String[] args) {

		/* Scanner의 nextLine()과 next() */
		/* nextLine() :  공백을 포함한 한 줄을 입력을 위한 개행문자 전까지 읽어서 문자열로 반환한다. (공백문자 포함)
		 * next() :  공백 문자나 개행문자 전까지를 읽어서 문자열로 반환한다. (공백문자를 포함하지않음) 
		 * */
		
		
		/* 1. Scanner 객체 생성 */
		Scanner sc = new Scanner(System.in);
		// 스캐너클래스 임포트 해오기
		
		/* 2. 문자열 입력 
		 * 2-1. nextLine() 
		 * */
		System.out.print("인사말을 입력 해주세요 : ");
		String greeting1 = sc.nextLine();
		System.out.println(greeting1);
		
		
		/* 2-2. next() */
		System.out.print("인사말을 입력해주세요. : ");
		String greeting2 = sc.next();
		System.out.println(greeting2);
		
		
		
		//인사말을 입력 해주세요 : 안녕하세요 저는 임수연 입니다
		//안녕하세요 저는 임수연 입니다
		//인사말을 입력해주세요. : 안녕하세요 저는 임수연 입니다
		//안녕하세요

		
		
		
		
		
		
		

	}

}

 

 

 

스캐너 주의 사항, 발생할 수 있는 이슈사항들
import java.util.Scanner;

public class Application3 {

	public static void main(String[] args) {


		/* 스캐너 주의 사항, 발생할 수 있는 이슈사항들 */
		/* 스캐너의 next 메소드들은 입력한 내용을 버퍼로부터 토큰단위로 분리해서 읽어온다.
		 * 그래서 크게 두가지 사항을 주의해야 한다.*/
		
		/* 스캐너 객체생성 */
		Scanner sc = new Scanner(System.in);
		
		/* 1. next()로 문자열 입력을 받은 후 정수, 실수, 논리 값 입력 받을 때 */
		/* "안녕하세요 반갑습니다" 입력시 공백을 기준으로 두 개의 토큰 "안녕하세요" 와 "반갑습니다"로 분리가 된다.
		 * next() 는 다음 토큰인 "안녕하세요"를 읽었고 nextInt()는 다음토큰을 정수로 읽어야하는데
		 * "반갑습니다"가 나와서 InputMismatchException이 발생한다.
		 * 결론 => 공백이 있는 문자열을 입력받을 경우에는 nextLine()을 이용하자. */
		
		System.out.print("문자열을 입력해주세요 : ");
		String str1 = sc.next();
		System.out.println("str1 : " + str1);
		
		System.out.print("숫자를 입력해주세요 : ");
		int num1 = sc.nextInt();
		System.out.println("num1 : " + num1);
		
		//Runtime Error : 실행시 문제가 발생하는 것 
		//공백이라던가, 공백 이후에 문자열이 있으면 오류가 발생한다.
		// 안녕하세요는 next가 입력받았다. 그러나 공백이후 버퍼에 남아있는 반갑습니다를 nextInt가 읽은것이다. 이때 int형이 아니기에 오류발생
		
		
		
		/* 정수, 실수, 논리값 입력 후 nextLine() 으로 문자열 입력 받을 때 */
		/* 앞에서 남긴 개행을 nextLine()이 읽고 넘어가서 아무것도 입력하지 않았는데 출력되고 프로그램이 종료된다.
		 * 결론 => 미리 nextLine()을 호출해서 버퍼를 비우고 동작시킨다.  */
		System.out.print("다시 숫자를 입력해주세요 : ");
		int num2 = sc.nextInt();
		System.out.println("num2 : " + num2);
		
		sc.nextLine(); // 오류이후 호출한 nextLine() //즉 버퍼를 비워주고 재입력을 준비해주는 역할
		
		
		System.out.print("공백이 있는 문자열을 하나 입력해주세요 : ");
		String str2 = sc.nextLine();
		System.out.println("str2 : " + str2);
		
		// nextLine에서 입력이 끝났다. 왜냐면 nextLine이 입력받을 수 있는 개행이 있었기 때문에
		// 앞에서 뭘 작성하든 nextLine이 개행을 읽고 넘어가버리는문제가 발생할 수 있다.
		// 넥스트 라인 이전에 넥스트 라인이 아닌 경우가 있다면 위와같은 문제가 발생
		// 넥스트 라인은 개행을 읽을 수 있는 메소드. 그래서 아무것도 없는 버퍼를 만들기위해
		// 중간에 넥스트 라인을 미끼삼아 넣어주는 것이다. 그럼 앞선 숫자뒤 개행이 버려질것이고 
		// 마지막에 있는 넥스트 라인은 버퍼링이없는 상태에서 입력값을 받을 수 있다. 
		
		
		
	}

}





//문자열을 입력해주세요 : 1
//str1 : 1
//숫자를 입력해주세요 : 1
//num1 : 1
//다시 숫자를 입력해주세요 : 20
//num2 : 20
//공백이 있는 문자열을 하나 입력해주세요 : 드디어 문자열을 입력할 수 있어요!
//str2 : 드디어 문자열을 입력할 수 있어요!

 

 

더보기

학습점검

✅ 메소드의 호출 흐름을 이해할 수 있다.

✅ 전달인자와 매개변수의 의미를 이해할 수 있다.

✅ return과 반환값의 의미를 이해할 수 있다.

✅ 패키지의 의미를 이해할 수 있다.

✅ impor의 의미를 이해할 수 있다.

✅ java.lang.Math에서 제공하는 메소드 및 상수의 의미를 이해할 수 있다.

✅ java.util.Scanner를 활용하여 값을 입력받고 활용할 수 있다.

 

 

 

 

 

 

 

 

 

 

조건문

  • 프로그램 수행 흐름을 바꾸는 역할을 하는 제어문 중 하나로 조건에 따라 다른 문장이 수행되도록 한다.
  • 조건문의 종류 : if 문과 switch문

 

 

 

 

 

 

 

 

if 문 (1) 

 

호출 후 실행할 main 메소드
package com.greedy.section01.conditional_statement;

public class Application {

	public static void main(String[] args) {
		
		A_if a = new A_if();
		// a.testSimpleIfStatement();
		a.testNestedIfStatement();

	}

}

 

A_if 메소드
import java.util.Scanner;

public class A_if {

	/* [if문 표현식] 
	 * if(조건식) {
	 * 		조건식이 true 일 때 실행할 명령문;
	 * }
	 * => 조건을 만족하는 경우에만 추가적인 명령을 실행시키고자 할 때
	 * */
	
	
	public void testSimpleIfStatement() {
		
		/* 정수 한 개를 입력 받아 그 수가 짝수이면 "입력하신 숫자는 짝수입니다. 라고 출력하고,
		 * 짝수가 아니면 출력하지 않는 구문을 작성해보자. 
		 * */
		
		Scanner sc = new Scanner(System.in);
		//임포트 해오기
		
		System.out.print("숫자 한 개를 입력하세요 : " );
		int num = sc.nextInt();
		
		/* 짝수인지 물어보는 조건을 기술함
		 * 어떤 수를 2로 나누었을 때 나머지가 0이면 짝수이다. 즉, 2의 배수이다.
		 * */
	
		if(num % 2 == 0) {
			/* 조건식 부분에 작성한 내용이 true 일 때는 해당 내용을 실행하고
			 * false 일때는 if 블럭 전체를 무시하고 실행하게 된다. */
			System.out.println("입력하신 숫자는 짝수입니다.");
		}

		
		/* 조건문과 상관없이 실행하는 구문 */
		System.out.println("프로그램을 종료합니다.");
		
	}

	
	
	
	public void testNestedIfStatement( ) {
		
		/* 중첩 된 if문 실행 흐름 확인 */
		/* if문 안에서 또 다른 조건을 사용하여 if문을 사용할 수 있다. */
		
		/* 정수 한개를 입력 받아 그 수가 양수인 경우에만 짝수인지를 확인하여
		 * 짝수이면 "입력하신 숫자는 양수이면서 짝수입니다." 라고 출력하고
		 * 둘 중 하나라도 해당되지않으면 아무 내용도 출력하지않는 구문을 작성해보자 */
		
		Scanner sc = new Scanner(System.in);
		System.out.println("숫자를 한 개 입력하세요 : ");
		int num = sc.nextInt();
		
		
		/* 양수인지 조건 확인 */
		if(num > 0) {
			
			/* 양수가 맞는 경우 다시 한 번 더 짝수인지 조건을 확인함 */
			if (num % 2 == 0) {
				
				System.out.println("입력하신 숫자는 양수이면서 짝수입니다.");
				
			}
			
			System.out.println("프로그램을 종요합니다.");
			
		}
		
	}
	
}





//콘솔창
//숫자 한 개를 입력하세요 : 10
//입력하신 숫자는 짝수입니다.
//프로그램을 종료합니다.



//숫자를 한 개 입력하세요 : 
//11
//프로그램을 종요합니다.

 

 

 

 

 

if문 (2) : If ~ else 문

 

if ~ else문 공식 
if(조건식) {

                 a

} else {

                 b

}
  • 조건식1의 결과 값이 true면 ⓐ 안의 내용 실행
  • 조건식2의 결과 값이 true면 ⓑ 안의 내용 실행

 

 

호출 후 실행할 main 메소드
package com.greedy.section01.conditional_statement;

public class Application {

	public static void main(String[] args) {
		
		B_ifElse b = new B_ifElse();
		// b.testSimpleIfElseStatement();
		b.testNestedIfElseStatement();
	}

}

 

 B_ifElse 클래스
package com.greedy.section01.conditional_statement;

import java.util.Scanner;

public class B_ifElse {  
	
	//실행클래스가 아닌 메소드 정의클래스 이므로 메인메소드에 체크하지않는다.


	/* [if-else문 표현식] 
	 * if(조건식) {
	 * 		조건식이 true 일때 실행 할 명령문;
	 * } else {
	 * 		조건식이 false 일때 실행 할 명령문;
	 * }
	 * => 조건을 만족하는지 여부에 따라 둘 중 하나는 무조건 실행해야 하는 경우 많이 사용된다.
	 *
	 */
	
	
	public void testSimpleIfElseStatement() {
		
		/* 정수 한개를 입력받아 그 수가 홀수이면 "입력하신 숫자는 홀수입니다. 라고 출력하고,
		 * 홀수가 아니면 "입력하신 숫자는 짝수입니다."라고 출력하는 프로그램을 작성해보자.
		 * */
		
		Scanner sc = new Scanner(System.in);   
		//ctrl + shift + o를 눌러 스캐너 클래스 임포트 해오기
		System.out.println("정수를 하나 입력하세요 : ");
		int num = sc.nextInt();
		
		
		/* 홀수인지 조건 확인 */
		if( num % 2 != 0 ) {  //num % 2 ==1 도 가능하다.
			/* 조건식이 참일때 출력할 내용 */
			System.out.println("입력하신 정수는 홀수입니다.");
		} else {
			/* 조건식이 거짓일때 출력할 내용 */
			System.out.println("입력하신 정수는 짝수입니다.");
		}
		
			/* 조건식과 상관없이 출력할 내용 */
			System.out.println("프로그램을 종료합니다.");
		
		
	}

	
	public void testNestedIfElseStatement( ) {
		
		/* 중첩된 if-else 문 실행흐름 확인 */
		/* if-else문 안에서 또 다른 조건을 사용하여 if-else 문을 사용할 수 있다. */
		
		/* 숫자ㅡㄹ 하나 입력 받아 양수이면 "입력하신 숫자는 양수입니다." 라고 출력하고,
		 * 음수이면 "입력하신 숫자는 음수입니다. "출력 
		 * 단, 0이면 "0입니다" 라고 출력하세요.
		 * */
		
		
		Scanner sc = new Scanner(System.in);
		int num = sc.nextInt();
		
		
			/* 0인지 아닌지 조건 확인 */
		if( num != 0 ) {
			/* 0이 아닌 경우 양수인지 음수인지 조건 확인 */
			if (num > 0) {
				System.out.println("입력하신 숫자는 양수입니다.");
				
			} else {
				System.out.println("입력하신 숫자는 음수입니다.");			
			}
			
		} else {
			/* 0인경우 출력할 내용 */
			System.out.println("입력하신 숫자는 0입니다.");
		}
		
		System.out.println("프로그램을 종료합니다.");
		
		
	}
	
	
	
	
	
	
	
	
}

 

 

 

 

 

if문 (3) : if~ else if~ else문  

 

 

  • 조건식1의 결과 값이 true면 ⓐ 안의 내용 실행
  • 조건식2의 결과 값이 true면 ⓑ 안의 내용 실행
  • 모두 false면 Ⓒ안의 내용 실행
  • if조건마다 true인지 살펴보며 내려감

 

 

실행 할 메인메소드
package com.greedy.section01.conditional_statement;

public class Application {

	public static void main(String[] args) {
		
		
		// 메인 메소드가 하나이고 여러 메소드를 호출하고 있으므로 하나를 실행했으면
		// 이전 메소드들은 주석처리 해 주어야 중첩되어 실행되지 않는다. 
		// C 메소드 실행시 앞 A와 B 메소드가 중첩처리 되어있는지 확인할 것. 
		A_if a = new A_if();
		// a.testSimpleIfStatement();
		// a.testNestedIfStatement();
		
		
		B_ifElse b = new B_ifElse();
		// b.testSimpleIfElseStatement();
		// b.testNestedIfElseStatement();
		
		C_ifElseIf c = new C_ifElseIf();
		//c.testSimpleIfElseIfStatent();
		//c.testNestedElseIfStatement();
		c.improveNestedIfElseIfStatement();
		
		
	}

}

 

 

메소드 C_ifElseIf
package com.greedy.section01.conditional_statement;

import java.util.Scanner;

public class C_ifElseIf {

	
	/* [if-else-if문 표현식] 
	 * if (조건식1) {
	 * 		조건식1이 true일때 실행할 명령문;
	 * } else if (조건식2) {
	 * 		조건식1이 false이고 조건식2가 true일 때 실행할 명령문;
	 * } else {
	 * 		위의 조건 2개가 모두 거짓인 경우 실행할 명령문;
	 * } 
	 * => 여러개의 조건을 제시하여 그 중 한가지를 반드시 실행시키고 싶은 경우 사용한다. 
	 * 
	 * */
	
	
	public void testSimpleIfElseIfStatent() {
		
		System.out.println("산 속에서 나무를 하던 나무꾼이 연못에 도끼를 빠트리고 말았다.");
		System.out.println("연못에서 산신령이 금도끼, 은도끼, 쇠도끼를 들고 나타났다.");
		System.out.println("나무꾼에서 셋 중 어떤 도끼가 나무꾼의 도끼인지 물었다.");
		
		System.out.println("어느 도끼가 너의 도끼이냐? (1.금도끼, 2.은도끼, 3.쇠도끼) : ");
		
		
		Scanner sc = new Scanner(System.in);
		//임포트
		int answer = sc.nextInt();
		
		
		/* 대답한 내용이 금도끼인지 확인 */
		if (answer == 1) {
			System.out.println("이런 거짓말쟁이! 너에게는 아무도끼도 줄 수 없구나! 이 욕심쟁이야!");

		} else if (answer ==2) {
			System.out.println("욕심이 과하지는 않지만 그래도 넌 거짓말을 하고있구나! 썩꺼지거라!");
			
			/* 금도끼, 은도끼가 아닌 경우, 즉 쇠도끼인 경우 */
		} else {
			System.out.println("오호~ 정직하구나~ 여기있는 금,은,쇠도끼를 다 가져가거라.");
		}
		
		/* if문과는 무관할 때 나오는 문장 */
		System.out.println("그렇게 산신령은 다시 연못속으로 사라지고 말았다.");
		
		
	}
	
	

	
	public void testNestedElseIfStatement( ) {
		
		
		/* 중첩된 if-else-if 문 실행흐름 확인 */
		/* if-else-if문 안에서 또 다른 조건을 사용하여 if or if else or if-else-if 문을 사용할 수 있다.   */
		
		/* 김교수님은 학생 시험 성적을 수기로 계산해서 학점 등급을 매기는 채점 방식을 사용하고 있다.
		 * 90점 이상이면 'A', 80점 이상이면 'B', 70점 이상이면 'C', 60점 이상이면 'D'를
		 * 60점 미만인 경우에는 'F'를 학점 등급으로 하는 기준이다.
		 * 추가로 각 등급의 중간점수(95,85,75,...)이상인 경우 '+'를 붙여서 등급을 세분화 한다.
		 * 학생의 이름과 점수를 입력하면 자동으로 학점 등급이 계산되는 프로그램을 만들어보자. */
		
		/* 학생의 이름과 점수 입력 */
		Scanner sc = new Scanner(System.in);
		System.out.println("학생의 이름을 입력하세요 : ");
		String name = sc.nextLine();
		System.out.println("학생의 점수를 입력하세요 : ");
		int point = sc.nextInt();
		
		/* 학생의 등급을 저장하기 위한 변수 초기화 */
		String grade = ""; //빈문자열, 스트링 타입은 유효값
		
		
		// 조건은 항상 위에서부터 체킹한다. if문의 가장 맨 위에 오는것이 60점 이상이면 안된다는 뜻
		if( point >= 90 ) {
			grade = "A";
			
			if (point >= 95) {
				grade += "+";
			}
			
		} else if ( point >= 80 ) {
			grade = "B";
			
			if (point >= 85) {
				grade += "+";
			}
			
		} else if ( point >= 70 ) {
			grade = "C";
			
			if (point >= 75) {
				grade += "+";
			}
			
		} else if ( point >= 60 ) {
			grade = "D";
			
			if (point >= 65) {
				grade += "+";
			}
			
		} else {
			grade = "F";
		}
		
		
		
	/* 위에서 결정 된 등급을 점수와 함께 출력한다. */
		System.out.println(name + "학생의 점수는" + point + "이고, 등급은 " + grade + "입니다." );
		
		
	}
	
	
	
	public void improveNestedIfElseIfStatement() {
		
		/* 위에서 */
		
		
		/* 학생의 이름과 점수 입력 */
		Scanner sc = new Scanner(System.in);
		System.out.println("학생의 이름을 입력하세요 : ");
		String name = sc.nextLine();
		System.out.println("학생의 점수를 입력하세요 : ");
		int point = sc.nextInt();
		
		/* 학생의 등급을 저장하기 위한 변수 초기화 */
		String grade = ""; //빈문자열, 스트링 타입은 유효값
		
		
		// 조건은 항상 위에서부터 체킹한다. if문의 가장 맨 위에 오는것이 60점 이상이면 안된다는 뜻
		if( point >= 90 ) {
			grade = "A";

			
		} else if ( point >= 80 ) {
			grade = "B";
			
	
		} else if ( point >= 70 ) {
			grade = "C";
			

			
		} else if ( point >= 60 ) {
			grade = "D";
			

			
		} else {
			grade = "F";
		}
		
		
		/* 각 등급의 중간 점수 이상이면서 60점 이상인지 확인, 100경우도 '+'가 붙도록 */
		// 모듈러 연산하여 10으로 나눈다음 1의 자릿수에대해 5보다 큰 지 확인
		if ( point % 10 >= 5 && point >= 60 || point == 100) {
			grade += "+";
		}
		
		
	/* 위에서 결정 된 등급을 점수와 함께 출력한다. */
		System.out.println(name + "학생의 점수는" + point + "이고, 등급은 " + grade + "입니다." );
		

		
	}
	
	
}




// 콘솔창

//산 속에서 나무를 하던 나무꾼이 연못에 도끼를 빠트리고 말았다.
//연못에서 산신령이 금도끼, 은도끼, 쇠도끼를 들고 나타났다.
//나무꾼에서 셋 중 어떤 도끼가 나무꾼의 도끼인지 물었다.
//어느 도끼가 너의 도끼이냐? (1.금도끼, 2.은도끼, 3.쇠도끼) : 
//3
//오호~ 정직하구나~ 여기있는 금,은,쇠도끼를 다 가져가거라.
//그렇게 산신령은 다시 연못속으로 사라지고 말았다.




// 콘솔창
//학생의 이름을 입력하세요 : 
//임수연
//학생의 점수를 입력하세요 : 
//55
//임수연학생의 점수는55이고, 등급은 F입니다.




// 콘솔창
//학생의 이름을 입력하세요 : 
//임수연
//학생의 점수를 입력하세요 : 
//100
//임수연학생의 점수는100이고, 등급은 A+입니다.

 

 

 

 

 

 

조건문1 switch

 

기본 switch문 설명
  • 조건식 하나로 많은 경우의 수를 처리할 때 사용하며 이 때 조건식의 결과는 정수 또는 문자, 문자열 비교 가능
  • 조건식의 결과 값과 일치하는 case문으로 이동
  • if문에서 조건식에 해당하는 부분에 값이 들어가야 한다.
  • 단 값자리에 실수는 들어갈 수 없다.
  • 공식 - case 값 :

switch (비교할변수) {

		case 비교값1 : 비교값1과 일치하는 경우 실행할 구문; 
        break;
        
 		case 비교값2 : 비교값2과 일치하는 경우 실행할 구문; 
        break;
        
 		default : case에 모두 해당하지 않는 경우 실핼할 구문; 
        break;
        
}

 

default
  • 값에 해당하는 케이스가 없을경우 이동시킬 default가 있어야 함
  • default문은 일치하는 case문이 없을 때 수행(=else)

 

break
  • break : 코드의 수행을 멈춘다는 뜻
  • break 가 없다면 switch 문은 멈추지 않고 계속 내려간다.  

 

 

 

 

 

메인 메소드

public class Application {

	public static void main(String[] args) {
		
		
		// 메인 메소드가 하나이고 여러 메소드를 호출하고 있으므로 하나를 실행했으면
		// 이전 메소드들은 주석처리 해 주어야 중첩되어 실행되지 않는다. 
		// C 메소드 실행시 앞 A와 B 메소드가 중첩처리 되어있는지 확인할 것. 
		A_if a = new A_if();
		// a.testSimpleIfStatement();
		// a.testNestedIfStatement();
		
		
		B_ifElse b = new B_ifElse();
		// b.testSimpleIfElseStatement();
		// b.testNestedIfElseStatement();
		
		C_ifElseIf c = new C_ifElseIf();
		//c.testSimpleIfElseIfStatent();
		//c.testNestedElseIfStatement();
		//c.improveNestedIfElseIfStatement();
		
		
		D_switch d = new D_switch();
		//d.testSimpleSwitchStatement();
		d.testSwitchVendingMachine();
		
		
		
	}

}

 

 

 

D_switch 클래스
import java.util.Scanner;

public class D_switch {

	/* [switch 문 표현식] 
	 * switch (비교할변수) {
	 * 		case 비교값1 : 비교값1과 일치하는 경우 실행할 구문; break;
	 * 		case 비교값2 : 비교값2과 일치하는 경우 실행할 구문; break;
	 * 		default : case에 모두 해당하지 않는 경우 실핼할 구문; break;
	 * }
	 * 
	 * 여러개의 비교값 중 조건에 해당하는 로직을 실행하는 것은 if-else-if 와 유사하다.
	 * 따라서 일부 호환이 가능하다.
	 * 하지만, switch문으로 비교가능한 값은 정수, 문자, 문자열 형태의 값이다.
	 * 실수와 논리는 비교할 수 없다.
	 * 또한 정화하게 일치하는 경우만 비교할 수 있으며 대소비교를 할 수 없다는게 차이점이다.
	 * case 절에는 변수를 사용하지 못한다. (값만 비교 가능함)
	 * 
	 * case뒤 비교값에는 변수를 넣는것이 아니라 정확한 리터럴을 기입하는 것이다. 
	 * 
	 * */
	
	public void testSimpleSwitchStatement() {
		
		/* 정수 두 개와 연산 기호 문자를 입력 받아서
		 * 두 숫자의 연산결과를 출력해보는 간단한 계산기 만들기 
		 * 나누기 할시에 0으로 나누면 에러 매세지가 뜬다. */
		
		
		Scanner sc = new Scanner(System.in);
		// 임포트 해오기
		System.out.print("첫 번째 정수 입력 : ");
		int first = sc.nextInt();
		System.out.print("두 번째 정수 입력 : ");
		int second = sc.nextInt();
	    System.out.print("연산 기호 입력 (+, -, *, /, %) : ");
	    char op = sc.next().charAt(0); // 문자열에서 순서만 도출해내는 메소드
	    
	    /* 연산의 결과를 저장할 변수 */
	    int result = 0;
	    
	    switch(op) {
	    
	    case '+' : 
	    	result = first + second;
	    	break;
	    	
	    case '-' :
	    	result = first - second;
	    	break;
	    
	    case '*' :
	    	result = first * second;
	    	break;
	    	
	    case '/' :
	    	result = first / second;		// second가 0이면 에러발생 java.lang.ArithmeticException
	    	break;
	    	
	    case '%' :
	    	result = first % second;
	    	break;
	    	/* default 문은 생략가능하지만 생략하는 경우 주석으로 생략이유를 작성해주는 것이 좋다. */
	    	/* 산술 연산 외에 다른 문자에 대한 처리는 생략하였음 */
	    }
		
		System.out.println(first + " " + op + " " + second + " = " + result);

	}
	
	
	
	
	
	
	
	// 자판기
	
	public void testSwitchVendingMachine() {
		
		/* switch 문을 이용해서 문자열 값 비교 및 break에 대한 테스트 */
		/* JDK 1.7 이상부터 switch문을 이용하여 문자열을 비교할 수 있다.
		 * break를 사용하지 않으면 멈추지 않고 계속 실행 구문을 동작시킨다. */
		
		System.out.println("========= vending machine =========");
		System.out.println("   사이다   콜라   환타   박카스   핫식스   ");
		System.out.println("음료를 선택해 주세요 :");
		
		Scanner sc = new Scanner(System.in);
		//임포트
		String selectedDrink = sc.nextLine();
		
		/* 원하는 음료에 맞는 가격을 저장할 변수 */
		int price = 0;
		
		
		/* 아래와 같이 작성했을 경우
		 * case는 찾아가지만 break가 없어서 그 이후 구문을 모두 수행하는 오류를 발생한다. */
		
		
		switch (selectedDrink) {
		
		case "사이다" :
			System.out.println("사이다를 선택하셨습니다.");
			price = 500;
		case "콜라" :
			System.out.println("콜라를 선택하셨습니다.");
			price = 600;
		case "환타" :
			System.out.println("환타를 선택하셨습니다.");
			price = 700;	
		case "박카스" :
			System.out.println("박카스를 선택하셨습니다.");
			price = 2000;	
		case "핫식스" :
			System.out.println("핫식스 선택하셨습니다.");
			price = 5000;
			
			
		
		}
		
		
		System.out.println(price + "원을 투입해주세요!");
		
		
		
		
		System.out.println("==========개선된 자판기===========");
		
		switch (selectedDrink) {
		
		case "사이다" :
			price = 500;
			break;
			
		case "콜라" :
			price = 600;
			break;
			
		case "환타" :
			price = 700;
			break;
			
		case "박카스" :
			price = 2000;
			break;
			
		case "핫식스" :
			price = 5000;
			break;
			
			
		
		}
		
		
		System.out.println(selectedDrink + "를 선택하셨습니다.");
		System.out.println(price + "원을 투입해 주세요.");
		
		
	}
	
	
	
	
	
	
	
/* 콘솔 : break를 입력하지 않았을때 	
	========= vending machine =========
			   사이다   콜라   환타   박카스   핫식스   
			음료를 선택해 주세요 :
			사이다
			사이다를 선택하셨습니다.
			콜라를 선택하셨습니다.
			환타를 선택하셨습니다.
			박카스를 선택하셨습니다.
			핫식스 선택하셨습니다.
			5000원을 투입해주세요!
			*/
	
	
	
	
	
	
	
	
	
	
	
}




// 콘솔창
//첫 번째 정수 입력 : 7
//두 번째 정수 입력 : 2
//연산 기호 입력 (+, -, *, /, %) : *
//7 * 2 = 14

// 준비한 값이 아닌걸 입력할 경우
//첫 번째 정수 입력 : 3
//두 번째 정수 입력 : 4
//연산 기호 입력 (+, -, *, /, %) : $
//3 $ 4 = 0




// 개선 이후 콘솔
/* ========= vending machine =========
사이다   콜라   환타   박카스   핫식스   
음료를 선택해 주세요 :
환타
환타를 선택하셨습니다.
박카스를 선택하셨습니다.
핫식스 선택하셨습니다.
5000원을 투입해주세요!
==========개선된 자판기===========
환타를 선택하셨습니다.
700원을 투입해 주세요.
*/

 

 

 

 

 

 

 

 

 

 

 

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

배열  (0) 2021.12.27
반복문  (0) 2021.12.24
메소드  (0) 2021.12.22
연산자  (0) 2021.12.21
변수와 리터럴  (0) 2021.12.20

 

 

return이란?

해당 메소드를 종료하고, 자신을 호출 한 메소드로 돌아가는 예약어
  • 메소드 종료 시 return으로 메소드를 호출 한 곳으로 돌아감
  • 반환 값(리턴 값)을 가지고 자신을 호출 한 메소드로 돌아갈 수 있음
  • 입력되지 않아도 자동적으로 return;이 붙음
  • 메소드의 호출에 스택(STACK)이라는 자료구조가 쌓인다.

 

 

 

메소드 리턴 테스트
  • void : 'return값이 없습니다'는 의미, 이 경우 return을 작성하지않아도 괜찮은데 그 이유는 컴파일러가 자동으로 추가해주기 때문이다.
  • return은 메소드 가장 마지막에 작성해야 한다. 그 이후 작성된 코드는 컴파일 에러를 발생시킨다. 
	public static void main(String[] args) {
		
		/* 메소드 리턴 테스트 */
		/* 모든 메소드의 내부에는 return;이 존재한다. 
		 * void메소드의 경우 return;을 명시적으로 작성하지 않아도 마지막줄에 컴파일러가 자동으로 추가를 해준다.
		 * return은 현재 메소드를 강제종료하고 호출한 구문으로 다시 돌아가는 명령어이다.
		 * */
		
		System.out.println("main() 메소드 시작함...");
		
		Application5 app5 = new Application5();      // testMethod 호출
		app5.testMethod();
		
		System.out.println("main() 메소드 종료됨...");
	
	}

	public void testMethod() {
		System.out.println("testMethod () 동작 확인...");
		/* 컴파일러에 의해 자동으로 추가되는 구문이다.
		 * 가장 마지막에 작성해야하고, 마지막에 작성되지 않을 경우 컴파일 에러를 발생시킨다. */
		return;
		
		//System.out.println("test");  //Unreachable code //return 뒤에 작성되었기에 컴파일에러
		//return은 메소드 가장 마지막에 작성해야 한다. 
	}
	
	
	
}

 

 

 

리턴값 테스트
  • void 를 작성하지않고 return 값을 반환받기 위해서는 메소드 선언부에 리턴 타입을 명시해주어야 한다. 
  • 값을 반환받기 위해선 명시적으로 return 구문을 작성해주어야 한다. 
	public static void main(String[] args) {
		
		/* 메소드 리턴값 테스트 */
		/* 메소드는 항상 마지막에 return 명령어가 존재한다.
		 * return은 자신을 호출한 구문으로 복귀하는 것을 의미한다.
		 * 복귀할 때 그냥 복귀할 수도 있지만, 값을 가지고 복귀할 수도 있다.
		 * 이 때 가지고 가는 값을 "리턴값" 이라고 한다.
		 * 
		 * return 값을 반환받기 위해서는 메소드 선언부에 리턴 타입을 명시해주어야 한다.
		 * void는 아무 반환값도 가지지 않았다는 리턴타입에 사용할 수 있는 키워드 이다.
		 * 반환값이 없는 경우 return 구문은 생략해도 컴파일러가 자동적으로 추가해주지만,
		 * 반환값이 있는 경우는 return 구문을 반드시 "명시적" 으로 작성해주어야 한다.
		 * 또한 메소드 선언 부에 선언한 리턴 타입 반환값을 자료형은 반드시 일치해야 한다. */
		
		/* 메소드 작성 후 호출 시 아무런 내용이 출력되지 않는다.
		 * 이유는 출력하는 명령어가 존재하지 않기 때문이다.
		 * 호출하는 메소드는 hello world 라는 문자열을 반환하고종료되었다. */
		Application6 app6 = new Application6();
		app6.testMethod();
			// 이 위치에 "hello world" 라는 값이 리턴되었다. 출력되지 않았을뿐이다.
		
		// 값을 리턴받고 바로 출력되는 것이 아닌 출력하기 위한 또 다른 작업이 필요하다. 
		// 변수에 저장하여 출력하는 방법
		String returnText = app6.testMethod();
		System.out.println(returnText);
		
		/* 변수에 저장하지 않고 바로 출력도 가능함 */
		System.out.println(app6.testMethod());
		
	}

	
	/**
	 * <pre>
	 * 문자열 형태의 반환값을 확인해보기 위한 메소드
	 * </pre>
	 * @return hello world 라는 문자열을 반환
	 *  */
	
	public String testMethod() {
	// This method must return a result of type String라는 빨간줄이 뜬다.
	// 아직 return 값이 없다는 뜻인데 그 값이 String 타입이어야 한다는 의미이다. 
		
		
		/* public 뒹에 바로 return으로 가지고 갈 타입을 명시한다.
		 * 아무값도 리턴하지 않는 경우 void, 값을 반환하는 경우에는 반환 값을 자료형을 작성해야 한다.  */
		return "hello world";
		
		
	}
	
	
	
	
	
	
}



//콘솔창
//hello world
//hello world

 

 

 

매개변수와 리턴값 복합 활용
  • 메소드의 전달인자(매개변수)와 반환값을 이용해 메소드를 활용할 수 있다. 
  • 이러한 작성을 통해 알고있어야 하는 것 : 매개변수 부분을 작성하는 방법, 리턴타입을 작성하는 방법, 메인메소드에서 특정메소드를 호출하는 방법, 리턴의 구조와 흐름
public class Application7 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		
		/* 매개변수와 리턴값 복합 활용 */
		/* 매개변수도 존재하고 리턴값도 존재하는 메소드를 이용하여 간단한 계산 만들기 */
		
		/* 숫자 두개를 매개변수로 입력받아 연산하는 메소드를 사칙연산별로 추가해서 호출하는 테스트를 해보자. */
		
		
		int firstNum = 100;
		int secondNum = 10;
		
		Application7 app7 = new Application7();
		// app7.plusTwoNumbers(firstNum, secondNum); //그냥 여기서멈추면 출력되지않기때문에 출력문에 같이 넣어준다.
		System.out.println("두 수를 더한 결과 : " + app7.plusTwoNumbers(firstNum, secondNum));
		System.out.println("두 수를 뺀 결과 : " + app7.minusTwoNumbers(firstNum, secondNum));
		System.out.println("두 수를 곱한 결과 : " + app7.multipleTwoNumbers(firstNum, secondNum));
		System.out.println("두 수를 나눈 결과 : " + app7.devideTwoNumbers(firstNum, secondNum));
		
        
	}



	/* 더하기 */
	public int plusTwoNumbers(int first, int second) {		
		
		return first + second;
	}
	
	
	/* 빼기 */
	public int minusTwoNumbers(int first, int second) {
		
		return first - second;
	}
	
	
	
	/* 곱하기*/
	public int multipleTwoNumbers(int first, int second) {
		
		return first * second;
	}
	
	
    /* 나누기 */
	public int devideTwoNumbers(int first, int second) {
		
		return first / second;
	}	
	
    
}


// 이러한 작성을 통해 알고있어야 하는 것
// 매개변수 부분을 작성하는 방법, 리턴타입을 작성하는 방법, 
// 메인메소드에서 특정메소드를 호출하는 방법, 리턴의 구조와 흐름





// 콘솔창
//두 수를 더한 결과 : 110
//두 수를 뺀 결과 : 90
//두 수를 곱한 결과 : 1000
//두 수를 나눈 결과 : 10

 

 

 

static 키워드가 있는 메소드
  • static 키워드가 있는 메소드는 호출 시 클래스명.메소드명( ); 으로 호출함
  • static은 그동안 메인메소드에 있는 public static void main 에서 볼 수 있었다. 즉, 그동안은 static이 없는 메소드에선 객체를 생성하여 호출했다.
  • 그러나 static 이 붙으면 방식이 조금 달라지는데 클래스명.메소드명( ); 으로 호출해주면 된다.  
public class Application8 {

	public static void main(String[] args) {


		/* static 메소드 호출 */
		/* main 메소드에는 public과 void 사이에 static이라는 키워드가 있다.
		 * static 키워드에 대해서는 뒤에서 다루게 될 예정이지만,
		 * static 메소드를 호출하는 방법부터 먼저 학습해보자.
		 * static 메소드건 non-static 메소드건 메소드의 동장 흐름은 동일하다. 
		 * */
		
		/* static메소드를 호출하는 방법
		 * : 클래스명.메소드명() 
		 * */
		
		System.out.println("10과 20의 합 : " + Application8.sumTwoNumbers(10, 20));
		
		/* 동일한 클래스 내에 작성 된 static메소드는 클래스명 생략이 가능하다. */
		System.out.println("10과 20의 합 : " + sumTwoNumbers(20, 30));
		
	}

	public static int sumTwoNumbers(int first, int second) {
		
		return first + second;
		
	}
	
	
	
	
}




//10과 20의 합 : 30
//10과 20의 합 : 50

 

 

 

 

다른 클래스에 작성한 메소드 호출
  • Application9 클래스에서 호출할 클래스 Calculator를 임의로 만든다. 
public class Calculator {

	
	/** <pre>
	 * 매개변수로 전달 받은 두 수를 비교하여 더 작은 값을 가진 정수를 반환함
	 * 같은 값을 가지는 조건에 대해서는 처리하지 않음
	 * </pre>
	 * @pram first 최솟값 비교를 위한 첫번째 정수
	 * @param second 최솟값 비교를 위한 두번째 정수
	 * @return 두 수 중 작은 값을 정수형으로 변환
	 *  */
	
	
	public int minNumberOf(int first, int second){
		
		return first > second ? second : first ;
		
	}
	
	
	/** <pre>
	 * 매개변수로 전달 받은 두 수를 비교하여 더 큰 값을 가진 정수를 반환함
	 * 같은 값을 가지는 조건에 대해서는 처리하지 않음
	 * </pre>
	 * @prarm first 최대값 비교를 위한 첫번째 정수
	 * @param second 최대값 비교를 위한 두번째 정수
	 * @return 두 수 중 작은 값을 정수형으로 변환
	 *  */
	
	public static int maxNumberOf(int first, int second) {
		
		return first > second ? first : second;
		
	}
	
	
	
	
}

 

  • Calculator 클래스를 호출할 클래스 Application9
public class Application9 {

	public static void main(String[] args) {

		/* 다른 클래스에 작성한 메소드 호출 */
		/* 동일한 패키지에 Calculator 이라는 클래스를 하나 추가하고 메소드를 작성해서 테스트하자. */
		
		
		int first = 100;
		int second = 50;
		
		/* 1. non-static 메소드 호출 */
		/* 클래스가 다르더라도 사용하는 방법은 동일하다
		 * 클래스명 사용할이름 = new 클래스명();
		 * 사용할이름.메소드명(); 
		 * */
		Calculator calc = new Calculator();
		int min = calc.minNumberOf(first, second);  //리턴값을 받기위해 변수 설정
		System.out.println("두 수 중 최소값은 : " + min);
		
		
		/* 2. static 메소드 호출 
		 * 다른 클래스에 작성 된 static 메소드의 경우 클래스명을 반드시 기술해야 한다.
		 * : 클래스명.메소드명();
		 * */
		int max = Calculator.maxNumverOf(first, second);
		System.out.println("두 수 중 최대값은 : " + max );
		
		
		
		/*주의!
		 * static 메소드도 non-static 메소드처럼 호출은 가능하다.
		 * 하지만 권장하지 않는다.
		 * 이미 메모리에 로딩 되어 있는 static 메소드는 여러 객체가 공유하게 되는데
		 * 그 때 객체로 접근하게 되면 인스턴스가 가진 값으로 공유된 값에 예상치 못하는 동작을 유발할 수 있기 때문에
		 * 사용을 제한해 달라는 경고다. 시스템이 복잡해질 수록 이런 에러를 찾기 힘들어진다. 하지말라면 하지말자.*/
		
		int max2 = calc.maxNumverOf(first, second);
		System.out.println("두 수 중 최대값은 : " + max2);
		// 에러문 : The static method maxNumverOf(int, int) from the type Calculator should be accessed in a static way
		
		
		
	}

	
	
}




// 콘솔창
// 두 수 중 최소값은 : 50
// 두 수 중 최대값은 : 100
// 두 수 중 최대값은 : 100

 

 

 

 

 

 

패키지란?

서로 관련 있는 클래스 또는 인터페이스의 묶음(그룹)
  • 클래스명는 원래 '패키지명까지 포함하며' 서로 다른 패키지에서는 같은 클래스명 사용 가능

 

임포트란? 

서로 다른 패키지에 있는 클래스나 인터페이스를 사용하는 경우 선언 가능
  • 위에서 작성한 코드중 Calculator를 Application9 에서 호출했던 것은 같은 패키지라 문제가 없었다.
  • 그러나 서로 다른 패키지에서 호출하는 경우 import선언해야 한다. 
  • 이때 클래스는 패키지 명까지 포함한 풀 네임이어야 한다. 

 

public class Application1 {

	public static void main(String[] args) {
		
		/* 패키지와 임포트 */
		/* 패키지 : 서로 관련있는 클래스 또는 인터페이스 등을 모아 하나의 묶음(그룹)으로 단위를 구성하는 것을말한다. 
		 * 		  같은 패키지 내에서는 동일한 이름의 클래스를 만들 수 없지만, 패키지가 다르면 동일한 이름의 클래스를 만들 수 있다.
		 * 		  section01, section02 패키지명은 다르지만 각 클래스의 이름은 Application1이 동일하게 있는 것 참조
		 * 		  클래스 명은 원래 패키지명을 포함하고 있기 때문이다.
		 * 		  지금까지 클래스명에 패키지 명을 함께 사용하지 않은 이유는 동일한 패키지 내에서 사용했기 때문이다.
		 * 		  그렇게 때문에 서로 다른 패키지에 존재하는 클래스를 사용하는 경우에는 클래스명 앞에 패키지명을 명시해야 한다. */
		

		/* 이전에 만든 Calculator 클래스를 재사용해서 static method  와 non-static method 호출 */
		// Calculator calc = new Calculator();
		// 에러문 : Calculator cannot be resolved to a type
		
		
		// 클래스의 풀네임을 써주면 인식한다.
		// 자동완성을 쓰는순간 임포트 구문이 자동으로 생긴다.
		// import com.greedy.section01.method.Calculator; 
		//임포트 구문을 넣지않는다면 클래스의 풀네임으로
		com.greedy.section01.method.Calculator calc = new com.greedy.section01.method.Calculator();
		int min = calc.minNumberOf(30, 20);
		System.out.println("30과 20 중 더 작은 값은 : " + min);
		
		
		int max = com.greedy.section01.method.Calculator.maxNumverOf(30, 20);
		System.out.println("30과 20 중 더 큰 값은 : " + max);
		
		
		
		
	}

}

// 콘솔
//30과 20 중 더 작은 값은 : 20
//30과 20 중 더 큰 값은 : 30

 

package com.greedy.section02.package_and_import;

/* 사용하려는 클래스까지를 작성해야 한다. */
import com.greedy.section01.method.Calculator;
/* static import의 경우 사용하려는 static method까지 전부 써줘야 한다. */
import static com.greedy.section01.method.Calculator.maxNumberOf;

public class Application2 {

	public static void main(String[] args) {
		
		/* 패키지와 임포트 */
		/* 임포트 : 서로 다른 패키지에 존재하는 클래스를 사용하는 경우 패키지명을 포함한 풀 클래스 이름을 사용해야 한다.
		 *         하지만 매번 다른 클래스의 패키지명까지 기술하는 것은 번거로우므로 패키지명을 생략하고 사용할 수 있도록 하는
		 *         import 구문을 사용한다. import는 package 선언문과 class 선언문 사이에 작성하며
		 *         어떠한 패키지 내에 있는 클래스를 사용할 것인지에 대해 미리 선언하는 효과를 가진다. */
		
		Calculator calc = new Calculator();	//임포트 구문 추가하기
		int min = calc.minNumberOf(50, 60);
		System.out.println("50과 60 중 더 작은 값은 : " + min);
		
		int max = Calculator.maxNumberOf(50, 60);
		System.out.println("50과 60 중 더 큰 값은 : " + max);
		
		/* 추가로 static 메소드를 호출할 때 클래스명도 생략하고 사용할 수 있다. */
		int max2 = maxNumberOf(100, 200);	//static import 구문 수동 추가
		System.out.println("100과 200 중 더 큰 값은 : " + max2);
		
		
		
		
	}

}




//50과 60 중 더 작은 값은 : 50
//50과 60 중 더 큰 값은 : 60
//100과 200 중 더 큰 값은 : 200

 

 

 

 

 

 

 

 

 

 

 

 

Math

  • -자바는 API라는 인터페이스에서 제공하는 클래스 및 메소드들을 활용하여 보다 편하게 코드 작성이 용이함
  • java.lang.Math에서 제공하는 것을 활용하여 수학적인 연산을 쉽게 할 수 있음
  • JAVA API 11을 검색하면 다양한 API를 살펴볼 수 있다. 

 

 

java.lang.Math 이용하기 
  • abs 와 random
		/* API란?
		 * Application Programming Interface 는 응용 프로그램에서 사용할 수 있도록,
		 * 운영체제나 프로그래밍 언어가 제공하는 기능을 제어할 수 있도록 만든 인터페이스를 뜻한다.
		 * 쉽게 말해 우리가 구현 할 수 없거나 구현하기 번거로운 기능들을 JDK 를 설치하면 사용할 수 있도록 제공해놓은
		 * 소스코드(클래스나 인터페이스) 들을 의미한다.
		 * 더 쉽게 말해 누가 작성해놓은 소스코드이나 가져다 쓰는 방법을 학습한다는 의미이다.
		 * 모든 코드를 우리가 다 외울 수 없으니 API문서를 별도로 제공해 주고 있다.  */
		
		
		/* java.lang.Math
		 * Math 클래스는 수학에서 자주 사용하는 상수들과 메소드 들을 미리 구현해놓은 클래스이다.  
		 * 
		 * API 문서에서 확인하면 MATH 클래스는 모두 static 으로 선언되어 있다. 
		 * static 메소드 호출방식으로 호출한다.*/
		
		/* 절대값 출력 */
		System.out.println("-7의 절대값 : " + (java.lang.Math.abs(-7)));
		/* Math클래스이 경우 import 하지않아도 사용할 수 있다. 
		 * java.lang 패키지 하위에 있는 클래스는 import 구문이 불필요하다.
		 * ex : String, System 등...
		 * 워낙 자주사용하는 패키지이기 때문에 import 없이 사용 가능하게 해 놓았다.
		 * 컴파일러가 import java.lang.*; 이 코드를 자동으로 추가해서 컴파일 한다. 
		 * 
		 */
		
		System.out.println("-1.25의 절대값 : " + (Math.abs(-1.25)));
		
		/* 우리가 Calculator에서 만든 min과 max를 구하는 기능도 이미 제공되고 있다.*/
		System.out.println("10과 20중 더 작은 것은 : " + Math.min(10,20));
		System.out.println("10과 20중 더 큰 것은 : " + Math.max(10,20));
		
		/* 수학적으로 많이 사용하는 고정된 값들도 이미 Math 안에 정의된 것이 있다.
		 * 필드라는 것을 이용한 것인데 이 부분은 나중에 자세히 다루겠다.
		 *  */
		System.out.println("원주율 : " + Math.PI);  //원의 둘레 너비등을 계산할 때 미리 정의된 값을 불러서 계산에 사용하면 된다. 
		
		
		/* 난수(랜덤값)를 발생시키는 메소드 
		 * 0부터 1전까지의 실수 형태의 난수를 발생시킨다.
		 * */
		System.out.println("난수 발생 : " + Math.random());  
		// 할때마다 다른 값이 나온다. 
		
		
		

	}

}


//콘솔창
//-7의 절대값 : 7
//-1.25의 절대값 : 1.25
//10과 20중 더 작은 것은 : 10
//10과 20중 더 큰 것은 : 20
//원주율 : 3.141592653589793
//난수 발생 : 0.6297901013367174

 

 

 

java.lang.Math 이용하기 2
원하는 범위의 난수를 구하는 공식  
int 변수 = (int)(Math.random() * 구하려는 난수의 갯수) + 구하려는 난수의 최소값 
		/* 난수의 활용 */
		/* Math.random()을 이용해 발생한 난수는 0부터 1전까지의 실수 범위의 난수값을 반환한다.
		 * 필요한 범위까지의 난수를 발생시켜보자 */
		
		
		/* 원하는 범위의 난수를 구하는 공식 
		 * (int)(Math.random() * 구하려는 난수의 갯수) + 구하려는 난수의 최소값 */
		
		
		/* 0~9까지의 난수 발생 */	
		int random1 = (int) (Math.random() *10);
		System.out.println("0부터 9사이의 난수 : " + random1);
		
		// 왜? random 의 값은 0 <= random < 1.0 이므로 * 10을 해주면 정수를 구할 수 있으므로
		// 이때 0을 값으로 받고 싶지않으면 +1 해주면 된다. 1~10
		
		/* 1~10 까지의 난수 발생 */
		int random2 = (int) (Math.random() *10) +1;
		System.out.println("1부터 10사이의 난수 : " + random2);
		
		/* 10에서 15까지의 난수 발생 */
		int random3 = (int) (Math.random() * 6) + 10;
		System.out.println("10부터 15사이의 난수 : " + random3);
		
		
		
		/* byte 타입이 가지는 값의 범위만큼 난수 발생(-128~127) */
		int random4 = (int) (Math.random() * 256) -128;
		System.out.println("-128부터 127까지의 난수 : " + random4);
		
		
		
	}

}




//0부터 9사이의 난수 : 6
//1부터 10사이의 난수 : 9
//10부터 15사이의 난수 : 12
//-128부터 127까지의 난수 : -15

 

 

 

 

java.util.Random 이용하기 
  • ctrl + Shift + o = import 해 오기
  • (1) java.lang 이 아니기 때문에, (2) static이 아니기 때문에 객체를 생성해서 사용해야 한다. 
원하는 범위의 난수를 구하는 공식
int 변수 = random.nextInt(구하려는 난수의 갯수) + 구하려는 난수의 최소값 

 

import java.util.Random;    //임포트 

public class Application3 {

	public static void main(String[] args) {
		
		/* java.util.Random 클래스
		 * java.util.Random 클래스의 nextInt() 메소드를 이용한 난수발생
		 * nextInt(int bound) : 0부터 매개변수로 전달받은 난수를 발생시켜 정수 형태로 전환 
		 * */
		
		/* 원하는 범위의 난수를 구하는 공식
		 * random.nextInt(구하려는 난수의 갯수) + 구하려는 난수의 최소값 
		 * */
		
		Random random = new Random();
		// ctrl + Shift + o = 임포트 해오기
		// 자바.랭 이 아니기 때문에, 스태틱이 아니기 때문에 객체를 생성해서 사용해야 한다. 
		
		
		/* 0부터 9까지 난수 발생 */
		int randomNumber1 = random.nextInt(10);
		System.out.println("0부터 9까지 난수 : " + randomNumber1);
		
		/* 1부터 10까지의 난수 발생 */
		int randomNumber2 = random.nextInt(10) +1;
		System.out.println("1부터 10까지 난수 : " + randomNumber2);
		
		/* 20부터 45까지의 난수 발생 */
		int randomNumber3 = random.nextInt(26) +20;
		System.out.println("1부터 10까지 난수 : " + randomNumber3);
		System.out.println("20부터 45까지의 난수 발생 : " + randomNumber3);
		
		/* -128 ~ 127 사이의 난수 발생 */
		int randomNumber4 = new Random().nextInt(256) -128;
		System.out.println("-128 ~ 127 사이의 난수 발생 : " + randomNumber4);
		// 객체를 생성하자마자 바로 메소드 호출도 할 수 있다.
		// 단 유의할 점은 한번쓰고 또 쓰지는 못함
		
		
	
	}

}



//0부터 9까지 난수 : 9
//1부터 10까지 난수 : 4
//1부터 10까지 난수 : 24
//20부터 45까지의 난수 발생 : 24
//-128 ~ 127 사이의 난수 발생 : 71

 

 

 

 

 

 

 

 

 

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

반복문  (0) 2021.12.24
스캐너와 조건문  (0) 2021.12.23
연산자  (0) 2021.12.21
변수와 리터럴  (0) 2021.12.20
변수 파트 암기할 표 정리  (0) 2021.12.18

 

증감 연산자

  • 단항 연산자로 구분된다 (단항: 피연산자가 하나)
  • 피연산자의 값에 1을 더하거나 빼는 연산자(++,--)로 위치에 따라 결과 값이 다르게 나타남
  • 주의해야하는 것은 연산의 순서 
  • 전위 연산 : 먼저 전위 연산 후 다른 연산 실행
int a = 10;
int b = ++a;

 

  • 후위 연산 : 다른 연산 우선 실행 후 후위 연산
  1.  다른 연산이라는 것은 대입이나 println을 통한 출력을 의미
  2.  다른 연산, 즉 대입이나 출력을 먼저 한 후 값을 출력하는 것
  3.  어떤 연산이 있든 가장 마지막에 하는 연산이다. 
int a = 10;
int b = a++;

 

		< 증감 연산자 >
		/* 피연산자의 앞 or 뒤에 사용이 가능하다 */
		/* '++' : 1의 증가 의미 */
		/* '--' : 1의 감소 의미 */
		
		int num = 20;
		System.out.println("num : " + num);   // 20

		num++;
		System.out.println("num : " + num);   //21
		
		++num;
		System.out.println("num : " + num);   //22
		
		num--;
		System.out.println("num : " + num);   //21
		
		--num;
		System.out.println("num : " + num);   //20
		
		
		/* 증감연산자만 사용 될 때는 1증가/1감소의 의미를 가진다
		 * 하지만 문제는 다른 연산자와 함께 사용할때 전위/후위 연산의 구분이 필요하다. */
		
		int firstNum = 20;
		int result1 = firstNum++ * 3;
		
		// 후위 연산은 다른 연산을 먼저 처리하고 난 뒤 마지막에 처리 됨

		System.out.println("result1 : " + result1);   //60
		System.out.println("firstNum : " + firstNum);   //21
		
		
		int secondNum = 20;
		int result2 = ++secondNum * 3;
		// 전위 연산은 증가를 먼저 처리하고 난 뒤 다른 연산을 함
		
		System.out.println("result2 : " + result2);   //63
		System.out.println("secondNum : " + secondNum);   //21

 

 

 

 

 

비교 연산자

  • 데이터가 같은지, 다른지, 혹은 대소 비교를 할 때 사용
  • 항상 논리 값(true, false)이 결과 값
  • ‘==‘과 ‘!=‘은 모든 자료형에 사용 가능 (정수, 실수, 논리 등)
  • ‘==‘과 ‘!=‘을 제외한 비교 연산자(>, >=, <, <=)는 기본형 boolean과 참조형(String)을 제외하고
    나머지 자료형에 모두 사용 가능
'==' 연산자 / 값이 같은지 묻는 연산자
int a = 10;
int b = 11;
boolean c = a == b; (a와 b의 값이 같은지 c로 반환)
이때의 c는 false

 

'!=' 연산자 / 값이 같지 않은지 묻는 연산자
int a = 10;
int b = 11;
boolean c == a != b; (a와 b의 값이 다른지 c로 반환)
이때의 c는 true

 

		/* 비교연산자 */
		/* 비교연산자는 피연산자 사이에서 상대적인 크기를 판단하여 참 혹은 거짓을 반환하는 연산자이다.
		 * 연산자 중 참 혹은 거짓을 반환하는 연산자는 삼항 연산자의 조건식이나 조건문의 조건절에 많이 사용된다.
		 *  */
		
		/* 1. 숫자값 비교 */
		/* 1-1. 정수 비교 */
		int inum1 = 10;
		int inum2 = 20;
		
		System.out.println("===========정수값 비교============");
		System.out.println("inum1과 inum2가 같은지 비교 : " + (inum1 == inum2));
		System.out.println("inum1과 inum2가 같지 않은지 비교 : " + (inum1 != inum2));
		System.out.println("inum1과 inum2가 큰지 비교 : " + (inum1 > inum2));
		System.out.println("inum1과 inum2가 작은지 비교 : " + (inum1 < inum2));
		System.out.println("inum1과 inum2가 작거나 같은지 비교 : " + (inum1 <= inum2));
		
		// ===========정수값 비교============
		// inum1과 inum2가 같은지 비교 : false
		// inum1과 inum2가 같지 않은지 비교 : true
		// inum1과 inum2가 큰지 비교 : false
		// inum1과 inum2가 작은지 비교 : true
		// inum1과 inum2가 작거나 같은지 비교 : true
		
		
		/* 1-2. 실수 비교 */
		double dnum1 = 10.0;
		double dnum2 = 20.0;
		System.out.println("===========실수값 비교============");
		System.out.println("dnum1과 dnum2가 같은지 비교 : " + (dnum1 == dnum2 ));
		System.out.println("dnum1과 dnum2가 같지 않은지 비교 : " + (dnum1 != dnum2 ));
		System.out.println("dnum1과 dnum2가 큰지 비교 : " + (dnum1 > dnum2 ));
		System.out.println("dnum1과 dnum2가 작은지 비교 : " + (dnum1 < dnum2 ));
		System.out.println("dnum1과 dnum2가 작거나 같은지 비교 : " + (dnum1 <= dnum2 ));
		
//		===========실수값 비교============
//		dnum1과 dnum2가 같은지 비교 : false
//		dnum1과 dnum2가 같지 않은지 비교 : true
//		dnum1과 dnum2가 큰지 비교 : false
//		dnum1과 dnum2가 작은지 비교 : true
//		dnum1과 dnum2가 작거나 같은지 비교 : true
		
		
		/* 2. 문자값 비교 */
		char ch1 = 'a';
		char ch2 = 'A';
		System.out.println("===========문자값 비교============");
		System.out.println("ch1과 ch2가 같은지 비교 : " + (ch1 == ch2 ));
		System.out.println("ch1과 ch2가 같지 않은지 비교 : " + (ch1 != ch2 ));
		System.out.println("ch1과 ch2가 큰지 비교 : " + (ch1 > ch2 ));
		System.out.println("ch1과 ch2가 작은지 비교 : " + (ch1 < ch2 ));
		System.out.println("ch1과 ch2가 작거나 같은지 비교 : " + (ch1 <= ch2 ));
		
		//===========문자값 비교============
		//ch1과 ch2가 같은지 비교 : false
		//ch1과 ch2가 같지 않은지 비교 : true
		//ch1과 ch2가 큰지 비교 : true
		//ch1과 ch2가 작은지 비교 : false
		//ch1과 ch2가 작거나 같은지 비교 : false
		
		
		/* 3. 논리값 비교 */
		boolean bool1 = true;
		boolean bool2 = false;
		System.out.println("===========논리값 비교============");
		System.out.println("bool1과 bool2가 같은지 비교 : " + (bool1 == bool2 ));
		System.out.println("bool1과 bool2가 같지 않은지 비교 : " + (bool1 != bool2 ));
//		System.out.println("bool1과 bool2가 큰지 비교 : " + (bool1 > bool2 ));
//		System.out.println("bool1과 bool2가 크거나 같은지 비교 : " + (bool1 >= bool2 ));
//		System.out.println("bool1과 bool2가 작은지 비교 : " + (bool1 < bool2 ));
//		System.out.println("bool1과 bool2가 작거나 같은지 비교 : " + (bool1 <= bool2 ));
		
// 주석처리한 부분은 비교가 불가능한 것, true와 false 값의 대소를 비교할 수 없다.




		/* 4. 문자열값 비교 */
		/* 문자열도 ==과 !=은 비교가 가능하지만 대소비교는 불가능하다. */
		String str1 = "java";
		String str2 = "java";
		System.out.println("===========문자열값 비교============");
		System.out.println("str1과 str2가 같은지 비교 : " + (str1 == str2 ));
		System.out.println("str1과 str2가 같지 않은지 비교 : " + (str1 != str2 ));
//		System.out.println("str1과 str2가 큰지 비교 : " + (str1 > str2 ));
//		System.out.println("str1과 str2가 크거나 같은지 비교 : " + (str1 >= str2 ));
//		System.out.println("str1과 str2가 작은지 비교 : " + (str1 < str2 ));
//		System.out.println("str1과 str2가 작거나 같은지 비교 : " + (str1 <= str2 ));
		
//		===========문자열값 비교============
//		str1과 str2가 같은지 비교 : true
//		str1과 str2가 같지 않은지 비교 : false

 

 

 

 

논리 연산자

논리 값(true, false)를 취급하는 연산자
  • && : 두 피연산자가 모두 true일 때 true 반환 (AND)
  • || : 두 피연산자 중 하나만 true여도 true 반환 (OR)
a b a && b a || b
true true true true (추정 불필요)
true false false true (추정 불필요)
false true false (추정 불필요) true
false false false (추정 불필요) false

 

* 추정 불필요?
이미 첫번째 조건만으로 판단근거가 나왔기에 두번째 조건을 수행할 이유가 없는 경우. 컴퓨터는 연산을 효율적으로 한다. 각 연산자의 특징에 기반해서, 굳이 확인을 안해도되는 경우는 확인을 안한다. or같은 경우 하나만 true여도 true를 반환한다. 그러므로 a값에서 true값을 확인했다면 b부분은 확인하지않고 넘어간다. 

 

 

 

 

 

논리 연산자

  • 논리 값을 부정하여 반대 값으로 변경
  • 제어문을 활용할 때 많이 쓰임
  • 논리 부정 연산자
boolean bool1 = true;
boolean bool2 != bool1;

 

		/* 논리 연산자 */
		/* 논리값(true or false)을 취급하는 연산자이다. */
		
		/* 1. 논리 연산자 결과 값 확인 */
		System.out.println("true와 true의 논리 and 연산 : " + (true && true) );
		System.out.println("true와 false의 논리 and 연산 : " + (true && false));
		System.out.println("false와 true의 논리 and 연산 : " + (false && true));
		System.out.println("false와 false의 논리 and 연산 : " + (true && false));
		
		//Dead code가 뜨는 이유? 코드 흐름자체가 도달하지 않으므로 추정 불필요를 의미
// 콘솔창은 다음과 같이 출력
//		true와 true의 논리 and 연산 : true
//		true와 false의 논리 and 연산 : false
//		false와 true의 논리 and 연산 : false
//		false와 false의 논리 and 연산 : false
		
		
		
		System.out.println("true와 true의 논리 or 연산 : " + (true || true) );
		System.out.println("true와 false의 논리 or 연산 : " + (true || false));
		System.out.println("false와 true의 논리 or 연산 : " + (false || true));
		System.out.println("false와 false의 논리 or 연산 : " + (true || false));
		
// 콘솔창은 다음과 같이 출력		
//		true와 true의 논리 or 연산 : true
//		true와 false의 논리 or 연산 : true
//		false와 true의 논리 or 연산 : true
//		false와 false의 논리 or 연산 : true
		
		
		System.out.println("true와 논리 not 연산 : " + (!true));
		System.out.println("false의 논리 not 연산 : " + (!false));
//		true와 논리 not 연산 : false  //콘솔
//		false의 논리 not 연산 : true  //콘솔
		
		
		/* 2. 논리식에 논리연산자 활용 */
		int a = 10;
		int b = 20;
		int c = 30;
		int d = 40;
		
		System.out.println("a가 b보다 작으면서 c가 d보다 작은지 확인 : " + (a < b && c < d));
		System.out.println("a가 b보다 작으면서 c가 d보다 큰지 확인 : " + (a < b && c > d));
		System.out.println("a가 b보다 크면서 c가 d보다 작은지 확인 : " + (a > b && c < d));
		System.out.println("a가 b보다 크면서 c가 d보다 큰지 확인 : " + (a > b && c > d));
//콘솔창		
//		a가 b보다 작으면서 c가 d보다 작은지 확인 : true
//		a가 b보다 작으면서 c가 d보다 큰지 확인 : false
//		a가 b보다 크면서 c가 d보다 작은지 확인 : false
//		a가 b보다 크면서 c가 d보다 큰지 확인 : false
		
		System.out.println("a가 b보다 작거나 c가 d보다 작은지 확인 : " + (a < b || c < d));
		System.out.println("a가 b보다 작거나 c가 d보다 큰지 확인 : " + (a < b || c > d));
		System.out.println("a가 b보다 크거나 c가 d보다 작은지 확인 : " + (a > b || c < d));
		System.out.println("a가 b보다 크거나 c가 d보다 큰지 확인 " + (a > b || c > d));
//콘솔창	
//		a가 b보다 작거나 c가 d보다 작은지 확인 : true
//		a가 b보다 작거나 c가 d보다 큰지 확인 : true
//		a가 b보다 크거나 c가 d보다 작은지 확인 : true
//		a가 b보다 크거나 c가 d보다 큰지 확인 false
		/* 논리 연산자의 우선순위와 활용 */
		/* && : 11순위
		 * || : 12순위
		 * && 연산자가 ||연산자보다 우선순위가 높다
		 *  */
		
		/* 1. 1부터 100사이의 값인지 확인 */
		/* 1 <= 변수 <= 100 ============== 수학적으로 했던 표현이므로 이렇게는 사용x 
		 * 변수 >= 1 && 변수 <=100 ======== 이렇게 사용해야 한다. */ 
		int num1 = 55;
		System.out.println("1부터 100사이인지 확인 : " + (num1 >= 1 && num1 <= 100));
		// 1보다 크거나 같으면서 100보다 작거나 같은지 확인 
		int num2 = 105;
		System.out.println("1부터 100사이인지 확인 : " + (num2 >= 1 && num2 <= 100));
//		1부터 100사이인지 확인 : true
//		1부터 100사이인지 확인 : false
		
		
		
		
		/* 2. 영어 대문자인지 확인 */
		/* 영어 대문자냐? ---> 문자변수 >= 'A' && 문자변수 <= 'Z' */
		char ch1 = 'G';
		System.out.println("영어 대문자인지 확인 : " + (ch1 >= 'A' && ch1 <= 'Z'));
		char ch2 = 'g';
		System.out.println("영어 대문자인지 확인 : " + (ch2 >= 'A' && ch2 <= 'Z'));		
//		영어 대문자인지 확인 : true
//		영어 대문자인지 확인 : false
		
		
		
		/* 3. 대소문자 상관없이 영문자 y인지 확인 */
		/* 문자변수 == 'y' || 문자변수 == 'Y' */
		char ch3 = 'Y';
		System.out.println("영문자 y인지 확인 : " + (ch3 == 'y' || ch3 == 'Y'));
		
		char char4 = 'y'; 
		System.out.println("영문자 y인지 확인 : " + (ch3 == 'y' || ch3 == 'Y'));
//		영문자 y인지 확인 : true
//		영문자 y인지 확인 : true
		
		
		
		
		/* 4. 영문자인지 확인 */
		/* A: 65, Z:90, a: 97, z: 122 (중간에 91~96은 영문자가 아님) */
		/* 연산자 우선순위를 고려한다면 and 연산이 먼저 수행되기 때문에 괄호를 묶지 않아도 되지만
		 * 논리적으로 먼저 실행하는 내용을 괄호로 묶어주면 코드를 읽기에 좋다. */
		
		char ch5 = 'f';
		System.out.println("영문자인지 확인 : " + ((ch5 >= 'A' && ch5 <= 'Z') || (ch5 >= 'a' && ch5 <= 'z')));
		
		char ch6 = 'F';
		System.out.println("영문자인지 확인 : " + ((ch6 >= 'A' && ch6 <= 'Z') || (ch6 >= 'a' && ch6 <= 'z')));
		
//		영문자인지 확인 : true
//		영문자인지 확인 : true	
		
		
		char ch7 = '가';
		System.out.println("영문자인지 확인 : " + ((ch7 >= 'A' && ch7 <= 'Z') || (ch7 >= 'a' && ch7 <= 'z')));
		
//		영문자인지 확인 : false

 

		/* AND 연산과 OR 연산자의 특징
		 * 논리식 && 논리식 : 앞의 결과가 false이면 뒤를 실행 안함
		 * 논리식 || 논리식 : 앞의 결과가 true이면 뒤를 실행 안함 \
		 * */
		
		/* 1. 논리식 && 논리식 : 앞의 결과가 false이면 뒤를 실행 안함  */
		/* 조건식 두개가 모두 만족해야 true를 반환하지만 앞에서 미리 false가 나오게되면
		 * 뒤의 조건을 확인할 필요 없이 false를 반환한다.
		 * 따라서 연산 횟수를 줄이기 위해서는 &&연산의 경우 앞에 false가 나올 가능성이 높은 조건을 
		 * 작성하는 편이 좋다. */
		
		int num1 = 10;
		int result1 = (false && ++num1 > 0) ? num1 : num1;
		
		System.out.println("&& 실행 확인 : " + result1);
		// && 실행 확인 : 10   // 콘솔창
		
		
		
		/* 2. 논리식 || 논리식 : 앞의 결과가 true 이면 뒤를 실행 안함 */
		/* 조건식 둘 중 하나라도 true를 반환하면 true를 반환하기 때문에 앞에서 미리 true가 나오면
		 * 뒤의 조건을 확인할 필요도 없이 true를 반환한다.
		 * 따라서 연산 횟수를 줄이기 위해서는 ||연산의 경우 앞에 true 가 나올 가능성이 높은 조건을 작성하는 편이 좋다. */
		
		int num2 = 10;
		int result2 = (true || ++num2 > 0) ? num2 : num2;
		System.out.println("||실행을 확인 : " + result2);
		// ||실행을 확인 : 10   //콘솔창

 

 

 

 

 

삼항 연산자

  • 자바에서 유일하게 피연산자 항목이 3개인 연산자
  • 공식 
조건식 ? 식1 : 식2;
  • 조건식의 결과 값(true or false)에 따라 연산을 처리하는 방식
  • 결과 값이 참일 경우 식1, 거짓일 경우 식2 수행
  • 삼항 연산자 안에 삼항 연산자를 중첩하여 쓰는 것도 가능
< 삼항연산자 >
int result1 = a > b ? a++ : b--;
int result2 = a < b ? a++ : (b == 0 ? a-- : b++)     ---- 삼항연산자 내부 삼항연산자 중첩
  • 후위 연산자이므로 값으로 도출된 a혹은 b는 result에 값을 대입한 뒤 증감이 이루어 질것이다. 
  • 단 조건문이 복잡해 지는 경우 삼항연산자를 쓰는것을 지양한다. 

 

		/* 삼항 연산자 */
		/* 자바에서 유일하게 피연산자 항목이 3개인 연산자이다. */
		/* 삼항연산자 공식 -> 조건식 ? 참일때 사용값1 : 거짓일시 사용값2 */
		/* 조건식은 반드시 결과가 true 또는 false로 나오게끔 작성해야 함
		 * 비교/논리 연산자가 주로 사용 됨 */
		
		int num1 = 10;
		int num2 = -10;
		String result1 = (num1 > 0 ) ? "양수이다." : "양수가 아니다.";
		String result2 = (num2 > 0 ) ? "양수이다." : "양수가 아니다.";

		System.out.println("num1은 " + result1);
		System.out.println("num2은 " + result2);		
		
//		콘솔창
//		num1은 양수이다.
//		num2은 양수가 아니다.
		
		
		/* 삼항연산자의 중첩사용도 가능하다. */
		int num3 = 5;
		int num4 = 0;
		int num5 = -5;
		
		String result3 = (num3 > 0) ? "양수이다." : (num3 == 0) ? "0이다." : "음수이다.";
		String result4 = (num4 > 0) ? "양수이다." : (num4 == 0) ? "0이다." : "음수이다.";
		String result5 = (num5 > 0) ? "양수이다." : (num5 == 0) ? "0이다." : "음수이다.";
		
		System.out.println("num3은 " + result3);
		System.out.println("num4은 " + result4);
		System.out.println("num5은 " + result5);
		
//		콘솔창
//		num3은 양수이다.
//		num4은 0이다.
//		num5은 음수이다.

 

 

 

 

연산자 종류와 우선 순위

 

종류 구분 세부구분 연산자 우선순위
최우선 연산자 직접 접근 연산자   ( ) . { } 1
단항 연산자     + - ! (자료형) ++ -- 2
이항 연산자 산술 연산자   * / % 3
+ - 4
쉬프트 연산자   >>  <<  >>> 5
비교 연산자   >  <  >=  <== 6
==  != 7
논리 연산자 비트 논리 연산자 & 8
^ 9
| 10
일반 논리 연산자 && 11
|| 12
삼항 연산자     (조건식) ? 참값 : 거짓값 13
대입 연산자 순수대입   = 14
복합대입 산술 대입 +=  -=  *=  /=  %=
  쉬프트 대입 <<=  >>=  >>>=
  비트 논리 대입 &=  ^=  |=
나열 연산자     , 15

 

 

 

 

 

 

 

 

더보기

학습점검


✅ 연산자 우선순위의 개념을 이해할 수 있다.
✅ 산술 연산자를 이용하여 데이터 연산을 수행할 수 있다.
✅ 복합 대입 연산자를 이용하여 데이터 연산을 수행할 수 있다.
✅ 증감 연산자를 이용하여 데이터 연산을 수행할 수 있다.
✅ 비교 연산자를 이용하여 데이터 연산을 수행할 수 있다.
✅ 논리 연산자를 이용하여 데이터 연산을 수행할 수 있다.
✅ 삼항 연산자를 이용하여 데이터 연산을 수행할 수 있다.
✅ 연산자 우선순위를 활용하여 데이터 연산을 수행할 수 있다.

 

 

 

메소드

특정 작업을 수행하기 위한 명령문의 집합
  • 수학에서의 함수와 비슷한 의미. 함수는 무언가 연산을 하여 값을 도출하듯 메소드 역시 값을 받아 연산을 하여 결과값을 도출, 어떠한 작업을 수행하는지는 메소드에 따라 다르다.

 

  • 메소드는 다른 메소드를 호출 가능 (메소드를 호출한 곳으로 돌아옴)
		/* 메소드란? */
		/* 메소드(method)는 어떤 특정 작업을 수행하기 위한 명령문의 집합이라고 할 수 있다.
		 * 자세한 메소드 사용법은 객체 부분에서 다루게 되니 지금은 호출 흐름에 대해 이해할 수 있도록 하자
		 *  */
		
		System.out.println("main() 시작됨...");
		
		
		/* 작성한 메소드 호출 */
		/* 클래스명 사용할 이름 = new 클래스명();     // 객체생성
		 * 사용할 이름.메소드명()                   // 메소드 호출
		 * */
		
		Application1 app1 = new Application1();      //메소드가 선언된 클래스를 이와같이 작성
		app1.methodA();                              //methodA를 호출하고 싶다면 이와같이 작성한다. 
		
		System.out.println("main() 종료됨...");
	}
	
	

	/* 호출 확인을 위한 메소드 */
	public void methodA() {
		
		System.out.println("methodA() 호출함...");
		
		methodB();           //위 객체생성순서와 호출방식이 약간 다르지만 우선 호출 흐름에 집중해서 확인하기
		
		System.out.println("methodA() 종료됨...");
	}
	
	
	
	
	/* 호출 확인을 위한 메소드 */
	public void methodB() {
		
		System.out.println("methodB() 호출됨...");		
		
		methodC();
		
		System.out.println("methodB() 종료됨... ");
	}
	
	
	
	
	/* 호출 확인을 위한 메소드 */
	public void methodC() {
		
		System.out.println("methodC 호출함...");
		System.out.println("methodC 종료됨...");
	}

	
	
	
    // 콘솔창은 다음과 같다. 
	//main() 시작됨...
	//methodA() 호출함...
	//methodB() 호출됨...
	//methodC 호출함...
	//methodC 종료됨...
	//methodB() 종료됨... 
	//methodA() 종료됨...
	//main() 종료됨...

	
	
	
	
	
}

 

public class Application2 {

	public static void main(String[] args) {
		
		/* 메소드 호출 흐름 연습 */
		/* Application1 에서 했던 것과 비슷하지만 호출 흐름을 메인 메소드에서 제어해보자 */
		
		
		
		System.out.println("main() 시작함...");
		
		/* methodA(), methodB(), methodC() 를 차례대로 호출한다. */
		Application2 app2 = new Application2();
		app2.methodA();
		app2.methodB();
		app2.methodB();
	
		System.out.println("main() 종료됨...");
		
	}

	
	
	public void methodA() {
		
		System.out.println("methodA() 호출됨...");
		System.out.println("methodA() 종료됨...");
	}
	
	
	
	
	public void methodB() {
		
		System.out.println("methodB() 호출됨...");
		System.out.println("methodB() 종료됨...");
	}
	
	
	
	
	public void methodC() {
		
		System.out.println("methodC() 호출됨...");
		System.out.println("methodC() 종료됨...");
	}
	
	
	
	// 콘솔창
	//main() 시작함...
	//methodA() 호출됨...
	//methodA() 종료됨...
	//methodB() 호출됨...
	//methodB() 종료됨...
	//methodB() 호출됨...
	//methodB() 종료됨...
	//main() 종료됨...

	
	
	
}

 

 

값을 전달하면서 메소드를 실행하기
  1. 메소드 실행 시 어떠한 값을 미리 줄 수 있는데 이 값을 전달인자라고 한다. 
  2. 전달인자가 없으면 비워 둘 수 있다    ->    ( )
  3. 그 값을 활용(매개변수)해서 메소드 수행 가능
method (50) public void methodA (int var) {
     System.out.println(var);
}
50은 전달인자 int var는 매개변수

 

public class Application3 {

	public static void main(String[] args) {

		/* 전달인자(argument)와 매개변수(parameter)를 이용한 메소드 호출
		 * 
		 *  지금까지 우리가 배운 변수는 지역변수에 해당한다. 
		 *  다양한 변수의 종류들이 존재하는데 이는 차차 배우게 될 것이다.
		 *  
		 *  1. 지역변수 - 지역변수는 그 메소드안에서만 유효하다.
		 *  2. 매개변수 - 다른 메소드끼리 전달해도 유효한 변수
		 *  3. 전역변수(필드)
		 *  4. 클래스(static) 변수
		 *  
		 *  
		 *  지역 변수는 선언한 메소드 블럭 내부에서만 사용이 가능하다. 이것을 지역변수의 스코프라고 한다.
		 *  다른 메소드간 서로 공유해야 하는 값이 존재하는 경우, 메소드 호출 시 사용하는 괄호를 이용해서 값을 전달할 수 있다.
		 *  이 때 전달하는 값을 전달 인자(argument) 라 부르고,
		 *  메소드 선언부 괄호 안에 전달 인자를 받기 위해 선언하는 변수를 매개변수(parameter)라고 부른다.
		 *  
		 *  */


	}

 

 

 

 

 

매개변수의 개수나 자료형의 제한은 없으며 상수(final 키워드)도 사용 가능함

 

public class Application3 {

	public static void main(String[] args) {

		/* 전달인자(argument)와 매개변수(parameter)를 이용한 메소드 호출
		 * 
		 *  지금까지 우리가 배운 변수는 지역변수에 해당한다. 
		 *  다양한 변수의 종류들이 존재하는데 이는 차차 배우게 될 것이다.
		 *  
		 *  1. 지역변수 - 지역변수는 그 메소드안에서만 유효하다.
		 *  2. 매개변수 - 다른 메소드끼리 전달해도 유효한 변수
		 *  3. 전역변수(필드)
		 *  4. 클래스(static) 변수
		 *  
		 *  
		 *  지역 변수는 선언한 메소드 블럭 내부에서만 사용이 가능하다. 이것을 지역변수의 스코프라고 한다.
		 *  다른 메소드간 서로 공유해야 하는 값이 존재하는 경우, 메소드 호출 시 사용하는 괄호를 이용해서 값을 전달할 수 있다.
		 *  이 때 전달하는 값을 전달 인자(argument) 라 부르고,
		 *  메소드 선언부 괄호 안에 전달 인자를 받기 위해 선언하는 변수를 매개변수(parameter)라고 부른다.
		 *  
		 *  */


		Application3 app3 = new Application3();
		
		/*  전달 인자와 매개변수를 이용한 메소드 호출 테스트  */
		/* 1. 전달 인자로 값 전달 테스트 */
		/* 호출하려는 메소드의 매개변수 선언부에 미리 선언해둔 자료형 타입과 갯수, 순서가 일치하게 값을 넣어 호출한다.
		 *  */
		
		app3.testMethod(30);
		//app3.testMethod("40");
		// The method testMethod(int) in the type Application3 is not applicable for the arguments (String)
		// 매개변수는 int 형이지만 인자가 String 형이기 때문에 호출될 수 없다.
		
		//app3.testMethod(20, 30, 40);
		// The method testMethod(int) in the type Application3 is not applicable for the arguments (int, int, int)
		// 매개변수는 int 형 한개지만 인자는 3개이기 때문에 호출할 수 없다.
		
		//app3.testMethod();
		//The method testMethod(int) in the type Application3 is not applicable for the arguments ()
		// 매개변수는 선언되어 있지만 인자로 값을 전달하지 않으면 호출할 수 없다. 
	
		
		
		/* 2. 변수에 저장한 값 전달 테스트 */
		/* 2-1. 변수에 저장 된 없을 이용하여 값을 전달할 수 있다. */
		
		int age = 20;
		app3.testMethod(age);    //변수값으로 전달
		
		// 같은 age를 메소드에도 인트 변수에도 똑같이 쓸 수 있을까?
		// 결론은 된다. 왜냐하면 age는 지역 변수이므로, 각자의 지역에서만 사용되며, 각자의 지역안에서는 중복되면 안되지만 엄연히 다른 지역에 있는 것이기 때문
		// 같은 지역 내에서 같은 변수명을 사용하는 것은 안된다. 
		
	
		
		/* 2-2. 자동형변환을 이용하여 값 전달을 할 수 있다. */
		byte byteAge = 10;
		app3.testMethod(byteAge);
		
		
		
	
		/* 2-3. 강제형변환을 이용하여 값 전달을 할 수 있다. */
		long longAge = 80;
		app3.testMethod((int) longAge); 
		// app3.testMethod(longAge); 
		// 컴파일 에러: The method testMethod(int) in the type Application3 is not applicable for the arguments (long)
		// int 로 강제형변환을 하여 전달을 하게되면 문제없다. 
		
		
		
		/* 2-4. 연산 결과를 이용해서 값 전달을 할 수 있다. */
		app3.testMethod(age * 3);
		
		
		
	}

	
	
	
	public void testMethod(int age) {
		// int age = 10;    // 매개 변수에서 선언된 변수명과 같은 지역변수를 선언할 수 없다. 
		System.out.println("당신의 나이는 " + age + "세 입니다.");
		

	}
	
	// 메소드를 호출하며 어떤 값을 input 할 수 있다.
	// 단 값을 넘길때 선언해둔 자료형과 갯수와 순서가 일치해야만 한다. 그렇지않으면 컴파일 오류가 난다. 
	// 이를 전달인자라고 부르고. 전달인자를 받기위해 선언하는 변수를 매개변수라 한다.

 

/** 
 * <pre>
 * Class : Application4
 * Comment : 여러개의 전달인자와 매개변수를 이용한 메소드 호출
 * History : 
 * <2021/12/21 (임수연) 처음작성함>
 * <2021/12/31 (아무개) 수정함
 * </pre>
 * @author 임수연
 * @version 1.0.0 
 * */





public class Application4 {

	public static void main(String[] args) {


		
		
		/* 여러 개의 전달 인자를 이용한 메소드 호출 테스트 */
		Application4 app4 = new Application4();
		app4.testMethod("유관순", 15, '여');
		
		/* */            // 범위주석
		//               //한줄주석
		/** */           // 앞에 별이 두개붙으면, 문서에대해서 설명할때 붙이는 주석, 무언가 문서적인 설명을 하고자 할때 사용.
		

		// app4.testMethod(20, "홍길동", '남');
		// The method testMethod(String, int, char) in the type Application4 is not applicable for the arguments (int, String, char)
		// 왜 오류가 날까? 값의 개수는 맞지만 순서가 다르게 전달되면 호출하지 못한다. 정해진 순서대로 전달해야 함
		
		
		
		/* 변수에 저장된 값을 전달하며 호출할 수 있다. */
		String name = "신사임당";
		int age = 40;
		char gender = '여';
		
		app4.testMethod(name, age, gender);
		
		
		
		
		
		
	}

	
	
	/** 
	 * <pre>
	 * 이름과 나이와 성별을 전달받아 한 번에 출력해주는 기능을 제공합니다.
	 * </pre>
	 * @param name 출력할 이름을 전달 해 주세요
	 * @param age 출력할 나이를 전달 해 주세요
	 * @gender gender 출력할 성별을 전달해주세요. 성별은 변경되지 않을 것을 보장합니다. 
	 * */
	
	
	
	
	public void testMethod(String name, int age, final char gender) {
		/* 매개변수도 일종의 지역변수로 구분된다.
		 * 매개변수 역시 final 키워드를 사용할 수 있다. 
		 * 지역변수에 final 키워드를 붙여 상수를 만드는 것과 동일하다.
		 * final 매개변수는 상수 네이밍 규칙을 선택적으로 따르는 경향이 있다. (써도 되고 안써도 됨) 
		 * 즉 늘 대문자로 작성하기를 권할때와는 달리 상수가 매개변수로 쓰일땐 굳이 대문자만 고집하지 않아도 된다.
		 * */
		System.out.println("당신의 이름은 " + name + "이고, 나이는 " + age + "세 이며, 성별은 " + gender + "입니다.");
		
		
		
	
	}
	
	
	
	
}

 

 

 

 

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

스캐너와 조건문  (0) 2021.12.23
메소드  (0) 2021.12.22
변수와 리터럴  (0) 2021.12.20
변수 파트 암기할 표 정리  (0) 2021.12.18
변수  (0) 2021.12.17

 

변수의 명명 규칙

컴파일 에러를 발생시키는 규칙

1. 동일한 범위 내에서 동일한 변수명을 가질 수 없다.
2. 예약어 사용이 불가능하다. (주요 예약어 참고)

 - 자료형을 변수명으로 사용할 수 없다.
3. 대/소문자를 구분한다.

4. 숫자로 시작할 수 없다.

int age1 = 5; (o)
int 1age = 5; (x)

 

5. 특수문자는 ‘_’ (언더바)와 ‘$’(달러) 만을 허용한다.

 

 

 

 

 

변수의 명명 규칙(2)

(개발자들 간의 암묵적 규칙, 안지키더라도 컴파일 에러는 나지않는다. )

 

1. 길이의 제한은 없지만 적당한 길이의 변수명 작성하는 것이 좋다.
2. 합성어일 경우 첫 단어는 소문자로 시작하며, 두 번째 단어부터는 대문자로 시작(camel-case)

 - 변수의 시작은 무조건 소문자, 두번째 단어부터 대문자 ex) isTrue

 - 중간의 대문자가 옴으로서 낙타의 등처럼 생겼다고 해서 camel-case라고 함
3. 단어와 단어 사이에 언더스코어(_) 사용 안 함

 - 단어와 단어사이는 '대문자로 구분'짓는 2번의 방법 사용
4. 한글로 변수명을 짓는 것이 가능하지만, 권장하지는 않는다.
5. 변수 안에 저장된 값이 어떤 의미를 가지는지 알 수 있도록 이름을 짓는다.

 - 변수에 어떤 값이 저장되는지 유추가 가능하도록 이름 짓는 편이 좋다. 

6. 전형적인 변수명이 있으면 가급적 그것으로 사용한다.
7. 명사형으로 작성한다.
8. boolean형은 의문문으로 작성하되 가급적이면 긍정형으로 네이밍한다.

 - isDeath와 isAlive 쪽이 낫다. 

 

* 이클립스에 뜨는 노란색은 경고와 같은것, 불필요한 선언이 일어나지는 않았는지 확인하자.

* 클래스명만 대문자로 시작한다.

 

< 변수의 명명 규칙 >
/* 변수의 이름을 지을 때 아무렇게나 짓는 것이 아닌 정해진 규칙이 있다.
 * 실무적으로는 굉장히 중요하기 때문에 반드시 숙지해야 하고,
* 또한, 규칙에 맞는 올바른 변수명을 짓는 것이 좋은 프로그래밍을 하는 첫 단추이다.
 *  */
		
/* 1. 컴파일 에러를 발생시키는 규칙 */
/* 1-1. 동일한 범위 내에서 동일한 변수 명을 가질 수 없다. */
		
int age = 20;
// int age = 30; //위와 동일한 변수 명을 가지므로 에러 발생
		
        
/* 1-2. 예약어는 사용 불가능하다. */
// boolean true = true;
// int int = 10; //예약어를 사용했기 때문에 오류발생
		
        
/* 1-3. 변수명은 대 소문자를 구분한다. */
int Age = 20;   // 위에서 만든 age와 다른 것으로 취급한다.
int True = 10;  // 예약어 True와 다른 것으로 취급한다.
		
		
/* 1-4. 변수명은 숫자로 시작할 수 없다. */
// int 1age = 20;   // 숫자로 시작해서 에러발생
int age1 = 20;      // 숫자로 시작하지 않는다면 혼용해서 사용가능
		
		
/* 1-5. 특수기호는 '_'와 '$'만 사용 가능하다. */
//int sh@rp = 20;   // 사용 가능한 특수문자 외에는 사용 불가능
int _age = 20;      // 언더스코어는 사용가능함, 처음, 중간, 끝 모두 가능
int $harp = 20;     // $도 사용 가능함, 처음, 중간, 끝 모두 가능
		
        
/* 2. 컴파일 에러를 발생시키지는 않지만 개발자들끼리의 암묵적인 규칙 */
/* 2-1. 변수명의 길이 제한은 없다. */
		
int abcdsfoekposfpoeifpsofieosjfilseflkshlkfjealkjwela;
// 이렇게 짓는다고 해도 컴파일 에러는 뜨지않음, 다만 적당한 길이의 이름 필요
		
/* 2-2. 변수명이 합성어로 이루어진 경우 첫 단어는 소문자, 두 번째 시작 단어는 대문자로 시작한다. */
/* 자바에서는 클래스명만 유일하게 대문자로 시작한다. 그 외의 나머지는 전부 소문자로 작성 */
int maxAge = 20;
int minAge = 10;   //낙타의 등처럼 생겼다고 하여 camel-cage 라고한다.

 

 

 

 

 

상수란?

수식에서 변하지 않는 값을 뜻한다.
  • 변하는 값인 변수와 반대이다. 
  • 컴퓨터(Java)에서는 프로그램이 실행되는 동안 '값이 고정되어 변경할 수 없는 메모리 공간'을 의미
  • 상수 선언 방법 (final 키워드 필요, 더이상 값의 변경이 불가능함을 의미)
 final int AGE;

 

 

상수 초기화 방법
  • 1) 선언과 동시에 초기화
final int NUM =100;
  • 2) 선언 후 초기화
final int NUM;
NUM = 100;

* 중요: 초기화 이후 다른 데이터(값)을 대입할 수 없음

 

 

 

 

 

상수의 명명 규칙

변수와 다르지 않으나 개발자들 간의 암묵적 규칙에서 차이가 있다.
  • 1. 모든 문자는 영문자, 대문자, 혹은 숫자만 사용
  • 2. 단어와 단어 사이는 언더스코어(_)를 사용

(상수와 상수는 대문자로 쓰니까 카멜케이스를 적용할 수 없으므로 언더스코어 사용)

 

< 상수란 ?>
/ * 변수가 메모리에 변경할 값을 저장하기 위한 공간을 나타낸다면, 상수는 이와 상반되는 개념이다.
* 변하지 않는 값을(항상 고정된 값을) 저장해두기 위한 메모리상의 공간을 상수라고 한다.
 * 
 *  상수의 사용목적
 *  변경되지않는 고정된값을 저장할 목적으로 사용한다.
 *  초기화 이후 값 대입시 컴파일 일어를 발생시켜 값이 수정되지 못하게 한다.
 *  예) 수학 공식에 사용되는 수치 등 
 *  
 *  사용방법
 *  1. 상수를 선언한다. (변수선언과 유사하지만 final 키워드 사용)
 *  2. 값을 초기화 한다. (초기화 이후에는 값 변경 불가능)
 *  3. 필요한 위치에 상수를 호출해서 사용한다.
 *  */
		
		
/* 1. 상수 선언 */
final int AGE;
		
        
/* 2. 초기화 */
AGE = 20;
//AGE = 30;   

//  The final local variable AGE may already have been assigned 라는 메세지가 뜸 
// 한 번 초기화 한 이후 값을 재대입하는 것은 불가능하다. 
		
		
/* 3. 필요한 위치에 상수를 호출해서 사용한다. */
/* 3-1. 출력 구문에서 사용 */

System.out.println("AGE의 값 : " + AGE);
		
        
/* 3-2. 필요시 연산식에 호출해서 사용 */

System.out.println("AGE의 2배 : " + (AGE *2));
		
        
/* 3-3. 대입 연산시 활용 */
int sum = AGE;   // 대입 연산자의 오른 편(재정의X)에는 기술 가능함

 

< 상수의 명명 규칙 >
/* 상수의 명명 규칙은 변수의 명명규칙과 컴파일 에러를 발생시키는 규칙은 동일하다
 * 단, 개발자들 끼리의 암묵적인 규칙에서 일부 차이를 보인다. 
 *  
 * 1. 모든 문자는 영문자 혹은 대문자 혹은 숫자만 사용한다.
 * 2. 단어와 단어의 연결은 언더스코어(_)를 사용한다. (camel-case가 아니기에)
 * */
		
		
/* 1. 모든 문자는 영문자 대문자 혹은 숫자만 사용한다. */
final int AGE1 = 20;
final int AGE2 = 30;
final int age3 = 40;   // 소문자로 사용은 가능하지만 변수와 구분하기 힘들기 때문에 만들어진 규칙이다. 
		
		
/* 2. 단어와 단어 연결은 언어스코어(_)를 사용한다. */
final int MAX_AGE = 60;
final int MIN_AGE = 20;
final int minAGE = 30;      //camel case 사용이 가능하지만 역시 변수와 구분되지 않는다.

 

 

 

 

변수를 사용할때 주의해야하는 점들 1

 

데이터 오버플로우
  • 1byte 는 8 bit 
A              
  • A 가 0일시 - 양수 
  • A 가 1일시 - 음수
  • 허용된 범위 이상의 비트를 침범하게 되는 것을 오버플로우라고 함

예) 전자시계가 표현할 수 있는 범위 (00~23 / 00~59 / 00~59) 처럼 표현 할 수 있는 범위가 정해져 있으며(-128 ~ 127) 이를 넘어갈시 초기화됨

 

 

위의 것을 암기할 필요는 없다. 다만 유의할 점 
데이터는 제한된 범위를 가지고 할당되기때문에 알맞은 값의 범위를 쓰지않으면 예상하지못한 결과가 나올 수 있다. 오버플로우라는 현상에 대해서는 이해하고 넘어가야 한다. 

 

 

컴퓨터의 음수처리
  • 컴퓨터는 2의 보수법이라는 개념과 MSB를 사용하여 음수를 처리
  • 2의 보수법을 하기 위해서는 2진수에 1의 보수를 적용하고 이후 2의 보수를 구하여야 함

 

< 오버플로우 >
/* 자료형 별 값의 최대 범위를 벗어나는 경우
 * 초과한 값을 버림처리하고 sign bit를 반전시켜 최소값으로 순환시킴 */
		
byte num1 = 127;
System.out.println("num1 : " + num1);    //127: byte의 최대 저장 범위

num1++;     // 1증가
		
System.out.println("num1 overflow : " + num1);
// -127 : byte 의 최소저장 범위

콘솔창에서 127에 1을 증가시킨값이 최소값 -128로 순환된 것을 통해 오버플로우 현상을 확인 해 볼 수 있다.

 

 

 

< 언더플로우 >
/* 오버플로우의 반대개념으로 최소범위보다 작은 수를 발생시키는 경우 발생하는 현상 */
		
// byte num2 = -129;
// 컴파일 에러가 다음과 같이 뜬다./
// Type mismatch: cannot convert from int to byte 범위를 벗어났다는 의미
		
byte num2 = -128;
System.out.println("num2 : " + num2);      //-128 : byte의 최소 저장범위
		
num2 --;
System.out.println("num2 underflow : " + num2);    //127 : byte의 최대 저장 범위
		
/* 이러한 오버 플로우와 언더플로우가 발생한다고 해서 컴파일 에러나 런타임 에러가 발생하지않는다.
* 그렇기에 최대값 혹은 최소값 범위를 고려해서 코드를 작성해야 한다. */
		
/* 일반적으로 많이 사용하는 int 값의 최대값은 대략 21억 정도이다.
 * 이 범위를 벗어난 계산은 오버플로우를 발생시켜서 원하지 않는 결과값이 나오게 될 수 있다.
 *  */
		
int firstNum = 1000000;        //100만
int secondNum = 700000;        //70만
		
int multi = firstNum * secondNum;      //7천억이 나와야 함
		
System.out.println("firstNum * secondNum = " + multi);
//firstNum * secondNum = -79669248    
//실제로 콘솔창에 출력된 값 

		
/* 이런 현상이 발생해도 그냥 넘기는 경우가 발생할 수 있다.
* 이런 경우를 논리적 에러라고 표현한다. (디버깅시 가장 힘든 이유중 한가지)
*/
		
/* 해결방법 */
/* 오버플로우를 예측하고 더 큰 자료형으로 결과값을 받아서 처리한다. 
 * */
		
long longMulti = firstNum * secondNum; 
		
System.out.println("longMulti = " + longMulti);
		
/* 이미 오버플로우 처리 된 결과를 가지고 변수에 담기 때문에 int와 long의 결과 차이가 없다.
	* 그렇다면 계산이 처리 되기 전에 long타입으로 자료형을 변경해주어야 한다. (강제형변환 이용) 
	* */
		
//정정된 코드
long result = (long) firstNum * (long) secondNum;
System.out.println("result : " + result);
// 정상적으로 7천억이 출력된다.

 

오버플로우와 언더플로우라는 논리적 오류가 발생할 수 있으므로 어떤 변수의 데이터 타입이 필요한지 값의 범위를 고려한뒤 유의하며 코드를 작성해야 한다.

 

 

 

 

 

변수를 사용할때 주의해야하는 점들 2

형변환 (casting)
  • - 값(Data)의 자료형을 바꾸는 것 (boolean 제외)
  • - 컴퓨터의 값 처리 원칙 : 
같은 종류 자료형만 대입 가능
같은 종류 자료형만 계산 가능
계산의 결과도 같은 종류의 값이 나와야 함
  • ☞ 이러한 원칙이 지켜지지 않은 경우에 형 변환이 필요함

 

  • 즉, 형변환이 왜 필요한가? 에 이러한 답변이 됨 
컴퓨터는 같은 종류의 자료형 끼리만 대입을 할 수 있으며, 같은 종류의 자료형 끼리만 계산할 수 있으며, 계산의 결과도 같은 종류의 값만 나와야 한다는 원칙때문에 다른 타입의 형태들을 통일하는 과정이 필요함

 

  • 형변환 예시
123456789 (int) → 123456789.0 (double)
'A' (char) → 65 (int)
3.14f (float) → 3 (int) 
  • 형변환 하고자 하는 값과 자료형의 표현 범위 차이에 따라 형변환 방법이 나뉨 (자동 형변환, 강제 형변환)

 

 

 

 

 

자동 형변환

컴파일러가 자동으로 값의 범위가 작은 자료형을 값의 범위가 큰 자료형으로 변환
  • 자바는 같은 데이터 타입끼리만 연산을 수행하기 때문이다.
1byte   2byte   4byte   8byte   4byte   8byte
byte short int long float double
    char              

 

< 데이터 형변환 >
/* 데이터 형변환이 필요한 이유
 * 자바에서 다른 타입끼리의 연산은 피연산자들이 모두 같은 타입인 경우 실행할 수 있다.
 * 즉, 같은 데이터 타입 끼리만 연산을 수행할 수 있다. */
		
/* 1. 자동형변환 규칙 테스트 */
/* 1-1. 작은 자료형에서 큰 자료형으로는 자동 형변환 된다. */
/* 작은 자료형에서 큰 자료형으로 공간만 옮기는 경우 데이터 손실이 발생하지 않기 때문에 컴파일러가 자동으로 처리해준다. */
/* 1-1-1. 정수끼리의 자동 형변환 */
/* 점점 더 큰 자료형으로 데이터를 옮겨도 문제 없이 자동 형변환 처리된다. */
		
byte bnum =  1;
short snum = bnum;
int inum = snum;
long lnum = inum;
// 컴파일러가 자동으로 처리해주기 때문에 컴파일 에러가 뜨지않는다.
		
		
/* 연산시에도 자동으로 큰 쪽 자료형에 맞춰서 계산한다. */
int num1 = 10;
long num2 = 20;
		
// int result = num1 + num2;
//컴파일 에러 메세지
// Type mismatch: cannot convert from long to int
// 자동으로 큰 쪽 자료형인 long 으로 변경 하여 계산되기 때문에 int형 변수에 담을 수 없다. 
		
long result1 = num1 + num2;
// int + long은 서로 다른 자료형이라 데이터 손실이 발생하지 않는 한 int ->long 변환을 자동 수행 후 연산한다. 
		
System.out.println("result1 : " + result1);    //정상 수행
		
		
/* 1-1-2. 실수끼리의 자동 형변환 */
float fnum = 4.0f;
double dnum = fnum;
		
		
/* 연산 시에도 자동으로 큰 쪽 자료형에 맞춰서 계산한다. */
//float result2 = fnum + dnum;
//double을 float 형 변수에 담을 수 없다.
double result2 = fnum + dnum;
		
System.out.println("result2 : " + result2);
/* 1-2. 정수는 실수로 자동 형변환 된다. */
/* 정수를 실수로 변경할 때 소수점 자리수가 없어도 실수 형태로 표현 가능하다. 
* 이 때 데이터 손실이 없기 때문에 자동 형변환이 가능하다.
 * 정수는 실제 값을 저장하는 매커니즘을 가진 것과 달리 실수는 지수부와 가수부를 따로 나눠서 작성하기 때문에
 * 바이트 크기보다 훨씬 더 많은 값을 표현할 수 있다.  */
		
long eight = 8;
float four = eight;
		
System.out.println("four : " + four);
		
		
/* 따라서 실수와 정수의 연산은 실수로 연산 결과가 반환된다. */
float result3 = eight + four;
		
System.out.println("result3 : " + result3);
		
		
/* 1-3. 문자형은 int형으로 자동 형변환 된다. */
char ch1 = 'a';
int charNumber = ch1;
		
System.out.println("charNumber : " + charNumber);
		
		
/* char가 가지는 범위 안의 정수는 char형 변수에 기록 가능하다. */
char ch2 = 65;
System.out.println("ch2 : " + ch2);
		
		
/* 1-4. 논리형은 형변환 규칙에서 제외된다. */
/* 어느 자료형이든 boolean을 형변환해서 담을 수 없다. */
		
boolean isTrue = true;
//byte b = isTrue;
//short s = isTrue;
//int i = isTrue;
//long l = isTrue;
//char c = isTrue;
//float f = isTrue;
//double d = isTrue;

 

 

 

강제 형변환

값의 범위가 큰 자료형을 값의 범위가 작은 자료형으로 변환
  • 강제 형변환 시 데이터 손실이 발생할 수 있음
    -> 데이터의 변형, 손실을 감수하고 강제 변환
  • 캐스트 연산자를 이용하여 형변환 한다. ex: (바꿀자료형) 값; 
int num = 290;
byte num2 = (byte) num;

 

/* 강제형변환 */
/* 바꾸려는 자료형으로 캐스트 연산자를 이용하여 형변환한다. */
/* 예) (바꿀자료형) 값; 
 * */
		
/* 자동형변환 규칙의 반대 상황에서 강제 형변환이 필요하다. */
/* 1-1. 큰 자료형에서 작은 자료형으로 변경 시 강제 형변환이 필요하다. */
/* 1-1-1. 정수끼리의 강제 형변환 */
long lnum = 8L;
//int inum = lnum;      //데이터 손실 가능성을 컴파일러가 알려준다. (에러발생)
int inum = (int)lnum;   // 변경하려는 자료형을 명시하여 강제형변환을 해야 함
short snum = (short) inum;
byte bnum = (byte) snum;
		
		
/* 1-1-2. 실수끼리의 강제 형변환 */
double dnum = 8.0;
// float fnum = dnum;   //데이터 손실 가능성을 컴파일러가 알려준다. (에러발생)
float fnum = (float) dnum;
		
		
		
/* 1-2. 실수를 정수로 변경시 강제 형변환이 필요하다. */
float fnum2 = 4.0f;
long lnum2 = (long) fnum2; //데이터 손실 가능성을 컴파일러가 알려준다. (에러발생)
// float는 4byte, long은 8byte 임에도 자동형변환 불가능 (소수점 자리 이하 데이터 손실 가능성)
		
		
		
/* 1-3. 문자형은 int 미만 크기의 변수에 저장할 떄 강제 형변환이 필요하다. */
char ch = 'a';
byte bnum2 = (byte) ch;
short snum2 = (short) ch; // 같은 2byte 인데 왜 강제 형변환을 해야할까? 
//답은 부호비트 (sign bit) 로 인한 값의 범위가 다르기 때문이다.
		
		
/* 1-4. 논리형은 강제 형변환 규칙에서도 제외된다. */
/* 강제형변환을 해도 전부 에러난다. */
boolean isTrue = true;
// byte b = (byte) isTrue;

 

/* 자동형변환과 강제형변환을 이용한 다른 자료형끼리의 연산 */
/* 다른 자료형 끼리의 연산은 큰 자료형으로 자동 형변환 후 연산 처리 된다. */

int inum = 10;
long lnum = 100;
		
		
/* 방법1. 두 수의 연산결과를 int형으로 변환 후 int 자료형 변수에 리턴받는다. */
	int isum = (int) (inum + lnum);
		
/* 방법2. long형 값을 int로 강제 형변환 한다. */
	int isum2 = inum + (int) lnum;
		
/* 방법3. 결과 값을 long형 자료형으로 받는다(자동 형변환 이용) */
	long lsum = inum + lnum;
		
		
/* 주의! int 미만의 연산의 처리결과는 int형이다. */
	byte byteNum1 = 1;
	byte byteNum2 = 2;
	short shortNum1 = 3;
	short shortNum2 = 4;
		
	//byte result1 = byteNum1 + byteNum2;   
	int result1 = byteNum1 + byteNum2;     //byte + byte => int
	//short result2 = byteNum1 + shortNum1;
	int result2 = byteNum1 + shortNum1;    //byte + short => int
	//short result3 = shortNum1 + shortNum2;
	int result3 = shortNum1 + shortNum2;   // short + short => int

	//int미만이어도 결과는 int로 저장되기 때문에 더 작은 단위에 저장할 수 없다.

 

다른 자료형간의 연산
(1) 낮은 자료형으로 맞출 시 : 낮은 자료형으로 강제 형변환
(2) 높은 자료형으로 맞출 시 : 높은 자료형으로 자동형변환
* 단, byte와 short 자료형 값의 계산 결과는 무조건 int로 처리

 

 

 

 

 

형변환 사용시 유의할 점

데이터 손실에 유의하며 사용해야 한다. 
/* 형변환 사용 시 주의할 점 */
/* 데이터 손실에 유의해서 사용해야 한다. */


/* 1. 의도하지 않은 데이터 손실 */
int inum = 290;
byte bnum = (byte) inum;
		
System.out.println("inum : " + inum); //290 값 도출
System.out.println("bnum : " + bnum); //34 값 도출
// 비트 앞부분 손실로 예측 어려움
        
        
/* 2. 의도적인 데이터 손실 */
double height = 175.5;
int floorHeight = (int) height;
System.out.println("height : " + height);
System.out.println("fllorHeight : " + floorHeight);
// 의도적으로 소수점 절삭에 활용할 수도 있다.
  • - 개념적으로 언급했던 부분을 잘 암기하고 숙지 해 두어야 한다. 
  • - 이 부분을 잘 숙지한채로 프로그래밍에 들어가는 것이 너무나 중요

 

 

 

 

 

 

더보기

학습점검

 

✅ 리터럴과 리터럴의 종류에 대해 이해하고 설명할 수 있다.
✅ 리터럴의 연산 처리에 대해 이해할 수 있다.
✅ 문자열 처리에 대해 이해할 수 있다.
✅ 변수의 사용 목적을 이해할 수 있다.
✅ 변수를 이해하여 선언할 수 있다.
✅ 기본자료형의 byte size를 암기할 수 있다.
✅ 상수를 이해하고 선언할 수 있다.
✅ 변수와 상수의 명명규칙에 대해 이해하고 적용할 수 있다.
✅ 데이터 오버플로우에 대해 이해할 수 있다.
✅ 형변환을 해야 하는 이유에 대해 이해할 수 있다.
✅ 자동형변환이 일어나는 조건에 대해 이해할 수 있다.
✅ 강제형변환을 이해하고 적용할 수 있다.

 

 

 

 

 

산술 연산자

사칙연산과 관련 된 연산자로 가장 기본적이면서도 많이 사용되는 연산자
  • 연산에 필요한 값이나 변수가 두 개인 이항 연산자
  • 우선 순위에 따라 연산되어 결과가 산출 됨  (반드시 왼쪽에서 오른쪽의 순서가 아닐 수도 있다. )
  • 기본적인 피연산자들의 연산 방향은 왼쪽에서 오른쪽
  • num % 2 에서 나올 수 있는 경우의 수는 0과 1이 있다. 짝수라면 0으로 홀수라면 1로, 나중에 짝 홀수를 판단할 때 사용 된다. 짝/홀과 배수의 개념과 연관된다. 

 

/* 산술 연산자 */
/* 산술 연산자는 주로 사칙연산과 관련 된 연산자로 가장 기본적이면서도 많이 사용되는 연산자이다. 
* 연산자의 실행이 가능하기 위해 필요한 값이나 변수가 두개인 이항 연산자로 분류되며
* 피연산자의 연산 방향은 왼쪽에서 오른쪽이다. 
* */
		
		
		
/* 산술 연산자의 우선순위 
 * 수학의 개념과 유사하게 곱하기와 나누기 연산이 더하기와 빼기 연산보다 우선적으로 동작한다. 
 * */

int num1 = 20;
int num2 = 7;
		
System.out.println("num1 + num2 = " + (num1 + num2));   
//소괄호를 작성하지않으면 연산이 되지않고 문자열이 합쳐진다. 	

System.out.println("num1 + num2 = " + (num1 - num2));
System.out.println("num1 + num2 = " + num1 * num2);   
//곱셉은 우선순위가 우선하기 때문에 괄호로 감싸지 않아도 된다. 

System.out.println("num1 + num2 = " + (num1 / num2));
System.out.println("num1 + num2 = " + (num1 % num2));

 

 

 

 

 

복합 대입 연산자

 다른 연산자와 대입 연산자가 결합한 것
  • 자기 자신의 값과 연산 후 연산 결과를 자기 자신에게 누적 대입
  • 복합 대입 연산자 사이에 스페이스를 누르지 않도록 주의, 붙여진게 하나의 형태이다. 
  • 증감 연산과 비슷해 보이지만 증감연산자(++, —)는 1씩 증가

 

a +=10  = a = a + 10
a -=10 a = a - 10
a *=10 a = a * 10
a /=10  a = a / 10
a %=10  a = a % 10

 

/* 대입연산자와 산술 복합 대입 연산자 */
int num = 12;
System.out.println("num : " + num);
		
//3증가시
num = num + 3; // 대입연산자의 오른쪽에는 값, 왼쪽에는 값을 저장할 공간
System.out.println("num : " + num);   //15
		
num += 3;   // num = num + 3; 과 같은 의미
System.out.println("num : " + num);   //18
		
num -= 5;
System.out.println("num : " + num);   //13
		
num *= 2;
System.out.println("num : " + num);   //26
		
num /= 2;
System.out.println("num : " + num);   //13
		 
		
/* 주의! 산술 복합 대입연산자의 작성 순서에 주의해야한다. */
/* 산술 대입 연산자가 아닌 num에 -5를 대입한다는 의미가 되는 것이다. */
//만약 복합 대입연산자의 순서를 바꿔 쓴다면?

num =- 5;
System.out.println("num : " + num);   //-5

 

 

 

 

 

 

 

 

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

메소드  (0) 2021.12.22
연산자  (0) 2021.12.21
변수 파트 암기할 표 정리  (0) 2021.12.18
변수  (0) 2021.12.17
프로그래밍 기초  (0) 2021.12.16

+ Recent posts