Java

20.07.01Java_addr domain, 필드변수, Scanner, Prompt, nextLine(), valueOf(), try-catch문, 생성자 초기화, equals()

우롱차 2020. 8. 31. 11:01
728x90

domain 객체

  • 주로 1개의 데이터를 담아서 이동, 처리하는 용도로 사용하는 클래스(객체)들
  • 클래스를 객체로 선언하고 초기화 할 때
  • 호출하는 생성자는 매개변수가 없는 기본 생성자와
  • 필드변수 리스트를 매개변수로 받아서 값을 지정하는 필드생성자를 만들 수 있다.

필드 변수

  • 필드변수가 String을 포함한 primitive(기본형) 변수형 일때는
  • 초기화가 자동으로 이루어진다.
  • 문자열은 "" 으로 숫자는 0으로
 
  • Primitive(기본형) 변수형
    • int, float, double, long, boolean, char
  • Wrapper 클래스(기본 확장형) 변수형
    • Integer, Float, Double, Long, Boolean, Character
  • 특별히 클래스이면서 Primitive처럼 동작하는 변수형
    • String
// 객체가 생성 될 때 필드변수에게 특별히 값을 만들어주고 싶을때
// 임의로 기본 생성자를 만들고
// 필드변수들에 값을 Setting할 수 있다.
public AddrVO() {
this.name = "이름을 입력하세요";
this.tel = "전화번호를 입력하세요";
this.addr = "주소를 입력하세요";
this.age = 0;
this.net = "관계를 입력하세요";
}
 
// 똑같이 void도 없고 매개변수가 생겨짐
// 필드(변수) 생성자
 
* 객체를 초기화하면서 동시에 데이터를 Setting하고자 할 때 호출하는 생성자
 
public AddrVO(String name, String tel, String addr, int age, String net) {
super();
this.name = name;
this.tel = tel;
this.addr = addr;
this.age = age;
this.net = net;
}
 
// 나중에 주소, 나이, 관계 추가하고싶다 해서 이름, 전화번호만 남기고 다 지워봤음
 
* 필드(변수) 생성자
* 객체를 초기화할 때 필수적으로 필요한 이름과 전화번호 값만 저장하여
* 주소를 만들고 싶다
* 이때 호출하여 사용하는 생성자
public AddrVO(String name, String tel) {
this.name = name;
this.tel = tel;
}
// 나이랑 이름만 하고싶다~
public AddrVO(String name, int age) {
this.name = name;
this.age = age;
}
>>>>>>>> domain > AddrVO🙂

Scanner

// Console에 어떤 값을 출력
System.out.println();
// 키보드로부터 전송되어온 이진수를
// 컴퓨터에서 알아볼 수 있는 데이터 코드로 변환
// 키보드로 문자(열)을 입력하는 동안 그 데이터 코드를
// 임시의 저장장치(Buffer)에 저장을 하고 있다가.
// Enter를 누르는 순간 Scanner에게 입력이 완료되었음을 알려주는 역할을 한다.
InputStream in = System.in;
  • InputStream을 Scanner()에 연결하면
  • InputStream으로부터 전송되어온 데이터 코드를
  • 실제의 문자열로 변환시키는 역할을 수행한다.
 
  • InputStream이 입력이 완료되었다는 신호를 보내오면
  • Scanner는 Buffer에 저장된 데이터 코드를 읽어서 (Scan)
  • 문자열로 변환을 시킨다.
// Console에서 값을 입력
Scanner scan = new Scanner(in);
// >>>>>>실제로는 한꺼번에 사용하지만 지금은 우리에게 한번 나누어서 보여준 것!
// nextLine()가 호출되면
// 코드는 여기에서 잠시 멈추고 있으면서 // 멈추고 : 기다리고 있다는 이야기
// 키보드에서 문자열이 입력되고 Enter가 눌리면
// Scanner를 통해서 문자열을 가져오는 역할을 수행한다.
// 입력을 기다리면서 코드가 잠시 wait상태가 되는 현상을
// blocking 되었다 라고 한다.
scan.nextLine();
// >>>>>>>>> 여기서 실행을 바로하면 terminate코드가 빨갛게 되면서 blocking되었음
// 멈추게하려면 콘솔창에 클릭 엔터!
>>>>>>>> scan > ScanEx_01🙂

Prompt

Scanner scan = new Scanner(System.in);
// [prompt(라고 한다)]
// scanner의 nextLine() method가 실행되어 blocking 상태가 되면
// 코드진행이 멈추는데
// 사용자는 무엇을 어떻게 해야할지 당황스럽게 된다.
// 이때 nextLine() method를 실행하기 이전에
// 사용자가 수행할 일을 미리 알려주는 역할을 하는 출력문
System.out.print("영문자열 입력 >> ");
// 키보드에서 문자열이 입력되기를 기다리고 있다가
// 문자열이 입력되면 입력된 문자열을 strInput변수에 담아달라라는 코드
String strInput = scan.nextLine();
System.out.println("입력된 문자열 : " + strInput);
>>>>>>>> scan > ScanEx_02🙂

 

  • Scanner 클래스를 사용하여 객체를 생성하게 되면
  • 키보드 입력장치의 resource가 소모된다.
  • 컴퓨터 입장에서는 resource를 사용하는데 있어서 매우 신중해야 한다.
  • 제한된 resource를 무작위로 사용하게 되면
  • 컴퓨터 입장에서는 매우 불편하게 된다.
 
  • 그래서 일반적으로 어떤 장치와 관련된 resource들은 사용한 후 반드시 종료를 해주어야 한다.(resource 반납)
  • 따라서 scanner도 사용후에는 반납해주는 것이 좋다.
 
  • 단, 최신 java(JDK)에서는 제한된 사용 범위에서는
  • 반납하지 않아도 GC(Gabage Collection)에 의해 반납 처리가 되기는 한다.
Scanner scan = new Scanner(System.in);
scan.nextLine();
// scanner resource 반납
scan.close();
>>>>>>>> scan > ScanEx_03🙂

System.out.print("문자열 입력 >> "); // print를 쓰게 되면 우리가 일반적으로 쓰는 가로형태로 나와서 print로
String strInput = scan.nextLine();
System.out.println("입력된 문자열 : " + strInput);
// 문자로 바로 받은게 아니라 숫자로 변환시켜줌
System.out.print("숫자1 >> ");
int num1 = scan.nextInt();
이렇게 하면 문제가 없는데
>>>>>>>> scan > ScanEx_04🙂
 
  • InputStream의 문제로 인하여
  • 숫자를 scan하는 nextInt() method를 수행한 후
  • 곧바로 이어서 문자열을 scan하는 nextLine() method를 수행하면
  • 내부 메커니즘 문제로 인하여  Buffer에 Enter코드가 남아있다가
  • 곧바로 nextLine() method에게 전달되어버린다.
  • 이때문에 nextInt()를 수행한 후 nextLine()를 수행하면
  • 의도하지않게 코드가 진행된다.
 
  • 이 문제를 해결하기 위해
  • scanner를 통해 키보드를 입력받기 위해서는 nextLine()만 사용하자.
  • 그럼 숫자는?! >> ScanEx_06
Scanner scan = new Scanner(System.in);
System.out.print("숫자1 >> ");
int num1 = scan.nextInt();
System.out.print("숫자2 >> ");
int num2 = scan.nextInt();
System.out.printf("%d + %d = %d ", num1, num2, num1 + num2);
 
System.out.print("문자열 입력 >> ");
String strInput = scan.nextLine();
System.out.println("입력된 문자열 : " + strInput);
>>>> 이렇게 되면 바로 문자열을 입력 할 수가 없음
숫자를 입력받는 메서드와
문자열 입력받는 메서드를 하게되면 이런 오류가 자주 발생한다.
컴퓨터는 내가 엔터를 쳤다고 생각하고 넘어가버리게 되는 것
>>>>>>>> scan > ScanEx_05🙂

 


nextLine() method

  • scanner를 사용해서 nextInt(), nextLine() 메서드를 섞어서 사용하면
  • 내부 문제로 인한 의도하지 않는 코드 진행이 되어
  • 숫자, 문자 모두 문자열을 입력받는 nextLine()메서드로 통일하여 사용한다.
 
  • Scanner의 내부 문제에 의한 코드 진행의 문제를 해결하기 위해
  • 키보드로부터 값을 읽는 method를 nextLine()만 사용하기로 하였다.
  • 그런데 숫자를 2개 입력받아 덧셈을 수행한 후
  • 결과를 보고 싶은 코드를 작성하고 나니
  • 숫자의 덧셈이 아닌 숫자형 문자열의 연결을 만다는 코드가 되어버렸다.
 
  • 만약 키보드에서 입력받은 문자열을 숫자형(int, float)으로 변환할 수 있다면
  • nextLine()을 사용하여 원하는 결과를 얻을 수 있을 것이다.
// Integer.valueOf() method를 사용하여 숫자형으로 된 문자열 데이터를 정수형 데이터로 변환
int intNum1 = Integer.valueOf(strNum1);
>>>>>>>> scan > ScanEx_06🙂

valueOf() : 숫자형 문자열을 정수로 변환시키는 method

  • 숫자형 wrapper class의 valueOf() method를 사용하면
  • 숫자형 문자열을 숫자형 데이터로 변환 시킬 수 있다.
 
  • 오래된 java버전에서는 valueOf(), parse*()method의 성능차이가 있었으나
  • java 1.6이상에서는 내부 메커니즘이 같아져 성능차이가 없다.
Integer.valueOf("34"); // 정수 34
Float.valueOf("34.3"); // 실수형로 변환시키는
Double.valueOf("34.3");
Long.valueOf("333333"); // 숫자형 문자열을 실제 숫자로 변환시켜주는 메서드들
>>>>>>>>>>>>>>>> 1.5이후에 이걸 써도 아무런 문제 없으니까
>>>>>>>>>>>>>>>> 우리가 사용할 것들은 valueOf
// 두개의 성능이 같다.라고 보면 된다. 굳이 parse는 안써도 됌.
Integer.parseInt("34");
Float.parseFloat("34.3");
Double.parseDouble("34.3");
Long.parseLong("3333"); // >>>> 자바 1.5 이전부터 사용되던 method
>>>>>>>>>> 이런게 있다고 생각
 
  • 아래와 같은 경우는 모두 NumberFormatException을 일으키는 코드
Integer.valueOf(""); // >>> 가장 많이 문제가 되는 코드 (아무것도 없이 엔터만 누르는) 
Integer.valueOf("34 "); // 숫자 앞, 뒤에 white space 문제 (spacebar 빈칸이 들어가있는 경우) 
Integer.valueOf("A34"); // 숫자 앞, 뒤에 숫자형 이외의 문자열이 있는 경우 
Integer.valueOf("3 4"); // 숫자 중간에 space, 숫자형 이외의 문자열이 있는 경우 
Integer.valueOf("3+4"); // 하나의 문자열이 연산식처럼 보일 때
>>>>>>>> exec > Number_Ex🙂

try-cathc문 사용하는 건 사용자를 배려하는 가장 좋은 개발자의 자세이다.

Exception Handling

  • exception이 발생할 가능성이 1/100만 라도 있으면
  • try-catch문을 사용하여 Handling(처리)를 수행하여
  • 사용자가 어플을 사용하는데 혼란, 어려움을 겪지않도록 해주어야 한다.
try {
// TODO: handle exception
// 지금부터 이코드를 실행해봐라
intMenu = Integer.valueOf(strMenu);
} catch (Exception e) {
//exception 이 발생하면
System.out.println("입력한 값 : " + strMenu);// 사용자가 잘못 입력한값을 다시 보여주면서 안내메시지같이 보여주는 
System.out.println("업무 선택은 숫자 1 ~ 3 또는 -1만 가능!!!!");
return; // exception이 발생했으니 더이상 다음으로 코드 진행을 하지말고 종료하라.
}
>>>>>>>> scan > ScanEx_08🙂

 


생성자 초기화하는 방법

  • List<AddrVO> addrList;
  • 리스트 클래스를 이용해서 addrList 변수 선언만 한 것
    • 현재 AddrService01 클래스를 선언하면서
    • addrList라는 필드변수를 선언 해둔 상태
    • 선언만 된 필드변수 중에 객체형태의 변수는
    • 그 변수에 값을 저장, 추가하려고 하면 NullPointerException이 발생하면서 코드가 진행되지 않는다.
 
    • 아래의 1 ~ 3의 방법으로 반드시 변수를 초기화 해주어야 한다.
    • 1. 필드변수를 선언과 동시에 초기화 하기 (권장하지 않는 방법)
      • 메모리 관리상 여러가지 문제를 일으킬 수 있기 때문에 가급적 사용하지말자.
    • 2. 생성자를 이용하여 초기화하기 (가장 많이 권장하는 방법)
    • 3. 사용하기 직전에 초기화하기 (권장하지 않는 방법)
 
    • 객체 형태의 변수란 클래스를 사용하여 선언된 변수들
    • (int, float, boolean, double 등 기본 형태의 변수 이외의 형태로 선언된 변수들)
 
  • 1. 필드변수를 선언과 동시에 초기화하는 코드(권장 X)
private List<AddrVO> addrList = new ArrayList<AddrVO>();
 
  • 2. 생성자를 이용하여 필드변수 초기화 하기
  • 이 방식을 주로 많이 사용함!!
// 클래스의 기본 생성자를 임의로 재 작성하기
// 누군가 AddrService01 클래스를 객체로 선언하고
// 초기화를 하기 위해 생성자를 호출하면
// 자동으로 addrList 필드변수가 초기화 되어
// 이후의 코드에서 NullPointerException이 발생하는 것을 방지한다.
public AddrService01() {
this.addrList = new ArrayList<AddrVO>();
}
 
  • 3. 사용하기 직전에 필드변수 초기화하기
public void makeAddr() {
 
// 3. 사용하기 직전에 필드변수 초기화하기.
// 필드변수 사용하기 직전에 초기화 하는 방식은
// 유지보수가 어려워지는 코드가 된다.
addrList = new ArrayList<AddrVO>(); // 썩 좋은 코드는 아님! 문제는 없지만. 2번을 사용하자.
>>>>>>>> service > AddrService01🙂
  • Scanner와 같은 유형의 클래스는 System의 resource를 사용하므로
  • 신중하게 사용하는 것이 좋다.
  • resource 클래스의 경우는 가급적 필드영역에서 직접 초기화 하지말고
  • 생성자 method에서 초기화를 시키는 것이 좋다.
  • 필드영역에서 초기화된 객체들은 현재 클래스의 인스턴스가 만료되어도
  • GC가 작동될 때까지 메모리에 남아있는 경우가 있다
// 생성자에서 초기화된 객체는 현재 클래스의 인스턴스의 수명과 같다.
// 즉 현재 클래스를 사용하여 생성된 인스턴스가 사용이 만료되면
// 생성자에서 초기화된 객체들도 같이 만료(소멸)된다.
public AddrService02() {
addrList = new ArrayList<AddrVO>();
scan = new Scanner(System.in);
}
>>>>>>>> service > AddrService02🙂

 


문자열형 변수 값 비교하는 방법

  • 문자열형 변수는
  • 변수가 생성될 때 실제 문자열이 담기는 변수영역과
  • 문자열이 담긴 변수영역주소를 갖고있는 변수영역 이렇게 2개가 생성된다.
  • 한곳은 실제 값이 담기고, 한곳은 주소가 담긴다.
 
  • 문자열을 == 비교연산자로 비교를 하면
  • 원칙은 주소로 비교를 하나, 어떤때는 문자열 값으로 비교하기도 하고
  • 어떤때는 주소로 비교를 한다.
 
  • 똑같은 문자열임에도 불구하고 결과는 true, false 예측이 어렵다.
 
  • 따라서 문자열은 절대 == 비교연산자로 비교하면 안된다!!!
  • java에서는 !
 
  • 문자열형 변수
    • 기본형 변수와 같은 방식으로 사용을 하지만 태생은 클래스이다.
    • 즉, 문자열형 변수는 String 클래스의 객체(인스턴스)이다.
    • 따라서 String 클래스에 정의된 다양한 method들을 사용할 수 있다는 것이다.
    • 그 중 가장 많이 사용하는 method가 바로 문자열 변수의 값을 비교하는 equals() method이다.
 
    • equals()
    • 문자열형 변수의 저장된 실제 문자열이 같은가를 비교하는 method이다.
    • 문자열이 같으면 true, 그렇지 않으면 false를 retrun하도록 정의 되어 있다.
boolean bYes = str3.equals(str4);
bYes = str4.equals(str3);
//   str4에담겨있는 값하고, str3에 담겨있는 값하고 같냐고
    • equalsIgnoreCase()
    • 영문자일 경우 대소문자 관계없이 문자열을 비교한다.
//   ↓ 바로 값이 인스턴스가됌
System.out.println("Korea".equals("KOREA")); // false
System.out.println("Korea".equalsIgnoreCase("KOREA")); // true
System.out.println("Korea".equalsIgnoreCase("korea")); // true
System.out.println("KOrea".equalsIgnoreCase("KOREA")); // true
 
* 어떤형태든 상관없이 대소문자 상관없이 안의 문자열이 같으면 true
 
>>>>>>>> string > String01🙂

 


While( 1 == 1 ) {}

  • for(;;)과 같은 코드
  • 1 == 1 해도 되는게 while문 조건문이 true면 무한반복하라는 이야기임
  • 숫자 1은 당연히 1이므로 1==1은 결과값이 영원히 true이다.
  • 따라서 while(ture)와 같은 코드가 된다.
// ! : 그 값이 false이면! 이라는 소리임
 
* addrService객체의 inputAddr() method를 호출하고
* 그 결과를 메모리 어딘가에 보관하라.
* 메모리에 보관된 값이 false(!)이면 break를 실행하라
*/
if( !addrService.inputAddr()) {
break;
}
>>>>>>>> exec > AddrEx_04🙂

기본 생성자

  • 아무런 코드도 없는 클래스를 하나 생성하면
  • 클래스 내부에는 기본 생성자라고 하는 특별한 method가 자동으로 선언이 된다.
 
  • 클래스를 사용하여 객체(인스턴스)를 선언하고
  • 초기화를 할 때 생성자( new NewClass_01() )라는 method를 호출하게 되는데
  • 자바에서 클래스를 만들게 되면 모든 클래스에는 자신의 이름과 같은 method가 자동으로 생성된다.
  • 객체를 초기화할 때 이 생성자를 호출하여 초기화를 수행하는 것이다.
 
  • 생성자를 임의로 작성하고자 할 때는
  • 접근제한자를 public으로 설정
  • return type(void, int ... etc)이 없다.
  • 클래스의 이름과 대소문자 일치하도록 작성한다.
 
  • 생성자를 임의로 (재)작성하는 이유
  • 1. 클래스에 선언된 필드변수들을 초기화 위하여
  • 2. 클래스를 객체로 선언하고 초기화 할 때
    • 자동으로 실행될 어떤 일들이 필요할 때
 
  • 클래스를 선언만 하고
  • 임의의 method를 선언하여 사용하면
  • 당연히 기본생성자가 자동으로 생성된다.
 
  • 하지만 필드변수를 외부로부터 주입받아 초기화하는
  • 필드생성자를 만들 경우
  • 기본생성자는 만들어지지 않는다.
//public NewClass_01() {
//
//}
 
// 임의로 생성한 method
public void test() {
}
>>>>>>>> exec > NewClass_01🙂
* 매개변수 int num를 주입받도록 생성자를 선언했기 때문에
* 이 클래스의 기본생성자는 삭제된다.
* 따라서 이 클래스를 사용하여 선언된 객체 인스턴스는
* new NewClass_02(임의의 정수) 형태로 호출되어야 한다.
 
public NewClass_02(int num) {
 
}
>>>>>>>> exec > NewClass_02🙂
* 만약 클래스에 임의의 필드생성자가 필요로하고
* 객체를 초기화할 때 기본생성자도 사용하고 싶을때는
* 필드생성자와 함께 비어있는(blank) 기본 생성자도 만들어 주어야 한다.
* 그래야 기본생성자도 같이 쓸 수 있음!
 
* new NewClass_03() // 기본생성자 호출하여 객체 초기화
* new NewClass_03(0) // 필드생성자를 호출하여 객체 초기화
 
// 기본생성자
public NewClass_03() {
 
}
 
// 필드생성자
public NewClass_03(int num) {
 
}
>>>>>>>> exec > NewClass_03🙂

 


기본 생성자 초기화와 매개변수가 있는 생성자 초기화

public static void main(String[] args) {
 
// NewClass_01 클래스에는 기본생성자를 임의로 만들지 않았지만
// 자동으로 기본생성자가 선언이 되므로
// 생성자를 호출하여 nc 객체를 초기화할 수 있다.
NewClass_01 nc = new NewClass_01();
 
// NewClass_02 클래스에는
// int num 값을 매개변수로 주입받아야하는
// 필드 생성자를 임의로 작성해 두었다.
// 필드 생성자를 임의로 작성을 하게 되면
// 클래스의 기본 생성자는 삭제된다.
// 따라서 이 클래스는 
// new NewClass_02() 생성자를 호출하여 객체를 초기화 할 수 없게 된다.
// 생성자를 호출하여 객체를 초기화 하려면 매개변수로 임의의 숫자를 주입해주어야한다.
// 그래야만 오류가 발생하지 않는다.
NewClass_02 nc2 = new NewClass_02(3);
}
>>>>>>>> exec > NewEx_01🙂
728x90