본문 바로가기

Java

클래스 class

  • 자바에서 생성되는 프로그램의 최소 단위
  • 기능(메소드)과 속성(멤버변수)로 구성
  • 사용자 정의 자료타입
  • 데이터와 기능을 함께 저장할 수 있는 자료구조

객체 지향 프로그래밍 OOP( Object Oriented Programming)

  • 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러 개의 독립된 단위, 즉 "객체"들의 모임으로 파악하고자 하는 것

객체 지향 프로그래밍의 특징

추상화

  • 추상화의 사전적 의미는 특정한 개별 사물과 관련되지 않은 공통된 속성이나 관계 등을 뽑아내는 것
  • 공통의 속성이나 기능을 묶어 이름을 붙이는 것으로 객체 지향적 관점에서 클래스를 정의하는 것
  • 예를 들어, 토끼, 고양이, 사자, 치타가 있을 때 이것들을 각각의 객체라 하며 이 객체들을 하나로 묶으려 할 때 동물 또는 생물이라고 묶는 것
  • 자바에서 추상화란 메소드(기능)와 멤버변수(속성)로 클래스를 만드는 것(설계도, 부모클래스)
  • 자바에서 추상클래스라는 용어는 완성되지 않은 클래스(미완성 설계도)

상속 - 재사용

  • 추상화한 클래스(부모클래스)에 각각의 기능을 추가하거나 재정의하여 새로운 클래스를 정의하는 것을 의미
  • 부모클래스에 정의된 기능은 새로 만들 않아도 사용 가능(재사용)
  • 자바에서는 다중 상속이 되지 않음

캡슐화, 은닉화

  • 캡슐화는 실제로 구현되는 부분을 외부에 드러나지 않도록 캡슐로 감싸 이용방법만을 알려주는것
  • 은닉화는 내부 데이터, 내부 연산을 외부에서 접근하지 못하도록 은닉(hiding) 혹은 격리(isolation)시키는 것
  • 변수에 접근지정자를 private 로 지정
  • setter , getter 를 사용해 변수의 접근, 제어

다형성

  • 하나의 객체가 여러 가지 타입을 가질 수 있는 것을 의미
  • 자바에서는 부모의 클래스형으로 자식의 클래스형를 참조
  • 부모의 클래스를 자식이 오버라이딩 했을 경우 부모의 형으로 자식을 참조하면 자식의 메소드가 실행됨
  • 상속, 인터페이스 구현된 클래스에서 메소드의 인자 전달등에서 다형성이 많이 활용됨

클래스와 인스턴스(instance)

클래스

  • 어떤 문제를 해결하기 위한 데이터를 만들기기 위해 추상화를 거쳐 집단에 속하는 속성(attribute)과 행위(behavior)를 변수와 메서드로 정의한 것

인스턴스(화)

  • 클래스에서 정의한 것을 토대로 실제 메모리상에 할당된 것으로 실제 프로그램에서 사용
  • 참조변수 : new 로 생성된 인스턴스의 주소를 할당 받은 변수

클래스 모델링 및 설계

모델링

  • 클래스의 속성과 기능을 도출하는 단계
  • 특성(속성) : 클래스를 특징 지울 수 있는 성질
  • 기능 : 객체가 할 수 있는 행위

설계

  • 특정 클래스를 정의 하는 것
  • 설계도면을 작성하는 것과 같은 개념

클래스 기본 구성

접근자 class 클래스이름 {
    변수; // 속성, 데이터 필드
    생성자(); // 기본생성자 - 생략가능 
    메서드();// 기능
}

클래스 생성

package chapter07;

public class Member {

}

클래스 사용

  • . 을 통해 속성, 메서드 접근
package chapter07;

public class MemberMain {

    public static void main(String[] args) {

        Member m = new Member();
        Member m2 = new Member();

        if (m == m2) {
            System.out.println("m개체와 m2객체는 같다.");
        } else {
            System.out.println("m개체와 m2객체는 같지 않다.");
        }
    }

}

Car클래스 생성 및 사용

생성
package chapter07;

public class Car {

    // 필드
    String color;
    String company;
    String type;

    // 메서드
    public void go() {
        System.out.println("전진하다.");
    }
    public void back() {
        System.out.println("후진하다.");
    }
}
사용
package chapter07;

public class CarMain {

    public static void main(String[] args) {

        Car tico = new Car();
        Car pride = new Car();

        tico.color = "화이트";
        tico.company = "현대";
        tico.type = "경차";

        pride.color = "블랙";
        pride.company = "기아";
        pride.type = "소형";

        tico.go();
        pride.go();
        System.out.println(tico.color);
        System.out.println(tico.company);
        System.out.println(tico.type);
        System.out.println(pride.color);
        System.out.println(pride.company);
        System.out.println(pride.type);

    }
}

Car클래스 배열에 저장 사용

package chapter07;

public class CarMain2 {

    public static void main(String[] args) {

        // Car 타입의 배열객체 생성
        Car[] cars = new Car[2];

                Car tico = new Car();
        Car pride = new Car();

        tico.color = "화이트";
        tico.company = "대우";
        tico.type = "경차";

                cars[0] = tico;

        pride.color = "블랙";
        pride.company = "기아";
        pride.type = "소형";

                cars[0] = pride;               


        System.out.println("0번 인덱스 color : "+cars[0].color);
        System.out.println("1번 인덱스 color : "+cars[1].color);

        cars[0].color = "블랙"; // 0번 인덱스 객체의 color 필드에 "블랙" 대입

        System.out.println("0번 인덱스 color : "+cars[0].color);
        System.out.println("1번 인덱스 color : "+cars[1].color);

                for(Car car : cars){
                     System.out.println(car.color);
                }
    }
}

데이터 필드

  • 인스턴스 생성시 속성이나 상태값을 저장하는 곳
  • 멤버변수 : 클래스변수와 인스턴스변수로 구분

변수 구분

  • 멤버변수와 지역변수로 구분
클래스변수 - 스태틱(static),전역(global) 변수
  • 클래스가 로드될 때 Class Arae의 Static 영역에 생성
  • 객체 생성 없이 클래스이름으로 바로 참조 가능
  • 변수 선언시 static 키워드 사용
인스턴스 변수 - 필드, 멤버변수
  • static 없는 변수
    • 객체가 생성 될 때 (new) 자동 초기화
    • 힙(heap) 영역에 생성 됨
데이터 타입 기본값
정수 타입 0
실수 타입 0.0
문자 타입 '\U0000'
boolean false
참조형 null
로컬, 지역(local) 변수
  • 멤버변수가 아니면 모두 로컬 변수
  • 메소드나 실행블럭, 제어문 블럭, 초기화 블럭 안에 정의 된 변수
  • 블럭 밖에서 사용 불가
  • 스택(Stack)에 생성되면 메소드 실행 종료 시 자동 소멸
  • 자동 초기화 되지 않음
지역변수 범위 scope
package chapter07;

public class LocalVarTest {

    public static void main(String[] args) {

        int n = 0;

        {
            int a = 10;
        }

        // int b = a; // error 블럭에서 선언된 a 지역변수 

        for(int i=0; i<3; i++) {
            int j = 3;
        }

        // int b = i; error for() 선언된 i, for블럭에 선언된 j 지역변수

    }

    public static void nUse() {
        //int k = n; // main()에 선언된 n 지역변수
    }

}
클래스변수, 인스턴스변수 범위
package chapter07;

class Avante {

    static String company = "현대"; // 클래스 변수
    String color;    // 인스턴스 변수

}

public class VarEx {

    public static void main(String[] args) {

        // 클래스 변수 사용
        System.out.println("Avante 제조사 : "+Avante.company);

        Avante a1 = new Avante();
        Avante a2 = new Avante();

        // 인스턴스 변수의 값 변경
        a1.color = "화이트";
        a2.color = "블랙";

        // 인스턴스 변수 출력
        System.out.println("a1 색상 : "+a1.color);
        System.out.println("a2 색상 : "+a2.color);

        // 클래스 변수를 인스턴스 객체로 출력
        System.out.println("a1 제조사 : "+a1.company);
        System.out.println("a2 제조사 : "+a2.company);

        // 클래스 변수의 값 변경
        a1.company = "기아";

        // 클래스 변수의 값 변경 후 클래스변수와 인스턴스변수 출력
        System.out.println("Avante 제조사 : "+Avante.company);
        System.out.println("a1 제조사 : "+a1.company);
        System.out.println("a2 제조사 : "+a2.company);


    }


}

클래스변수, 인스턴스변수, 지역변수 범위
package chapter07;

class Local {

    String name;

    void process() {
        name = "홍길동";
    }

    void printAge1() {
        int age = 20; // 지역변수
        System.out.println(age);
    }

    void printAge2() {
        int age = 30; // 지역변수
        System.out.println(age);
    }

}

public class LocalValEx {

    public static void main(String[] args) {

        Local local = new Local();

        System.out.println(local.name); // null

        local.process();
        System.out.println(local.name); // 홍길동

        local.printAge1();
        local.printAge2();

        // for문 블록 내에서의 변수 선언
        for (int i=0; i<10; i++) {
            int temp = 0;
            temp += i;
        }

        //System.out.println(temp); // 에러

    }

}

(멤버)메서드

가변 인자 메소드(Variable Arguments)

  • 인자 앞에 ..을 붙임,
  • 배열처럼 처리
void printInfo(String ...infos){
    System.out.println(infos[0]);
}
package chapter07;

public class VariableArgument {
    /**
     * Variable Argument Test
     */
    void printInfo(String ...infos){
        if(infos.length != 0){
            for(int i=0;i<infos.length;i++){
                System.out.println(infos[i]);
            }
        }
        else{
            System.out.println("인자가 없네요.");
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        VariableArgument vt = new VariableArgument();
        System.out.println("인자 없이");
        vt.printInfo();
        System.out.println("인자 하나");
        vt.printInfo("aaa");
        System.out.println("인자 두 개");
        vt.printInfo("aaa","bbb");
        System.out.println("인자 세 개");
        vt.printInfo("aaa","bbb","ccc");
    }
}

메서드 오버로딩 overloading

  • 같은 이름의 메소드를 한 클래스에 여러 개 정의 할 수 있는 기능
  • 파라미터 타입이나 개수가 달라야 함
오버로딩 메서드 println()
  • 클래스나 메서드 정의로 이동 : ctrl + 클래수, 메서드 클릭
package chapter07;

public class Overloading2 {

    public static void main(String[] args) {

        System.out.println(1);
        System.out.println(5.5);
        System.out.println((long)100);
        System.out.println("홍길동");
        System.out.println('a');
        System.out.println(true);
        System.out.println(new Overloading2());
        System.out.println(new int[5]);

    }

}

multiply() 메서드 오버로딩
package chapter07;

public class Overloading {

    public static void main(String[] args) {

        Operator op = new Operator();

        System.out.println(op.multiply(4, 3));
        System.out.println(op.multiply(4.5, 3.5));
        System.out.println(op.multiply(4, 3.5));
        System.out.println(op.multiply(4.5, 3));

    }

}

class Operator {

    int multiply(int x, int y) {
        System.out.println("(int, int)");
        return x * y;
    }

    double multiply(double x, double y) {
        System.out.println("(double, double)");
        return x * y;
    }

    double multiply(int x, double y) {
        System.out.println("(int, double)");
        return x * y;
    }

    double multiply(double x, int y) {
        System.out.println("(double, int)");
        return x * y;
    }
}

static 메소드와 인스턴스 메소드

  • static 메소드는 정의 부분 앞에 static 예약어가 지정된 메소드
  • static 메소드는 객체 생성 없이 클래스이름.메서드이름() 으로 호출 가능
  • static 메소드는 인스턴스 메서드나 변수를 바로 호출 할 수 없음
package chapter07;

public class StaticMethod {

    static int sVar; // static 변수
    int iVar; // instance 변수

    // static 메서드에선 호출 가능
    public static void staticCall() {

        System.out.println("staticCall()");
        System.out.println("sVar="+ sVar);
        //instannceCall(); // error : new 해서만 부를 수 있음
        //System.out.println("iVar="+ iVar);// error : new 해서만 사용가능
    }

    // new 생성 후 호출 가능
    public void instanceCall() {
        System.out.println("instantCall()");
        System.out.println("iVar=" + iVar);
    }

    public static void main(String[] args) {
        // static
        staticCall();
        System.out.println("main() - staticVar="+StaticMethod.sVar);
        System.out.println("main() - staticVar="+sVar); // 같은 클래스 : 클래스명 생략 가능

        // new
        StaticMethod sm = new StaticMethod();
        sm.instanceCall();
        System.out.println("main() - var=" +  sm.iVar);
    }

}

생성자 constructor

  • new 연산자와 함께 클래스 인스턴스화 할때 사용되는 리턴타입이 없는 특별한 메소드
  • 멤버 변수 초기화에 사용
  • 정의 하지 않으면 클래스 이름과 같은 기본 생성자 호출
  • 메소드 오버로딩을 통해 생성자 여러개 정의

기본 생성자

  • 생상자에 인자가 없는 생성자
  • 생성자 생략시 불려지는 생성자

클래스 생성

package chapter07;

public class Student {

    // 필드
    String name; // 학생명
    int grade; // 학년
    String department; // 학과

    // 기본 생성자 - 생략가능
    Student() {

    }
}

클래스 사용

package chapter07;

public class StudentMain {

    public static void main(String[] args) {

        Student stu1 = new Student(); // 기본 생성자        
    }
}

생성자 오버로딩

클래스 생성

package chapter07;

public class Student2 {

    // 필드
    String name; // 학생명
    int grade; // 학년
    String department; // 학과

    // 1번 생성자
    Student2() {

    }

    // 2번 생성자
    Student2(String n) {
        name = n;
    }

    // 3번 생성자
    Student2(String n, int g) {
        name = n;
        grade = g;
    }

    // 4번 생성자
    Student2(String n, int g, String d) {
        name = n;
        grade = g;
        department = d;        
    }

    // 학과와 학년을 매개변수로 받는 생성자 (에러 발생)
//    Student(String d, int g) {
//        department = d;        
//        grade = g;
//    }
}

필드 초기화

기본생성자 만 있을때

package chapter07;

public class StudentMain {

    public static void main(String[] args) {

        Student stu1 = new Student(); // 기본 생성자
        // 필드 초기화
        stu1.name = "홍길동";
        stu1.grade = 3;
        stu1.department = "자바";

        Student stu2 = new Student(); // 기본 생성자
        // 필드 초기화
        stu2.name = "임꺽정";
        stu2.grade = 3;
        stu2.department = "파이썬";

    }
}

오버로딩된 생성자 있을때

package chapter07;

public class StudentMain2 {

    public static void main(String[] args) {

        Student stu1 = new Student(); // 1번 생성자
        Student stu2 = new Student("홍길동"); // 2번 생성자
        Student stu3 = new Student("홍길동", 4); // 3번 생성자
        Student stu4 = new Student("홍길동", 4, "소프트웨어공학");

    }
}

this

  • 자신의 클래스 내부에 있는 필드, 생성자에 접근하기 위한 자가 자신의 instance

this() 생성자

package chapter07;

public class Car2 {

    // 필드
    String color;
    String company;
    String type;

    Car2() {
        this("white", "기아", "경차");
    }

    Car2(String color, String company, String type) {
        this.color = color;
        this.company = company;
        this.type = type;
    }

    Car2(String com, String t) {
        this("white", com, t);
    }

    Car2(String t) {
        this("white", "기아", t);
    }

    public String toString() {
        return color + "-" + company + "-" + type;
    }
}

this : 필드 접근

  • getter(필드값 가저오기), setter(필드값 대입하기) 작성시 활용
  • 은닉화, VO(Value Object), DTO(Data Transfer Object)와 연결됨
  • private 으로 외부 접근을 제어, 메서드를 통해 필드에 접근

클래스 생성

package chapter07;

public class Student3 {

    // 필드 : private  외부클래스에 접근 불가
    private String name; // 학생명
    private int grade; // 학년
    private String department; // 학과

    // getter, setter
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getGrade() {
        return grade;
    }
    public void setGrade(int grade) {
        this.grade = grade;
    }
    public String getDepartment() {
        return department;
    }
    public void setDepartment(String department) {
        this.department = department;
    }

}

클래스 사용

package chapter07;

public class StudentMain3 {

    public static void main(String[] args) {

        Student3 stu1 = new Student3(); // 기본생성자

        //stu1.name = "홍길동" // 접근 불가

        // set
        stu1.setName("홍길동");
        stu1.setGrade(4);
        stu1.setDepartment("자바");

        // get
        String name = stu1.getName();
        int grade = stu1.getGrade();
        String department = stu1.getDepartment();

        System.out.println("name="+name);
        System.out.println("grade="+grade);
        System.out.println("department="+department);


    }
}

초기화 블록

  • 클래스 필드의 초기화만을 담당하는 중괄호({})로 둘러싸인 블록
  • 초기화 블록은 생성자보다 먼저 호출
  • static 초기화 블록 : 클래스 instance 생성시 한 번 실행됨
  • 인스턴스 초기화 블록 : 클래스 instance 생성시 매 번 실행됨
package chapter07;

class InitBlockEx{
    int x;
    static int A ;
    static {
        test();
        A++;
        System.out.println("static block A : " + A);
    }

    {
        instanceMethod();
        x++;
        System.out.println("instance block x  : " + x);
    }

    static void test() {
        A++;
        System.out.println("static method  A : " + A);
    }

    public InitBlockEx() {
        instanceMethod();
        x++;
        System.out.println("contsructor A, x : " + A +"," + x);
    }

    private void instanceMethod() {
        x++;
        System.out.println("instance method x : " + x);
    }
}


package chapter07;


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


        InitBlockEx a = new InitBlockEx();        

    }
}

패키지

  • 자바에서 많은 클래스들을 분류하기 위한 방법
  • C#이나 다른 언어에서는 네임스페이스 라고 불려짐
  • package 란 비슷한 기능을 하는 클래스를 묶어 놓은 단위
  • 물리적으로는 클래스를 모아 놓은 디렉토리(폴더) 임
  • 패키지명은 중복을 피하기 위해 일반적으로 유일한 이름인 도메인명을 꺼꾸로 사용해서 만듬
  • 클래스이름은 실제적으로 상위패키지.하위패키지.클래스명
  • String 클래스 : java.lang.String
  • 이클립스 JRE System Library 확인, 프로젝트 scr 확인
  • 클래스 실행 : 패키지 최상위에서 java 상위패키지.하위패키지.클래스명 실행

다른 패키지에 있는 클래스 사용

  • 일반적으로 패키지 import 해서 사용
  • import 패키지.* : 패키지 내 모든 클래스 사용, 하위 패키지는 적용 안됨
package greeting.korea;

public class Hello {
    public Hello() {
        System.out.println("greeting.korea.Hello");
    }

}
  • src/greeting/korea/Hello.java
  • src/greeting/korea/Hello.class
package greeting.usa;

public class Hello {

    public Hello() {
        System.out.println("greeting.usa.Hello");
    }

}
  • src/greeting/usa/Hello.java
  • src/greeting/usa/Hello.class

접근 제한자

  • 멤버 또는 클래스에 사용
  • 해당하는 멤버 또는 클래스를 외부에서 접근하지 못하도록 제한하는 역할
  • 사용하는 곳 : 클래스, 멤버변수, 메서드, 생성자
  • private : 같은 클래스 내에서만 접근 가능
  • default: 같은 패키지 내에서만 접근 가능(접근 클래스를 붙이지 않은 경우)
  • protected: 같은 패키지 내에서, 그리고 다른 패키지의 자손클래스에서 접근 가능
  • public: 접근 제한 없음
package chapter07;

public class AccessEx {

    private int a = 1;
    protected int b = 2;
    int c = 3;
    public int d = 4;

}

각 접근 제한자 사용 - 같은 패키지

package chapter07;

public class AccessExMain{

    public static void main(String[] args) {

        AccessEx ae = new AccessEx();

        //System.out.println(ae.a); // private 접근 불가
        System.out.println(ae.b);
        System.out.println(ae.c);
        System.out.println(ae.d);


    }

}

각 접근 제한자 사용 - 다른 패키지

package chapter06;

import chapter07.AccessEx;

public class AccessExMain{

    public static void main(String[] args) {

        AccessEx ae = new AccessEx();

        //System.out.println(ae.a); // private 접근 불가
        System.out.println(ae.b); // protected 접근 불가
        System.out.println(ae.c); // default 접근 불가
        System.out.println(ae.d);


    }

}

싱글톤 singletone 기법(패턴)

  • 클래스의 인스턴스를 하나만 생성되도록 프로그래밍 하는 기법
  • 생성자 private 접근제어, static 메서드를 통해 인스턴스 리턴

클래스 생성

package chapter07;

public class Singleton {

    // static 변수
    private static Singleton instance = new Singleton();

    // 생성자에 private 접근 제한자
    private Singleton() {
        System.out.println("객체 생성");
    }

    // static 메서드
    public static Singleton getInstance() {
        System.out.println("객체 리턴");
        return instance;
    }
}

클래스 사용

package chapter07;

public class SingletonMain {

    public static void main(String[] args) {
        //Singleton s = new Singleton(); // 에러 발생

        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
        Singleton s3 = Singleton.getInstance();

        System.out.println(s1); // 동일 주소
        System.out.println(s2); // 동일 주소
        System.out.println(s3); // 동일 주소

    }

}

final 변경 불가

  • final 클래스 : 클래서 상속 불가 (상속 파트에서 확인)
  • final 메소드 : 메소드 오버라이딩 불가 (상속 파트에서 확인)
  • final 변수 : 상수, 생성자에 한번 초기화 가능

final 변수

package chapter07;

public class FinalEx {

    public static void main(String[] args) {

        Final f = new Final();
        //f.number = 200; // 에러
        System.out.println("PI = " + Final.PI);
        System.out.println(f.number);
    }

}

class Final {
    final static double PI = 3.14;
    final int number; // 상수

    Final() {
        number = 100; // 생성자에서 1번 초기화 가능
    }


}

USER 로그인 예제

  • UserVO : 유저 정보 저장 클래스
  • LoginService : 유저 입력 정보와 비교해서 로그인 처리 서비스 클래스
  • UserLoginTest : 프로그램 실행(테스트)

UserVO

package user;

// User 정보
public class UserVO {
    private String id;
    private String pw;
    private String name;

    public UserVO() {
    }

    public UserVO(String id, String pw, String name) {
        this.id = id;
        this.pw = pw;
        this.name = name;
    }


    public String getId() {
        return id;
    }

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

    public String getPw() {
        return pw;
    }

    public void setPw(String pw) {
        this.pw = pw;
    }

    public String getName() {
        return name;
    }

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


}

LoginService

package user;

// 로그인 서비스
public class LoginService {

    String id = "hong";
    String pw = "0000";


    boolean isLogin(String id, String pw, String name) {
        boolean rs = false;

        if(id.equals(this.id)) {
            if(pw.equals(this.pw)) {
                System.out.println("Welcom !! " + name );
                rs = true;
            }
        }

        return rs;
    }

    boolean isLogin(UserVO user) {
        boolean rs = false;

        String id = user.getId();
        String pw = user.getPw();
        String name = user.getName();


        if(id.equals(this.id)) {
            if(pw.equals(this.pw)) {
                System.out.println("Welcom !! " + name );
                rs = true;
            }
        }

        return rs;
    }

}

UserLoginTest

package user;

import java.util.Scanner;

public class UserLoginTest {

    public static void main(String[] args) {

        boolean rs = false;

        Scanner scan = new Scanner(System.in);

        System.out.println("id >>> ");
        String id = scan.next();

        System.out.println("pw >>> ");
        String pw = scan.next();


        System.out.println("name >>> ");
        String name = scan.next();

        LoginService ls = new LoginService();

        // 각각의 인자 사용
        rs = ls.isLogin(id, pw, name);

        if(rs) {
            System.out.println("login success");
        }else {
            System.out.println("login fail");
        }

        // VO 사용
        UserVO user = new UserVO(id, pw, name);
        rs = ls.isLogin(user);

        if(rs) {
            System.out.println("login success");
        }else {
            System.out.println("login fail");
        }

    }

}

'Java' 카테고리의 다른 글

인터페이스 interface  (0) 2022.03.07
상속 Inheritance  (0) 2022.03.07
배열 array  (0) 2022.03.07
함수 - 메서드 function  (0) 2022.03.07
제어문 - 반복문 loop  (0) 2022.03.07