본문 바로가기

JAVA

231218 Java

static 에 대해 공부

 

클래스 내부의 인스턴스에 static 이 붙으면 객체를 생성하지 않고도 인스턴스 호출 가능

class Cat {
    static String name;
    public static void print() {}
}
public class Static01 {
    public static void main(String[] args) {
        Cat.name = "";
        Cat.print();
    }
}

 

인스턴스 변수와 정적 변수

/* 인스턴스 멤버(static X), 정적 멤버(static O)
 * static 키워드
 * static 은 정적 이라는 의미가 있음
 * 자바에서는 정적 개념과 동적 개념이 있음
 * 쉽게 표현하면 정적은 클래스가 로드되는 시점, 동적은 클래스가 실행된 이후
 * 이 중, 객체는 동적 데이터라고 하여 프로그램이 실행된 이후에 발생하는 대표적인 형태
 *
 * 인스턴스 멤버
 *  인스턴스 생성 시 가지게 되는 자신의 변수
 *  인스턴스명.변수명 으로 호출
 *  new 로 인스턴스를 생성해야 사용 가능
 * 정적 멤버
 *  모든 객체가 공통적으로 사용하는 변수
 *  클래스명.변수명 으로 호출
 *  인스턴스 없이 클래스명으로 바로 호출하여 사용 가능
 *  하나의 클래스에는 하나의 변수만 사용 가능
 *  인스턴스 보다는 클래스에 의지(연결)하여 사용
 *  static 을 붙여서 사용
 * 
 * 사용 시 주의사항
 *  인스턴스가 생성되지 않은 상태에서 호출되는 변수/메소드 이므로
 *  인스턴스 안에서만 사용되는 인스턴스 변수를 쓸 수 없음
 *  정적 변수와 지역 변수만 사용 가능
 *  정적 메소드에서 인스턴스 메소드를 호출하면 오류 발생
 *  인스턴스 메소드로 객체가 생성되어야만 사용 가능하기 때문
 *  정적 메소드에서 정적 메소드 호출은 가능
 *  인스턴스 메소드에서 정적 메소드 호출 가능
 *  정적 메소드는 this 키워드를 사용할 수 없음 (this 는 인스턴스 생성 후 사용)
 *  final 붙인 상수는 모두가 변경 없이 사용하는 상수
 *  인스턴스를 만들지 않고 쓸 수 있으면 좋음
 *  그래서 final static 을 붙여 사용
 */
class Cat {
    static String name;
    int age;
    public static void print() {}
}
public class Static01 {
    public static void main(String[] args) {
        Cat cat = new Cat();
        Cat cat2 = new Cat();
        cat.age = 10;
        cat2.age = 20;
        System.out.println(cat.age); // 10
        System.out.println(cat2.age); // 20
        cat.name = "123";
        cat2.name = "1234";
        Cat.name = "야옹이"; // static 이 붙은 변수는 모든 객체가 같은 변수를 사용
        // 상수처럼 변하지 않는 값을 정적으로 많이 사용
        System.out.println(cat.name); // 야옹이
        System.out.println(cat2.name); // 야옹이
        System.out.println(Cat.name); // 야옹이
    }
}

 

static 사용 예시

package static01;
class Car {
    String model;
    String color;
    int speed;
    int id;
    static int numbers; // 기본 값인 0 으로 초기화

    public Car(String model, String color, int speed) {
        this.model = model;
        this.color = color;
        this.speed = speed;
        this.id = ++numbers; // Car 객체 생성 시 id 값이 1 씩 증가
    }
    public static void aaa() { // 인스턴스 없이 호출 가능
        // ccc(); ccc 메소드는 객체 생성 후 작동하기 때문에 오류 발생
        // this 명령어도 객체 생성 후 작동하기 때문에 사용 불가
    }
    public void bbb() {
        aaa();
        this.speed = 110;
    }
    public void ccc() {
        this.model = "그랜저";
    }
    // static 과 non-static
    /* static 은 non-static 을 부를 수 없음
     * non-static 은 static 을 부를 수 있음
     * non-static 은 this 를 사용할 수 있음
     * static 은 this 를 사용할 수 없음
     */
    /* 딱 하나만 만들어서 사용해야 할 때, 싱글톤
     * 1. 데이터베이스 접속 정보 (id, pw, url)
     */
}
public class Static02 {
    public static void main(String[] args) {
        Car car = new Car("아반떼", "흰색", 100);
        Car car2 = new Car("아반떼", "흰색", 100);
        Car car3 = new Car("아반떼", "흰색", 100);
        Car car4 = new Car("아반떼", "흰색", 100);
        Car car5 = new Car("아반떼", "흰색", 100);
        System.out.println(car.id); // 1
        System.out.println(car2.id); // 2
        System.out.println(car3.id); // 3
        System.out.println(car4.id); // 4
        System.out.println(car5.id); // 5
        System.out.println(Car.numbers); // 5
    }
}

 

접근 제어자

package com.gmail.pp;
/* 접근 제어자 Access Modifiers
 * 자바에서는 접근 제어자를 통해 각 api 의 접근 권한을 제한할 수 있음
 * 아래는 접근 제어자의 범위를 크기 순서대로 나열
 * public > protected > default(비어있는 것) > private
 * public : 모두 접근 가능, 가장 넓은 범위로써 제한 없이 모두 접근 가능, 패키지를 뛰어 넘음
 * protected : 같은 패키지에서 접근 가능
 *             다른 패키지에서는 상속 받은 자식 클래스 / 인터페이스 만 사용 가능
 * default : 접근 제어자가 아무것도 안 붙은 형태, 아무런 접근 제한을 두지 않을 때
 *           같은 패키지 내에서 접근 가능, 다른 패키지에서 접근 불가
 * private : 같은 패키지 X, 다른 패키지 X, 오직 내 클래스에서만 가능
 *
 * 접근 제어자는 클래스 명, 생성자, 메소드, 필드에 모두 사용 가능
 * 단, 클래스에서는 public 과 default 만 사용 가능
 */
class Apple { // default 상태
    String name; // 필드도 default 상태
    private int age; // private 선언

    private Apple() { }
    static Apple getInstance() {
        return new Apple();
    }

    public void setAge(int age) { // setter (저장)
        if (age < 0) {
            this.age = age * -1;
        } else {
            this.age = age;
        }
    }

    public int getAge() { // getter (호출)
        return age;
    }
}
public class AccessModifiers {
    public static void main(String[] args) {
        // Apple apple = new Apple(); // 생성자가 private 일 경우 getInstance 메소드를 사용
        Apple apple = Apple.getInstance();
        apple.name = "사과"; // 같은 패키지 내 사용 가능
        // apple.age = 13; // 같은 클래스가 아니라 오류 발생
        apple.setAge(5); // age 값을 13 으로 설정
        System.out.println(apple.getAge()); // apple 객체의 age 값 호출, 13
    }
}

 

데이터베이스에서 값 불러오기

package com.poseidon.db;

import java.sql.*;

public class DB01 {
    // 구로에 있는 DB 자바로 접속해보기
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Connection conn = null;
        Statement stmt = null;
        String url = "jdbc:mariadb://-----";
        String id = "-----";
        String pw = "-----";

        Class.forName("org.mariadb.jdbc.Driver");
        conn = DriverManager.getConnection(url, id, pw);
        stmt = conn.createStatement();

        // 데이터베이스에 질의하기 (SQL)
        String sql = "SELECT * FROM departments ORDER BY dept_no";
        // 오는 값 저장하기
        ResultSet rs = stmt.executeQuery(sql);
        // 출력하기
        while(rs.next()) {
            System.out.print(rs.getString(1) + " : ");
            System.out.print(rs.getString(2) + "\n");
        }
        // 마지막에 생성한 인스턴스 부터 닫기, * 필수 *
        rs.close();
        stmt.close();
        conn.close();
    }
}

 

접근 제어자에 따른 클래스, 메소드 확인해보기

// 패키지 확인 !
package com.poseidon.access; // poseidon.access 패키지

public class Human { // public
    String name; // default
    int age; // default
    public Human() { // 생성자는 public
    }
    void sleep() { // default 메소드
        System.out.println("Zzzz");
    }
}
------
package com.poseidon.access; // 같은 poseidon.access 패키지

public class AM02 {
    public static void main(String[] args) {
        Human human = new Human();
        human.sleep();
        human.age = 12;
        human.name = "홍길동"; // 같은 패키지 내 사용 가능
    }
}
------
package dec18; // 다른 패키지

import com.poseidon.access.Human;

public class Test02 {
    public static void main(String[] args) {
        Human human = new Human(); // public 클래스, 생성자라 객체 생성은 가능
        // human.sleep(); // default 메소드라 불가능
        //  human.age = 12;
        // human.name = "홍길동"; // 둘 다 default 필드라 설정 불가
    }
}

 

클래스 상속

package com.poseidon.inheritance;
// 상속
// 현실에서는 부모가 자식에게 물려주는 행위
// 자식은 부모의 모든 것을 자신의 것처럼 사용
// 자바에서는 부모와 자식 클래스를 만들고 서로 연결
// 부모의 코드를 모두 내려받아 자식이 자신의 것 처럼 사용
public class Inheritance {
    public static void main(String[] args) {
        A a = new A();
        B b = new B();
        b.field1 = 100; // A 를 상속하였기 때문에 A 의 필드와 메소드를 사용 가능
        b.method1(); // A 의 메소드
        C c = new C(); // 클래스 내부에 아무것도 없어도 생성 가능
        c.field2 = 1; // B 를 상속하였기 때문에 A, B 의 필드와 메소드를 사용 가능
        Cat cat = new Cat("야옹이");
        Dog dog = new Dog();
        cat.age = 1; // Animal 클래스를 상속하여 사용 가능
        dog.name = "멍멍이"; // Animal 클래스를 상속하여 사용 가능
    }
}

class A {
    int field1;
    void method1() {

    }
}

class B extends A { // 자식 B 가 부모 A 를 상속한다
    int field2;
    void method2() {

    }
}

class C extends B {

}

 

Animal 클래스들

package com.poseidon.inheritance;

public class Animal {
    String name;
    int age;
    String breed;
    int hp;
}
------
package com.poseidon.inheritance;

public class Cat extends Animal{
    public Cat(String name) {
        this.name = name;
    }
}
------
package com.poseidon.inheritance;

public class Dog extends Animal{

}

 

다수의 클래스에 사용하는 메소드를 하나로 압축해보기

package zoo;
// 나는 동물원 사육사
class Animal2 {
    String name;
    int age;
    String breed;
    int hp;
    public Animal2(String name, int age) {
        System.out.println("동물이 태어납니다.");
        this.name = name;
        this.age = age;
    }
}
class Mouse extends Animal2{ // 상속으로 인해 필드 생성할 필요가 사라짐
//    String name;
//    int age;
//    String breed;
//    int hp;
    public Mouse(String name, int age) {
        super(name, age);
        System.out.println("쥐 생성자");
    }
}
class Horse extends Animal2 { // 상속으로 인해 필드 생성할 필요가 사라짐
//    String name;
//    int age;
//    String breed;
//    int hp;
    public Horse(String name, int age) {
        super(name, age);
    }
}
class Rabbit extends Animal2{ // 상속으로 인해 필드 생성할 필요가 사라짐
//    String name;
//    int age;
//    String breed;
//    int hp;
    public Rabbit(String name, int age) {
        super(name, age);
    }
}

class ZooKeeper extends Animal2 {
//    public void feed(Mouse mouse) { // 오버로딩
//        mouse.hp++;
//    }
//    public void feed(Horse horse) {
//        horse.hp++;
//    }
//    public void feed(Rabbit rabbit) {
//        rabbit.hp++;
//    }
    public void feed(Animal2 animal2) {
        animal2.hp++;
    }

    public ZooKeeper(String name, int age) {
        super(name, age);
        System.out.println("사육사가 나옵니다.");
    }
}
public class Zoo {
    public static void main(String[] args) {
//        ZooKeeper zooKeeper = new ZooKeeper();
//        Mouse mouse = new Mouse();
//        Horse horse = new Horse();
//        Rabbit rabbit = new Rabbit(); // 기본 생성자 사용 시 사용
        ZooKeeper zooKeeper = new ZooKeeper("사육사", 30);
        Mouse mouse = new Mouse("쥐", 1);
        Horse horse = new Horse("말", 2);
        Rabbit rabbit = new Rabbit("토끼", 1); // 부모 생성자 변경 시 자식 클래스 전체 변경
        // Animal2 mouse1 = new Mouse(); 부모 클래스가 앞에 오는 형태로도 생성 가능
        // 대신 자식 클래스의 필드, 메소드는 사용 불가
        zooKeeper.feed(mouse); // 쥐 한테 밥 주기
        zooKeeper.feed(horse); // 말 한테 밥 주기
        zooKeeper.feed(horse); // 말 한테 밥 주기
        zooKeeper.feed(rabbit); // 말 한테 밥 주기
        System.out.println(mouse.hp); // 1
        System.out.println(horse.hp); // 2
        System.out.println(rabbit.hp); // 1
    }
}

 

자바 기초 몇가지 들

1. 오버라이드, 오버라이딩
2. 오버로드, 오버로딩
3. 인터페이스
4. 상속
5. 정적 메소드

'JAVA' 카테고리의 다른 글

231220 Java  (0) 2023.12.20
231219 Java  (0) 2023.12.19
231215 Java 객체지향  (0) 2023.12.15
231214 Java 객체지향  (2) 2023.12.14
231213 Java  (0) 2023.12.13