매일 조금씩

11/17 - Java (7) : java.util (Calendar, Random, StringTokenizer, Scanner, StringJoiner), 추상 클래스, 인터페이스 본문

빅데이터 플랫폼 구축을 위한 자바 개발자 양성과정

11/17 - Java (7) : java.util (Calendar, Random, StringTokenizer, Scanner, StringJoiner), 추상 클래스, 인터페이스

mezo 2020. 11. 17. 19:09
728x90
반응형

활용 풀이) 주민등록번호 검사

 

입력 로직                          - 입력값 검사

                 1. 14자리

                 ..

                 ..

비지니스(처리)로직        - 처리

출력 로직                          - 출력

 

 

1) 입력값에 대한 에러처리

public class JuminCheck{
    public static void main(String[] args){
        if(args.length != 1){   // 배열의 길이
            // 비정상 처리
            System.out.println("java 클래스명 xxxxxx-xxxxxxx 형식으로 입력하셔야 합니다.");
            System.exit(0);
        }

        if(args[0].length() != 14){ // 문자열의 길이
            System.out.println("14자리를 입력하셔야 합니다.");
            System.exit(0);
        }
        // 정상 처리
        System.out.println("정상");
    } 
}

 

 

입력받은 값인 args는 크기가 1인 배열이다.

args[0]에는 입력받은 주민등록번호가 String으로 들어가 있다. 

따라서 args의 길이는 args.length로 하고 

입력받은 String의 길이는 args[0].length() 로 String의 메소드를 사용한다.

 

 

 

2) 전체 구현

 

public class JuminCheck02{
    public static boolean checkJumin(String jumin){
        String strjumin = args[0].replaceAll("-","");
       
        int[] bits = {2,3,4,5,6,7,8,9,2,3,4,5};
        int sum = 0;
        for(int i = 0; ;i < bits.length; i++){
            sum += Integer.parseInt(strjumin.substring(i,i+1)) * bits[i];
        }
        
        int lastNum = Integer.parseInt(strjumin.substring(12,13));

        int resultNum = (11 - (sum % 11)) % 10;

        if(lastNum == resultNum){
            return true;
        }else{
            return false;
        }
    }
    
    
    public static void main(String[] args){
        if(args.length != 1){   // 배열의 길이
            // 비정상 처리
            System.out.println("java 클래스명 xxxxxx-xxxxxxx 형식으로 입력하셔야 합니다.");
            System.exit(0);
        }

        if(args[0].length() != 14){ // 문자열의 길이
            System.out.println("14자리를 입력하셔야 합니다.");
            System.exit(0);
        }
        
        if(JuminCheck02.checkJumin(args[0])){
            System.out.println("맞다");
        }else{
            System.out.println("틀리다");
        }
        
        
    } 
}

 

 

 

 

 

 

     *** replace()와 replaceAll() 차이

 

 

String 메소드인 replace()와 replaceAll()은 문자이냐 문자열이냐의 차이이다.

replace(바꿔질 문자, 바꿀 문자) 

replaceAll(바꿔질 문자열, 바꿀 문자열) 

이렇게 보았을 때 별 차이 없어 보이지만

replace()는 입력값의 형식이 CharSequence이고

replaceAll()은 String이라는 것에서 차이를 보인다.

 

  String str = "aaabbbccccabcddddabcdeeee";
  String result1 = str.replace("a", "왕").replace("b", "왕").replace("c", "왕");
  String result2 = str.replaceAll("[abc]", "왕");
  System.out.println("   replace result->"+ result1);
  System.out.println("replaceAll result->"+ result2);

 

replace result->왕왕왕왕왕왕왕왕왕왕왕왕왕dddd왕왕왕deeee
replaceAll result->왕왕왕왕왕왕왕왕왕왕왕왕왕dddd왕왕왕deeee

 

^는 not의 의미이다.

[]괄호 안에 [^0-9]처럼 ^가 오면 0부터 9가 아닌 문자/문자열을 말한다.

 


< Javascript, Java C++ 차이 >

1. 배열

javascript, java, c++에서 모두 배열은 참조형태이다.

그러나 java와 c++은 배열이름(arr)으로 호출했을 때 arr[0]의 주소값을 가져오고

javascript는 배열 전체를 가져온다.

 

2. 문자열

String에서

javascript와 c++은 문자열을 문자로된 배열로 취급한다.

(길이 : javascript - stringName.length / C++ - stringName.length() )

반면 java는 String클래스를 사용하여 하나의 객체로 본다. (길이 : java - stringName.length())

 

3. 객체

object(객체)에서는 모두 객체를 배열로 생각하면 된다. 모두 참조형이다. 

 


 

 

 

 

 

 

 

 


 

어제 이어서..

2. Calendar  클래스

2-3 . 날짜 더하기 빼기 ( add메소드)

 

1) 시간 차이

밀리세컨드 단위로 나오기 때문에 연산을 해줘야 원하는 대로 나온다.

ex) /1000 하면 초단위

 

 

 

2) 날짜 차이

다음과 같이 add() 사용

c.add(Calendar.DATE, 1);    // 하루를 더해
System.out.println(c.getTime());

c.add(Calendar.MONTH, -6);  // -6개월 해
System.out.println(c.getTime());

 

 

 

2-4 . 달력 만들기

 

  • 1을 기준점으로 7번씩 회전한다(7이되면 엔터). 마지막날까지.
  • 1일의 요일부터 계산하면 된다.
  • 1일의 요일과 마지막날짜를 알면 달력 만들수 있다.

 

import java.util.Calendar;

public class CalendarEx05{
    public static void main(String[] args){
        int year = 2020;
        int month = 12;

        int startDayofWeek = 0;
        int endDay = 0;

        Calendar sDay = Calendar.getInstance();
        Calendar eDay = Calendar.getInstance();
        
        sDay.set(year, month-1, 1);
        eDay.set(year, month, 1-1);

        // 0 - 일요일 (Date 클래스)
        // 1 - 일요일 (Calendar 클래스)
        startDayofWeek = sDay.get(Calendar.DAY_OF_WEEK);
        endDay = eDay.get(Calendar.DATE);

        System.out.println(startDayofWeek);
        System.out.println(endDay);

        // 세칸이 하나
        System.out.println(" SU MO TU WE TH FR SA");    
        
        // 1일 이전의 공백
        // 일요일부터 시작하는데 
        // 일요일이 1이기 때문에 1부터 함.
        for(int i = 1; i <startDayofWeek; i++){
            System.out.print("   ");    // 공백 세칸
        }
        
        // 달력 출력
        for(int i = 1, n = startDayofWeek; i <= endDay; i++, n++){
            // 한자리수 두자리수 차이가 있어서 칸수 맞춰주기 위함
            System.out.print((i < 10) ? "  " + i : " " + i);
            // 7로 나누어 떨어지면 즉 토요일이면 enter
            if(n % 7 == 0){ 
                System.out.println();
            }
        }

    }
}

 

 

 

 

 

 

 

 

3. Random 클래스

▷p537

  • Math.random() 을 편리하게 만든것이 Random 클래스다.
  • Random(long seed) 로 종자값(seed)을 설정 할 수 있다. 
  • 종자값 없이 Random()으로 해야 실행시마다 다른값이 나온다. 
  • 종자값이 같으면 같은 값이 나온다.
  • Math.random()은 값을 받아서 그걸 조작해야 했지만
  • Random 클래스는 값을 조작하는 메소드를 사용한다.

3-1. 메소드

  • nextBoolean() : boolean 타입의 난수 리턴
  • nextDouble() : double 타입의 난수 리턴
  • nextInt() : int타입의 난수를 리턴
  • nextInt(int n) : int타입의 난수를 리턴(0 <= ~ < n)

실행시킬때마다 다른값들이 출력된다.

import java.util.Random;

public class RandomEx01{
    public static void main(String[] args){
        int [] selectNumber = new int[6];

        Random random = new Random(3);
        for(int i = 0; i<6; i++){
            // 1 ~ 46 까지의 정수 난수
            selectNumber[i] = random.nextInt(45) + 1;
            System.out.println(selectNumber[i] + " ");
        }
        System.out.println();
    }
}

 

 

 

 

 

 

 

 

 

4. StringTokenizer  클래스

default는 공백을 기준으로 자른다.

// 공백 기준(기본)
String data1 = "사과 배 복숭아";
StringTokenizer st1 = new StringTokenizer(data1);

// 특정값 기준
String data1 = "사과&배&복숭아";
StringTokenizer st1 = new StringTokenizer(data1, "&");

// 여러개의 값 기준
String data1 = "x=100*(200+300)/2";
StringTokenizer st1 = new StringTokenizer(data1, "=*+/()");

4-1.  메소드 

  • countTokens() : 토큰 수
  • nextToken() :  다음 토큰을가리킴 (그 다음 그다음.. 계속)
  • hasMoreTokens() : 다음 토큰이 있으면 true, 없으면 false
import java.util.StringTokenizer;


public class StringTokenizerEx01{
    public static void main(String[] args){
        
        String data1 = "x=100*(200+300)/2";

        StringTokenizer st1 = new StringTokenizer(data1, "=*+/()");
        
        System.out.println(st1.countTokens());

        // 다음 토큰이 있으면 다음 토큰 출력
        while(st1.hasMoreTokens()){
            System.out.println(st1.nextToken());
        }
    }
}

 

4-2. Split()과의 차이

split()은 있는 그대로 뽑고

StringTokenizer()는 공백을 없앤다.

 

 

import java.util.StringTokenizer;

// String.split()
public class StringTokenizerEx02{
    public static void main(String[] args){

        String data = "사과&배&&&복숭아";

        StringTokenizer st = new StringTokenizer(data, "&");
        String[] datas = data.split("&");

        System.out.println(st.countTokens());
        System.out.println(datas.length);

        int i = 1;
        while(st.hasMoreTokens()){
            System.out.println(i + " : " + st.nextToken());
            i++;
        }

        i = 1;
        for(String d : datas){
            System.out.println(i + " : " + d);
            i++;
        }
    }
}

 

 

 

 

 

5. Scanner  클래스

5-1. next()  - 문자열 입력

next()에서 입력이 될때까지 기다리다가 enter키가 입려되면 다음이 진행된다.

만약  space바가 입력 값 사이에 입력되면 첫번째 값만 가져온다.

여러개를 입력받고 싶다면 여러개의 next()를 만든다.

String msg1 = sc.next();
String msg2 = sc.next();

만약 입력이 "가나다 마바사"이면 

msg1 : 가나다

msg2 : 마바사

import java.util.Scanner;

public class ScannerEx01{
    public static void main(String[] args){
        // System.in
        Scanner sc = new Scanner(System.in);
        System.out.print("입력 : ");
        String msg1 = sc.next(); // 실제 입력 
        String msg2 = sc.next();
        // enter키가 입력되는 순간 진행
        // space 바에서 끊긴다.
        System.out.println("입력된 메세지 : " + msg1);
        System.out.println("입력된 메세지 : " + msg2);
        sc.close();
    }
}

 

5-2. nextLine()  -  문장 입력

space에서 안끊고 다 저장됨

 

 

 

 

활용) 구구단 출력하기

단수를 입력받아서 구구단 출력 반복하다가 q가 입력되면 중단

 

1) 내코드

import java.util.Scanner;

public class Gugudan{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        while(true){
            System.out.print("단수 입력 : ");

            String msg = sc.next();
            if(msg.equals("q")){
                break;
            }

            int dan = Integer.parseInt(msg);

            for(int i = 1; i <= 9; i++){
                System.out.println(dan + " * " + i + " = " + (dan * i));
            }
        }
        sc.close();
        
    }
}

 

 

2) 강사님 예시 코드 참고 

import java.util.Scanner;

public class Gugudan{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
       do{
            System.out.print("단수 입력 : ");

            String msg = sc.next();
            

            if(msg.equals("q")){
                break;
            }

            int dan = Integer.parseInt(msg);

            for(int i = 1; i <= 9; i++){
                System.out.println(dan + " * " + i + " = " + (dan * i));
            }

        }while(true);

        System.out.println("프로그램 종료");

        sc.close();
    }
}

 

 

 

 

1. java 클래스명 입력

2. java 클래스명

   입력: 

 

 

 

 

 

 

 

6. StringJoiner  클래스

 

String을 합치는 것은 여러가지 방법이 있다.

1) + 연산자 사용

2) format()사용

3) join() 사용

4) StringJoiner클래스 사용

import java.util.StringJoiner;

public class StringJoinerEx01{
    public static void main(String[] args){

        // 문자열 연결
        // 1 - +를 사용하는 방법
        String str1 = "apple" + ",banana" + ",pineapple";
        System.out.println(str1);

        // 2 - format()을 사용하는 방법
        String str2 = String.format("%s,%s,%s", "apple", "banana", "pineapple");
        System.out.println(str2);

        // 3 - 배열과 join()을 사용하는 방법
        String[] arr = {"apple", "banana", "pineapple"};
        String str3 = String.join(",", arr);
        System.out.println(str3);
        
        // 4 - StringJoiner클래스의 add메소드 사용하는 방법
        StringJoiner sj = new StringJoiner(",");
        // sj.add("apple");
        // sj.add("banana");
        // sj.add("pineapple");
        sj.add("apple").add("banana").add("pineapple");
        System.out.println(sj);
    }
}

 

 

 

 

 

 

 

 

 

여기까지 java.util

 


 

 

 

 

 

 

 

 

 

 

 

기타 알아야할 중요한 개념


1. 추상 클래스

▷p329

상속을 받고 싶지 않을 수도 있는데

반드시 상속을 받도록 (상속받아서만 구현할 수 있도록) 하기 위해 필요하다.

추상클래스는 미완성 클래스라고 한다.

 

상속에서 부모클래스를 new로 먼저 생성해줘야 상속하는 자식클래스를 new할 때 상속받을 수 있었지만

추상클래스는 자식클래스를 new하면 자동 생성된다.

 

1-1. 추상 클래스의 용도 

1) 실체 클래스들의 공통된 필드와 메소드의이름을 통일할 목적

 

메소드이름을 자기마음대로 제각기 짓지 못하게 추상클래스에서 메소드명을 고정하고,

그걸 다른 클래스들이 상속받아서 override하게 한다.

 

2) 1번의 이유로 실체 클래스를 작성할 때 시간을 절약

 

 

 

 

1-2. 추상 클래스 선언

부모클래스와 같지만 class앞에 abstract를 붙인다.

미완성이기 때문에 직접적으로 new를써서 인스턴스화 할수 없다.

그렇다면 어떻게 완성을 하냐?

상속을 통해서 완성된다.

 

자식을 인스턴스화 시키면 추상 클래스도 완성된다.

class Parent1{
    Parent1(){
        System.out.println("Parent1 생성자");
    }
}

// 미완성이기 때문에 직접적으로 인스턴스화 할수 없다.
// 어떻게 완성하냐?
// 상속을 통해서 완성한다.
// abstract - 추상 메서드
abstract class Parent2{
    Parent2(){
        System.out.println("Parent2 생성자");
    }
}

class Child extends Parent2{
    // 자식을 인스턴스화 시키면 추상클래스도 완성된다. 
    Child(){
        System.out.println("Child 생성자");
    }
}

public class AbstractEx01{
    public static void main(String[] args){
        Parent1 p1 = new Parent1();
        // Parent1 p2 = new Parent2();        
        Child c = new Child();
    }
}

 

1-2. 추상 메서드

  • 일반클래스는 추상메서드를 가질 수 없다. 
  • 추상클래스만 추상메서드를 가질 수 있다.
  • abstract 클래스는 상속받아야 인스턴스화 되어 쓸수 있고,
  • abstract 메서드는 abstract클래스안에서 선언 되어, abstract클래스를 상속받은 클래스내에서 구현( {} )이 되어야 쓸 수 있다.

말이 복잡하지만 어쨋든 abstract클래스, abstract 메서드 둘다

선언 후에 상속을 통해 상속받은 클래스가 인스턴스화/구현({})을 해줘야 사용되는 것이다.

 

 

 

 

예제) dog, cat을 animal에서 상속받는 코드

 

abstract class Animal{
    String kind;

    void breathe(){
        System.out.println("숨을 쉽니다.");
    }
    
    abstract void sound();
}

class Dog extends Animal{
    Dog(){
        this.kind = "포유류";
    }

    // 나이거 고칠게 ~ 오버라이드 할게~ 하고 java에게 먼저 알려주는것
    @Override   
    void sound(){
        System.out.println("멍멍");
    }
}

class Cat extends Animal{
    Cat(){
        this.kind = "포유류";
    }

    @Override
    void sound(){
        System.out.println("야옹");
    }
}


public class AnimalExample{
    public static void main(String[] args){
        Dog dog = new Dog();
        Cat cat = new Cat();
        dog.sound();
        cat.sound();
        dog.breathe();
        cat.breathe();
        System.out.println("-----");
    }
}

 

 

1-3. 추상 메서드 구현을 자식이 안한다면?

만약 자식이 구현을 안한다면 자식클래스 또한 하나의 추상클래스가 되고 손자가 구현해야 한다. 

이처럼, 상속을 받았다면 손주, 증손 등 꼭 하나에선 구현을 해줘야한다.

abstract class Parent1{
    Parent1(){
        System.out.println("Parent1 생성자");
    }

    // 선언만 여기서 해줌으로서 메서드명을 고정하는 역할만 하며
    // 상속받았다면 꼭 구현해야한다.(자식, 손주, 증손 등 하나에서 꼭 구현해야함)
    abstract void viewParent1();
}

class Child extends Parent1{
    // 아래처럼 메서드를 통해 {}로 구현을 해줘야 만들어진다.
    Child(){
        System.out.println("Child 생성자");
    }
    void viewParent1(){
        System.out.println("viewParent1() 호출1");
    }
}

// 자식클래스
// 만약 자식이 구현을 안한다면? 이또한 추상클래스가 되고 손자가 구현해야한다.
abstract class Child2 extends Parent1{
    // 아래처럼 메서드를 통해 {}로 구현을 해줘야 만들어진다.
    Child2(){
        System.out.println("Child2 생성자");
    }
    
    // viewParent1() 구현 안함

}

// 손주 클래스
class GrandChild2 extends Child2{
    GrandChild2() {
        System.out.println("GrandChild2 생성자");
    }

    // 여기서 viewParent1()을 구현
    void viewParent1(){
        System.out.print("viewParent1() 호출");
    }
}


public class AbstractEx03{
    public static void main(String[] args){
        Child c = new Child();
        
        System.out.println();

        GrandChild2 gc2 = new GrandChild2();
        gc2.viewParent1();
    }
}

 

 

2. 인터페이스

▷p344

자바에서 인터페이스는 객체의 사용 방법을 정의한 타입이다. 

사용하는 목적은 추상화를 넘어서 객체와 개발 코드간의 접점 역할을 한다.

인터페이스는 구현을 위해서 만들었다.

다중 구현이 된다.

 

2-1. 인터페이스 선언

  • class 키워드 대신 interface 키워드를 사용한다.
  • 상수, 추상 메서드만 선언이 가능하다.
  • 접근 제한이 생략되어있으면 public이 생략되어 있는것이다.
public interface RemoteControl {}
// 상수
public static final String STR1 = "홍길동";
// public static final 생략
String STR2 = "박문수"; 

// 추상 메서드
public abstract void methodA();
// public abstract 생략
void methodB();

 

2-2. 인터페이스 구현

  • 클래스는 상속같은 건데  인터페이스는 구현이라고 한다.
  • extends 대신 implements를 사용한다.
  • 자바는 다중상속을 하지 않는데 다중상속을 하기 위해 implements를 만들었다. (다중상속을 위한 편법 - 다중구현)

'ClassA'는 'InterA'를 구현한다.

interface InterA{
    public static final String STR1 = "홍길동";
    public abstract void methodA();
}

class ClassA implements InterA{
    public void methodA(){
        System.out.println("methodA 호출");
    }
}

 

 

구현 코드

// 인터페이스 선언
interface InterA{
    // 선언할 수 있는것 : 상수 , 추상 메서드
    // 상수
    public static final String STR1 = "홍길동";
    // 추상 메서드
    public abstract void methodA();
}

class ClassA implements InterA{
    public void methodA(){
        System.out.println("methodA 호출");
    }
}

public class InterfaceEx01{
    public static void main(String[] args){
        ClassA a = new ClassA();
        a.methodA();
        System.out.print(InterA.STR1);
    }
}

 

 

2-3. 다중 구현

class ClassA implements InterA, InterB{
    public void methodA(){
        System.out.println("methodA 호출");
    }
    public void methodB(){
        System.out.println("methodB 호출");
    }
    public void methodC(){
        System.out.println("methodC 호출");
    }
}

 

 

2-4. 인터페이스 상속

interface InterA{
    String STR1 = "홍길동";
    void methodA();
}

// 인터페이스 상속
interface InterB extends InterA{
    String STR2 = "박문수";
    void methodB();
}

인터페이스를 인터페이스가 상속받을 땐 extends를 쓴다. 

 

 

2-5. 클래스 상속과 인터페이스 구현을 같이

class Child extends Parent implements InterB{

    Child(){
        System.out.println("Child 생성자");
    }

    public void methodA(){  // public생략하면 안됨
        System.out.println("methodA() 호출");
    }

    public void methodB(){
        System.out.println("methodB() 호출");
    }
}

 

 

 

 

2-6. 정적 메소드 선언

interface RemoteControl{
    int MAX_VOLUME = 10;
    int MIN_VOLUME = 0;

    void turnOn();
    void turnOff();
    void setVolume(int volume);

    default void setMute(boolean mute){
        if(mute){
            System.out.println("무음 처리합니다.");
        }else{
            System.out.println("무음 해제합니다.");
        }
    }

    static void changeBattery(){
        System.out.println("건전지를 교환합니다.");
    }
}

class Television implements RemoteControl{
    private int volume;

    Television(){
        System.out.println("Television생성자 호출");
    }

    public void turnOn(){
        System.out.println("TV를 켭니다.");
    }

    public void turnOff(){
        System.out.println("TV를 끕니다.");
    }

    public void setVolume(int volume){
        if(volume > RemoteControl.MAX_VOLUME){
            this.volume = RemoteControl.MAX_VOLUME;
        }else if(volume < RemoteControl.MIN_VOLUME){
            this.volume = RemoteControl.MIN_VOLUME;
        }else{
            this.volume = volume;
        }

        System.out.println("현재 TV 볼륨: " + this.volume);
    }
}

public class RemoteControlExample{
    public static void main(String[] args){
        RemoteControl rc;  // RemoteControl rc; 도 가능
        rc = new Television();
        rc.turnOn();
        rc.turnOff();
        rc.setVolume(7);
        // 위의 호출들만 쓸거면 
        // Television rc; 로 선언해도 됨


        // 아래의 호출 쓰려면 
        // RemoteControl rc; 해줘야함
        rc.setMute(true);
        RemoteControl.changeBattery();  // static     
    }
}

 

 

***  주의해야할 점

interface인 RemoteControl내에 정의된 함수인 setMute(boolean mute)과 changeBattery()호출하려면

객체 rc를 선언 할때 RemoteControl을 구현하는 Television클래스로 선언하면 안되고, 

RemoteControl로 선언해야 한다.

 

interface RemoteControl 내의 메서드 changeBattery()static이므로 rc.changeBattery(); 이 불가능하다.RemoteControl.changeBattery()로 호출해야한다.

 

interface내에 올수 있는 것들은 전부 public이 생략된 형태이므로 override를 할때 public을 써줘야한다. (구현하는 클래스는 접근제한을 안걸어주면  default이기 때문)

728x90
반응형