본문 바로가기
코딩/JAVA

23.02.02 String, interface

by Leedius 2023. 2. 2.

전날 복습

상속 (inheritance)

다형성, 오버라이딩

부모클래스명 객체명 = new 자식클래스생성자();

 

Object클래스

모든클래스의 상위클래스

모든클래스는 Object의 메서드를 사용가능.

 

 

 

 

 

==========================================================================================

 

String

public class String01 {
    public static void main(String[] args) {
        //String 클래스의 객체 생성 방법
        //첫번째 방식
        //문자열이 동일하면 새로운 객체를 만들지 않고
        //메모리 공간을 낭비하지 않도록 같은 데이터를 참조한다
        String str1 = "hello java";
        String str2 = "hello java";
        //보통 클래스를 사용하는 문법에 준하는 문법
        //두번째 방식
        //new 키워드가 새로운 객체를 생성한다는 명령어기 때문에
        //문자열이 같더라도 객체를 새로 생성해준다.
        String str3 = new String("hello java");
        String str4 = new String("hello java");

        //참조변수는 뒤에 .을찍으면 사용가능한 메소드가 나온다
        //참조변수 : 기본자료형이 아닌 참조자료형으로 만든 변수
        //str1.


        //==의미
        //숫자비교에서는 두 수가 같은 수인지를 판별
        //객체비교에서는 두 객체가 동일한 참조값을 가지는지 판별
        //String은 특별하게 정보가 같은 참조변수가 만들때 똑같은 문자열이 있으면
        //이미 만들어진 참조변수와 같은 주소값을 가진다.
        if(str1 == str2){
            System.out.println(1);
        }

        //str3와 str4는 new로 새로운 객체를 만들었기 때문에
        //참조변수를 따로 생성했기때문에 주소값이 달라서
        //다르다고 판별한다.
        if(str3 == str4){
            System.out.println(2);
        }
    }
}
public class String02 {
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new A();

        a1.num = 10;
        a2.num = 5;

        System.out.println(a1.num);     //10
        System.out.println(a2.num);     //5

        //a2가 가지고있는 주소값을 a1에 대입
        //따라서 같은 주소값을 가진다.
        a1 = a2;
        System.out.println(a1.num);     //5
        System.out.println(a2.num);     //5

        a1.num = 10;
        a2.num = 20;

        System.out.println(a1.num);     //20
        System.out.println(a2.num);     //20

        //String은 다른 대부분의 참조변수와 다르게
        //imutable변수이다.
        //imutable변수 - 값이 저장되면 변하지 않는 변수
        //따라서 String의 값을 바꿀때 원래 있던 주소안의 내용이 바뀌는것이아니라
        //새로운 주소를 만들어 값을 저장하고 주소를 바꾼다.
        String str1 = "java";
        String str2 = "java";


        str2 = "c++";
        System.out.println(str1);
        System.out.println(str2);
    }
}

class A{
    int num;
}
public class String03 {
    public static void main(String[] args) {
        //String 클래스에서 선언된 유용한 메소드
        String str1 = "coffee";
        String str2 = "bread";

        //length() -> 문자열의 길이를 리턴
        System.out.println(str1.length());      //6
        //concat() -> 두 문자열을 나열 +와같은기능
        System.out.println(str1+str2);          //내부적으로는 밑의 concat으로 해석한다.
        String result1 = str1.concat(str2);     //coffebread
        System.out.println(result1);

        String str3 = "abcdefg";

        //일부 문자열 추출;
        //2번째 문자부터 마지막까지 추출(자바는 순서를 매길때 0부터 출발)
        String result2 = str3.substring(2);
        System.out.println(result2);        //cdefg
        //1번째 부터 4번째 전까지.
        String result3 = str3.substring(1,4);
        System.out.println(result3);        //bcd

        //숫자들을 문자열로 변환해주는 메소드
        String result4 = String.valueOf(10);

        //문자열 슬라이스
        String str4 = "ab,cd,ef";
        String[] result5 = str4.split(",");
        for(int i = 0; i<result5.length; i++) {
            System.out.print(result5[i] + " ");
        }

    }
}

 

 

==========================================================================================

 

인터페이스(Interface)

자바에서 인터페이스는 클래스들이 필수로 구현해야 하는 추상 자료형.

쉽게 말하자면 객체의 사용방법을 가이드라인 하는 것이라고 생각.

자바의 인터페이스는 추상 메서드와 상수로만 이루어짐

구현된 코드가 없기 때문에 당연히 인터페이스로 인스턴스도 사용할 수 없다. 

 

인터페이스의 구성요소)

-메소드의 선언(내용은 없음)

 

인터페이스의 사용법)

자바에서 인터페이스를 선언할 때는 interface라는 키워드를 붙여서 만듬.

단 이렇게 interface라는 키워드를 붙여 인터페이스로 만들게 되면 오직 implements라는 키워드를 통해 객체들을 구현하는 용도로만 사용이 가능.

또한 인터페이스에는 구체적인 대상을 생성할 수 없고 오로지 상수와 추상 메서드만 사용할 수 있다.

이 메서드는 추상 클래스에서 껍데기만 생성하고 상속하는 자식 클래스에서 오버라이딩하여 사용.

인터페이스 내부의 메소드는 반드시 접근제한자를 public으로 사용해야한다.

그래서 public을 생략하더라도 알아서 public으로 해석한다.

예)

public interface Interface01 {

    public void printName();

}
//클래스를 만들 때 인터페이스를 구현해서 만들 수 가 있는데
//인터페이스에 선언된 메서드를 해당 클래스에서
//반드시 선언해야 한다는 의미.
public class Inter01 implements Interface01 {

    @Override
    public void printName() {

    }
}

 

인터페이스 사용 이유)

-추상 클래스를 통해 객체들 간의 네이밍을 통일할 수 있고 이로 인해 소스의 가독성과 유지보수가 향상됨.

-클래스와 클래스 간의 관계를 인터페이스로 연결하면, 클래스마다 독립적인 프로그래밍이 가능하기 때문.

 

인터페이스 문법에 대한 문법 설명)

 

예제1)

인터페이스TV

public interface TV {

    //전원을 켜는 기능
    public void powerOn();

    //전원을 끄는 기능
    public void powerOff();

    //소리를 높이는 기능
    public void volumeUp();

    //소리를 줄이는 기능
    public void volumeDown();


}

 

 

인터페이스를 이용하지 않은 LgTV의 기능을 가진 클래스 

public class LgTV {
    public void turnOn(){
        System.out.println("엘지 티비 - 전원 킴");
    }

    public void turnOff(){
        System.out.println("엘지 티비 - 전원 끔");
    }

    public void volumeUp(){
        System.out.println("엘지 티비 - 소리 높임");
    }

    public void volumeDown(){
        System.out.println("엘지 티비 - 소리 줄임");
    }
}

 

인터페이스를 이용하지 않은 SamsungTV의 기능을 가진 클래스 

public class SamsungTV {
    public void powerOn(){
        System.out.println("삼성티비 - 전원 킴");
    }

    public void powerOff(){
        System.out.println("삼성티비 - 전원 끔");
    }

    public void soundUp(){
        System.out.println("삼성티비 - 소리 높임");
    }

    public void soundDown(){
        System.out.println("삼성티비 - 소리 줄임");
    }

}

 

인터페이스를 이용한 NewLgTV의 기능을 가진 클래스 

public class NewLgTV implements TV {
    @Override
    public void powerOn() {
        System.out.println("엘지티비 - 전원을 킵니다.");
    }

    @Override
    public void powerOff() {
        System.out.println("엘지티비 - 전원을 끕니다.");
    }

    @Override
    public void volumeUp() {
        System.out.println("엘지티비 - 소리를 높입니다.");
    }

    @Override
    public void volumeDown() {
        System.out.println("엘지티비 - 소리를 줄입니다.");
    }
}

 

인터페이스를 이용한 NewSamsungTV의 기능을 가진 클래스 

public class NewSamsungTV implements TV {
    @Override
    public void powerOn() {
        System.out.println("삼성티비 - 전원을 킵니다.");
    }

    @Override
    public void powerOff() {
        System.out.println("삼성티비 - 전원을 끕니다.");
    }

    @Override
    public void volumeUp() {
        System.out.println("삼성티비 - 소리를 높입니다");
    }

    @Override
    public void volumeDown() {
        System.out.println("삼성티비 - 소리를 낮춥니다.");
    }
}

 

인터페이스를 이용한 각TV들의 기능을 테스트하는 클래스

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

        //인터페이스는 생성자가 없으므로 객체 생성 불가
        //TV t = new TV();

        //인터페이스명 참조변수명
        // = new 인터페이스를 구현한 클래스의 생성자;
        TV tv = new NewSamsungTV();
        tv.powerOn();
        tv.volumeUp();
        tv.volumeDown();
        tv.powerOff();

        TV tv1 = new NewLgTV();
        tv.powerOn();
        tv.volumeUp();
        tv.volumeDown();
        tv.powerOff();
    }
}

 

 

 

 

 

예제2)

 

인터페이스 클래스 MathUtil

public interface MathUtil {
    //매개변수로 받은 두 수 중 작은 수를 리턴.
    int getMin(int a, int b);

    //매개변수로 받은 반지름을 가진 원의 둘레 리턴.
    //단, 매개변수로 들어온 반지름이 음수라면
    //둘레는 0이 되어야 함.
    double getCircleArea(int radius);

    //첫번째 매개변수로 받은 num1수의 num2제곱 값을 리턴
    //첫번째 매개변수 : 3
    //두번째 매개변수 : 2
    // 3^2 = ?
    int getMultiple(int num1, int num2);

}

 

인터페이스의 기능을 구현할 클래스 MyMath

public class MyMath implements MathUtil{

//    이 경우는 pi값을 얼마든지 바꿀수있지만
//    앞에 final을 붙일시 값 변경이 불가능하다.
//    ex final int PI = 10;
//    int pi = 10;
//    public void aaa(){
//        pi = 20;
//        pi = 30;
//    }

    @Override
    public int getMin(int a, int b) {
        int min;
        min=Math.min(a,b);
        return min;
    }

    @Override
    public double getCircleArea(int radius) {
        if(radius<0){
            return 0;
        }
        //Math.뒤에는 여러가지 수학적 상수가 있다.
        return  2 * Math.PI * radius;
    }

    @Override
    public int getMultiple(int num1, int num2) {
        int result=1;
        for(int i = 0; i<num2; i++){
            result=result*num1;
        }
        return result;
    }
}

 

구현된 기능을 테스트할 클래스 MyMathTest

public class MyMathTest {
    public static void main(String[] args) {
        MyMath m1 = new MyMath();
        System.out.println(m1.getCircleArea(5));
        System.out.println(m1.getMin(6,3));
        System.out.println(m1.getMultiple(2,3));
    }
}

 

 

 

 

 

예제3)

 

인터페이스 클래스 MyArrayUtil

//array패키지에 아래의 인터페이스를 구현한 클래스
public interface MyArrayUtil {
    //매개변수로 받은 두 정수형 배열의 모든 요소의 평균을 리턴
    double getTwoArrayAvg(int [] arr1, int[] arr2);

    //매개변수로 받은 배열의 모든 요소가 짝수이면
    //true, 배열 요소 중 하나라도 홀수면 false 리턴
    boolean isEvenArray(int[] array);
}

 

인터페이스의 기능을 구현할 클래스 MyArray

public class MyArray implements MyArrayUtil{
    @Override
    //ex)1 2 3   4 5 6
    public double getTwoArrayAvg(int[] arr1, int[] arr2) {
        int sumArr1 = 0;
        int sumArr2 = 0;
        for(int i = 0; i<arr1.length; i++){
            sumArr1 += arr1[i];
        }
        for (int i = 0; i<arr2.length; i++){
            sumArr2 += arr2[i];
        }
        return (double) (sumArr1+sumArr2)/(arr1.length+arr2.length);
    }

    @Override
    public boolean isEvenArray(int[] array) {
        for(int i = 0; i < array.length; i++){
            if(array[i]%2!=0){
                return false;
            }
        }
        return true;
    }
}

 

구현된 기능을 테스트할 클래스 MyArrayTest

public class MyArrayTest {
    public static void main(String[] args) {
        //우선 MyArray클래스에 객체 생성
        //인터페이스는 객체는 못만들지만 MyArray의 생성자로 인터페이스의 객체 생성은 가능하다.
        MyArrayUtil myArray1 = new MyArray();

        MyArray myArray = new MyArray();

        //!!중요 우선 매개변수 배열을 먼저 만든다
        int[] a = {1,2,3,4,5};
        int[] b = {6,7,8,9,10};
        double result1 = myArray.getTwoArrayAvg(a,b);
        System.out.println(result1);

        //!!우선 매개변수 배열 생성!
        int[] c = {2,2,2,2,2};
        //기능을 만든 MyArray에서 isEvenArray메소드가 boolean이기 때문에 boolean으로 설정
        boolean result2 =myArray.isEvenArray(c);
        System.out.println(result2);

    }
}

 

 

 

 

 

 

예제4)

 

인터페이스 클래스 StudentUtil

//1. 아래 요구사항을 충족하는 메소드를 선언
//2. 완성한 인터페이스를 구현하는 클래스 StudentTest를
//   student 패키지에 만들고, StudentUtil 인터페이스에서
//   선언한 메소드를 구현.
public interface StudentUtil {
    //Student클래스에서 students라는 배열 생성, 두번째는 매겨변수로 이름을 받는도고 했으니 아래와 같이 매개변수 지정
    String getGradeByStudentName(Student[] students, String name);

    //    ==첫번째 기능==
    //    첫번째 매개변수로 받은 다수의 학생 중
    //    두번째 매개변수로 받은 이름을 가진 학생의 점수등급을 리턴
    //    단, 전달받은 이름을 가진 학생이 없는 경우, 등급은 "등급없음"이 된다.
    //    점수 등급 기준
    //     90 <= 점수 <= 100 -> A
    //     80 <= 점수 <= 89 -> B
    //     70 <= 점수 <= 79 -> C
    // 70 > 점수 -> D
    //메소드명 : getGradeByStudentName

    //다수의 학생의 총점을 배열로 리턴하라고 했으니 매개변수는 Student[] student매개변수 지정
    int[] getTotalScoresToArray(Student[] students);
    //==두번째 기능==
    //매개변수로 받은 다수의 학생들의 총점을 배열로 리턴
    //메소드명 : getTotalScoresToArray

    //학생 두명이 매개변수로 들어온다했으니 Student클래스에서 2개 매개변수지정
    //학생 객체를 리턴하라고 했으니 Student클래스를 리턴값으로 입력
    Student getHighScoreStudent(Student stu1, Student stu2);
    //==세번째 기능==
    //매개변수로 두 명의 학생이 전달된다.
    //전달된 두 학생 중 총점이 높은 학생 객체를 리턴하는 메소드
    //단, 두 학생의 총점이 같은 경우는 없다고 가정한다.
    //메소드명 : getHighScoreStudent
}

 

인터페이스의 기능을 구현할 StudentTest

public class StudentTest implements StudentUtil {

    @Override
    public String getGradeByStudentName(Student[] students, String name) {
        String grade = "";
        for(int i = 0; i < students.length; i++){
            //i번의 학생의 이름을 get해서 매개변수로 들어온 이름이랑 같은지 비교한다
            if(students[i].getName().equals(name)){
                int totalScore = students[i].getEngScore()+
                        students[i].getKorScore()+
                        students[i].getMathScore();
                double avgScore = totalScore / 3.0;
                if(avgScore>90 && avgScore <= 100){
                    grade="A";
                }
                else if(avgScore>=80){
                    grade="B";
                }
                else if(avgScore>=70){
                    grade="C";
                }
                else {
                    grade="D";
                }
            }
            //그레이드라는 문자열이 빈글자면
            //최초에 빈문자가 들어있었기떄문에
            if(grade.equals("")){
                grade="등급없음";
            }
        }
        return grade;

    }

    @Override
    public int[] getTotalScoresToArray(Student[] students) {
        //Student[] students가 매개변수로 들어오기때문에 배열의 길이는 students.length
        int[] resultArr = new int[students.length];
        for(int i = 0; i<students.length; i++){
            int totalScore = students[i].getKorScore()+
                    students[i].getEngScore()+
                    students[i].getMathScore();
            resultArr[i]=totalScore;
        }
        return resultArr;
    }

    @Override
    public Student getHighScoreStudent(Student stu1, Student stu2) {
        int max = 0;
        int totalstu1, totalstu2;
        totalstu1 = stu1.getMathScore()+stu1.getEngScore()+ stu1.getKorScore();
        totalstu2 = stu2.getKorScore()+stu2.getEngScore()+stu2.getMathScore();
        if(totalstu1>totalstu2){
            //학생객체를 리턴하라고 했으니 stu1객체 자체를 리턴
            return stu1;
        }
        else {
            return stu2;
        }
    }
}

 

객체의 정보를 저장 할 클래스 Student

public class Student {
    //이름
    private String name;

    //국어점수
    private int korScore;

    //수학점수
    private int mathScore;

    //영어점수
    private int engScore;

    public Student(String name, int korScore, int mathScore, int engScore) {
        this.name = name;
        this.korScore = korScore;
        this.mathScore = mathScore;
        this.engScore = engScore;
    }

    public String getName() {
        return name;
    }

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

    public int getKorScore() {
        return korScore;
    }

    public void setKorScore(int korScore) {
        this.korScore = korScore;
    }

    public int getMathScore() {
        return mathScore;
    }

    public void setMathScore(int mathScore) {
        this.mathScore = mathScore;
    }

    public int getEngScore() {
        return engScore;
    }

    public void setEngScore(int engScore) {
        this.engScore = engScore;
    }

    @Override
    public String toString() {
        return "Student {" +
                "이름='" + name + '\'' +
                ", korScore=" + korScore +
                ", mathScore=" + mathScore +
                ", engScore=" + engScore +
                '}';
    }
}

 

구현된 기능을 테스트할 클래스 RunStudent

public class RunStudent {
    public static void main(String[] args) {
        //!!중요 StudentTest의 기능 들을 활용하기 위한 객체 s 생성
        StudentTest s = new StudentTest();

        //Student클래스에 저장할 students배열 공간 3칸을 만듬
        Student[] students = new Student[3];
        students[0] = new Student("김", 90, 80, 70);
        students[1] = new Student("이", 95, 70, 88);
        students[2] = new Student("박", 90, 91, 76);


        String result1 = s.getGradeByStudentName(students, "김");
        System.out.println(result1);

        //인터페이스의 메서드가 배열로 리턴됨으로 리턴 자료형은 int[]이되고 매개변수는 배열로받는다
        int[] result2 = s.getTotalScoresToArray(students);
        //배열에 저장된 각 학생들의 총점을 순서대로 출력
        for(int i = 0; i<result2.length; i++){
            System.out.print(result2[i]+ " ");
        }
        System.out.println();

        //새로운 Student클래스에 s1, s2객체 생성하는 동시에 초기화
        Student s1 = new Student("김", 80,80,80);
        Student s2 = new Student("이", 70,70,70);

        //s.getHighScoreStudent메서드가 매개변수를 객체로 받아서 매개변수로 객체 s1,s2를 대입
        Student result3 = s.getHighScoreStudent(s1, s2);
        System.out.print(result3.getName()+" ");
        System.out.print(result3.getKorScore()+" ");
        System.out.print(result3.getEngScore()+" ");
        System.out.print(result3.getMathScore()+" ");


    }
}

 

댓글