문제가 일어났을 때 해결하는 방법 고민
초기값은 사용되지 않을 값을 넣은 것이기 때문에 아무런 값도 입력하지 않았을 때 어떻게 표현되게 할 것인지 고민해 보기
입출력용 장치(부품 클래스)
InOutClass - Scanner 없이 입출력장치가능하게 만들기
package View;
import java.util.Scanner;
public class InOutClass {
// 화면에 출력하거나 키보드로부터 값을 받는 기능을 제공하는 부픔 클래스
// 다른 클래스에서는 print와 Scanner를 사용하지 않고 이 클래스에서만 하도록 제한
// 제공 기능
// 1. 출력 : 한줄 출력과 두줄 출력
// 한줄 출력용 메소드, 화면은 문자열
public void olPrint(String str){
System.out.print(str);// 출력 화면이 바뀔 경우 수정하면 되는 부분
}
// 두줄 출력용 메소드
public void tlPrint(String str){
System.out.println(str);
}
// 2. 입력 : 안내문구 출력과 입력, 정수, 실수, 문자열
private Scanner scan = new Scanner(System.in);
// 문자열 입력 메소드
public String inStr(String s){
// 안내 문구 s를 받아서 먼저 출력하고 입력 받기
olPrint(s); // 안내문구 출력
String str = scan.nextLine(); //문자열 입력
return str; // 입력 받은 문자열 넘겨주기
}
// 정수 입력 메소드
// 문자열 -> 정수변환
public int intNum(String s){
int num = -999999;// 생각할 수 있는 최소의 값으로 초기화
String nstr = inStr(s);//문자를 입력하지 않는다. 숫자만 입력
if(!nstr.equals("")){
num = Integer.parseInt(nstr);
}
return num;
}
// 실수 입력 메소드
// 문자열 -> 실수변환
public float intFloat(String s){
float fnum = -0.0000000000001f;
String fstr = inStr(s);
if(!fstr.equals("")){
fnum = Float.parseFloat(fstr);
}
return fnum;
}
}
test - 초기값이 사용되지 않도록 처리해 주기
package View;
public class InOutTest {
static InOutClass ioc = new InOutClass();
public static void main(String[] args) {
// 타이틀 출력
ioc.tlPrint("어떤 프로그램 제목");
int num = ioc.intNum("입력값 : ");
String str = ioc.inStr("문자열 : ");
float fnum = ioc.intFloat("실수 : ");
ioc.olPrint((num + ", " + str + ", " + fnum));
while (true) {
ioc.tlPrint("메뉴>");
ioc.tlPrint("1. 입력");
ioc.tlPrint("2. 출력");
ioc.tlPrint("0. 종료");
num = ioc.intNum("입력 : ");
if(num == 0){
ioc.tlPrint("프로그램 종료");
break;
}
switch (num){
case 1 :
ioc.tlPrint("입력");
break;
case 2 :
ioc.tlPrint("출력");
break;
default:
ioc.tlPrint("잘못 입력하였습니다.");
}
}
}
}
종속된다(Dependency) - 라이브러리
A클래스가 B클래스의 인스턴스를 사용할 때, 'A는 B에 종속된다'라고 말한다. (종속관계)
예) 논문, 참고문헌, InOutClass에 test가 종속된다.
객체 지향의 특성
1. 캡슐화(+ 정보은닉)
in Java -> class = 필드 + 메소드
정보은닉 -> 접근제어자
private사용 - 변수(필드)는 숨긴다.
public사용 - 메소드는 공개한다.
제어자
1) 접근제어자 - public, protected, default, private
2) 기타 제어자(접근제어자 외) - static, final
static - 인스턴스 없이 사용 가능한 필드나 메소드
new로 인스턴스를 만들어 주어야 하는데, 예외적으로 처음 시작할 때 인스턴스를 만들 수 없기 때문에 쓰는 제어자
static이 붙은 필드(클래스변수) - 모든 인스턴스 공유하는 공간, 모든 인스턴스에 같은 값이 적용되도록 사용하는 공간
모든 인스턴스는 생성되면 자기만의 공간을 갖는다.
인스턴스 별로 다른 값을 저장할 때 필드를 사용, 모든 인스턴스가 같은 값을 저장할 때 클래스 변수를 사용
flash파일 - MemberVar
인스턴스 변수는 Heap 영역에 생성 // 예) 카드모양의 값, 카드의 숫자 heart, 7
클래스 변수는 Method 영역에 생성 //설계도, class에 직접적으로 작용한다. static은 하나만 생성 예) 카드의 너비와 높이
// 사용하는 클래스
public class CardTest {
public static void main(String[] args) {
Card c1 = new Card();
c1.kind = "Heart";
c1.number = 7;
Card c2 = new Card();
c2.kind = "Spade";
c2.number = 4;
System.out.println("c1은 " + c1.kind + ", " + c1.number + "이며, 크기는 ("
+ c1.width + ", " + c1.height + ")");
System.out.println("c2은 " + c2.kind + ", " + c2.number + "이며, 크기는 ("
+ c2.width + ", " + c2.height + ")");
// 인스턴스가 공유되는 공간인지 구별 불가
Card c3 = new Card();
System.out.println("c3은 " + c3.kind + ", " + c3.number + "이며, 크기는 ("
+ c3.width + ", " + c3.height + ")");
// 어느 인스턴스를 바꾸어도 모든 값이 바뀐다. 하나로 처리되는 것을 볼 수 있다.
c1.width = 50;
c2.height = 80;
System.out.println("c1은 " + c1.kind + ", " + c1.number + "이며, 크기는 ("
+ c1.width + ", " + c1.height + ")");
System.out.println("c2은 " + c2.kind + ", " + c2.number + "이며, 크기는 ("
+ c2.width + ", " + c2.height + ")");
System.out.println("c3은 " + c3.kind + ", " + c3.number + "이며, 크기는 ("
+ c3.width + ", " + c3.height + ")");
// 클래스 자체변경을 해도 모든 카드의 너비와 높이가 바뀐다.
Card.width = 200;
Card.height = 500;
System.out.println("c1은 " + c1.kind + ", " + c1.number + "이며, 크기는 ("
+ c1.width + ", " + c1.height + ")");
System.out.println("c2은 " + c2.kind + ", " + c2.number + "이며, 크기는 ("
+ c2.width + ", " + c2.height + ")");
System.out.println("c3은 " + c3.kind + ", " + c3.number + "이며, 크기는 ("
+ c3.width + ", " + c3.height + ")");
}
}
// 카드 클래스
class Card {
// 카드의 모양과 숫자는 카드마다 달라야한다.
// 카드의 모양(하트, 클로버, 다이아몬드, 스페이스)
String kind = "Diamond";
// 카드의 숫자
int number = 8;
// 카드의 가로(너비) 세로(높이)
// 똑같아야 하기 때문에 static을 붙인다. 미리 값을 정할 수 있다.
// 인스턴스 없이도 클래스로 접근 가능하다.
static int width = 100;
static int height = 250;
}
스태틱 멤버(변수, 메소드)와 인스턴스 멤버 사용에 대한 제약
1. 인스턴스 멤버는 스태틱 멤버 메소드에서 사용 불가
인스턴스 멤버는 인스턴스 메소드에서만 사용
인스턴스 멤버가 없을 확률이 더 큰데, 불확실한 경우에는 아예 사용되지 않음.
문법적으로 막혀 있음.
2. 스태틱 멤버는 모든 경우에 사용 가능
※ private를 붙이지 않는다.(인스턴스 없이도 사용 가능해야 함, 보호하기 어려움)
인스턴스가 만들어지기 전부터 존재하기 때문에 모든 경우에 사용이
가능한 것,
final 제어자
마지막! (이후 변경 불가 내포) 더 이상 변형할 수 없다.
변수, 클래스, 메소드 앞에 붙일 수 있다.
변수 앞에 붙으면 - 상수(constant), 초기화 후 값 변경 불가
클래스 앞에 붙으면 - 상속을 할 수 없는 클래스
메소드 앞에 붙으면 - 재정의가 안되는 메소드
상수명 작성 요령(권장 규칙)
1. 상수명은 대문자로 작성
2. 스네이크 케이스를 활용
예) final float PI_VALUE = 3.141592f;
메소드의 다형성 : Method Overloading (두 가지 중 하나, 다른 하나는 상속과 관련)
하나의 클래스에 같은 이름의 메소드를 다수 정의하는 것.
(이름은 같은데 제공 기능이 다른 메소드들)
조건
1. 메소드의 이름이 같아야 한다. // 어떻게 구분할 것인가?
2. 매개변수의 개수 또는 자료형이 달라야 한다. // 이름 뒤()
3. 반환형은 고려하지 않는다. // 메소드가 끝나고 난 후에 반환형이 사용되기 때문에 retrun 타입은 고려하지 않는다.
대표 예) System.out.println();
이름이 같고, 매개변수가 같은 경우 오버로딩 불가
public int add(int a, int b){
return a + b;
}
// 같은 이름을 작성 가능, 파라미터로 구분
public int add(int a, float b){
//형변환
return (int)(a + b);
}
// 파라미터의 갯수로 구분
public int add(int a, int b, int c){
return a + b + c;
}
/* 오버로딩 아님, 메소드 중복 정의 오류
public double add(int a, int b){
return (double)(a + b);
}*/
}
생성자(Constructor) <-> 파괴자(Destuctor)는 없음!
인스턴스가 생성될 때 자동으로 호출되는 메소드
인스턴스를 만들 때마다 사용!
인스턴스 생성 문법>
클래스명 인스턴스명 = new 클래스명();
()는 메소드를 호출할 때 사용, 단순히 클래스명을 쓰는 것이 아니라 생성자 메소드를 호출한 것!
생성자 특수성
1) 클래스의 이름과 같은 이름을 갖는다.(대소문자까지 완전 동일)
메소드 명 중 유일하게 대문자로 시작하는 메소드
2) 항상 반환하지 않는다. 그래서 반환형을 사용하지 않는다. (void도 사용하지 않는다. 유일한 예외)
3) 모든 클래스는 최소 하나의 생성자가 있어야 한다. (여러 개의 생성자를 작성할 수 있으나 반드시 하나는 있어야 한다.)
기본생성자(Default Constructor)
생성자 중에서 매개 변수가 없는 생성자 -> 컴파일러가 자동으로 작성해 준다.
단, 아무런 생성자가 없어야 한다.
public Car(String color){
this.color = color;
}
기본 생성자 작성 문법>
접근제어자 클래스명() {}
생성자의 역할
- 인스턴스를 생성할 때 딱 한 번만 호출되는 특수 메소드
=> 필드의 값을 초기화할 때 사용
생성자 작성 시 고려 사항
생성자는 인스턴스의 생성과 관련된 메서드가 때문에 public으로 작성(예외 있음. singleton 패턴)
생성자를 통해 인스턴스 생성을 제한할 수 있음
참고) 필드의 초기화 방법
1. 필드 선언 시 초기화를 같이 하는 방법
private int a = 10;
2. 인스턴스 생성 후 setter 메소드로 값을 대입
// 기본적으로 0에 해당하는 값에 초기화가 되기 때문에 엄밀히 말하면 초기화가 아니지만 처음으로 값을 넣기 때문에 초기화로 본다.
3. 생성자를 사용하여 생성 시 값을 대입
public class ConstructorTest {
public static void main(String[] args) {
Car mycar = new Car();
// 생성자를 통해서 초기화한 값 출력
System.out.println(mycar.getGearType());
System.out.println(mycar.getDoor());
// 사용자가 값을 넣음
mycar.setColor("초록색");
System.out.println(mycar.getColor());
}
}
//
class Car{
private String color;
private String gearType;
private int door;
// 1. setter 사용
// String color 필드와 똑같은 매개변수 사용 시 필드 앞에 this를 붙여주기
public void setColor(String color){
this.color = color;
}
public String getColor(){
return color;
}
// 기본 생성자
// 타입 생략, 클래스명과 똑같이
public Car(){
gearType = "자동";
door = 4;
}
public String getGearType(){
return gearType;
}
public int getDoor(){
return door;
}
}
'공부기록 > Java' 카테고리의 다른 글
4월 17일 Java - 객체지향의 특성 (0) | 2023.04.18 |
---|---|
4월 13일 (2) Java - this, 생성자 오버로딩, 실습 (0) | 2023.04.13 |
4월 12일 (2) Java - 객체지향 (0) | 2023.04.12 |
4월 12일 (1) Java - 데이터 관리 프로그램 (0) | 2023.04.12 |
4월 11일 (2) Java - 변수 용어, 저장 위치 (0) | 2023.04.11 |