전체 글 (165)
2024-06-27 00:07:45

이런식으로 서로 간선으로 연결되어있는 정점들의 집합을 하나의 연결 요소라고 한다.

이 주어진 그래프를 토대로 몇개의 연결 요소가 나오는지 구하는 문제이다.

 

문제에서 주어지는 정점의 개수는 1000개이다. 이를 일반적인 인접행렬로 표현하려면 1000 * 1000의 배열이 필요하므로, 메모리도 아끼고 실행 시간도 줄일 겸 각 정점이 어느 정점과 연결되어있는지 표현하는 인접행렬로 구현하였다.

 

문제를 풀기 위해서 dfs를 사용하여 순회하지 않았던 연결 요소라면 true를 반환하여 결과값에 1을 더하고, 순회하였던 연결 요소라면 false를 반환하도록 해주었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
namespace real연습
{
    internal class Program
    {
        static void Main(string[] args)
        {
            int[] input = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
            int edge = input[0];
            int linkes = input[1];
 
            Graph graph = new Graph(edge);
 
            for (int i = 0; i < linkes; i++)
            {
                int[] link = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
                graph.graph[link[0]].Add(link[1]);
                graph.graph[link[1]].Add(link[0]);
            }
            HashSet<int> visited = new HashSet<int>();
 
            int result = 0;
            for (int i = 1; i <= edge; i++) // 1번 정점부터 순회 시작
            {
                if (dfs_search(i, visited, graph) == true) // 순회한적 없다면
                {
                    result += 1; // 결과값 1 증가
                }
            }
            Console.WriteLine(result);
 
        }
        static bool dfs_search(int start, HashSet<int> visited, Graph graph)
        {
            bool result = false;
            Stack<int> stack = new Stack<int>();
            if (visited.Contains(start) == false) // 방문하지 않았던 정점일때만 실행
            {
               stack.Push(start); // stack에 순회를 시작하는 값을 미리 넣어둠
 
                while (stack.Count != 0)
                {
                    int current = stack.Pop(); // 스택의 맨 뒤에있는 값을 뽑아 사용
                    if (visited.Contains(current) == false) // 해당 정점을 방문하지 않았다면
                    {
                       visited.Add(current); // 방문처리
                    }
                    for (int vertex = graph.graph[current].Count - 1; vertex >= 0 ; vertex--)
                   { // 스택을 맨 위의 값부터 뽑아서 쓰기 때문에, 마지막 index부터 첫번쨰 index까지 역순회
                        if (visited.Contains(graph.graph[current][vertex]) == false)
                       {
                            stack.Push(graph.graph[current][vertex]);
                        }
                    }
 
                }
                result = true;
            }
 
 
            return result;
        }
        private class Graph=
        {
            int _size;
            public List<int>[] graph;
            public Graph(int size)
            {
                this._size = size;
                this.graph = new List<int>[size + 1];
                for (int i = 1; i < size + 1; i++)
                {
                    graph[i] = new List<int>();
                }
            }
        }
 
    }
    
}
 
cs

 

 

2024-06-01 16:57:32

프로세스 (process)

- 실행 중인 하나의 프로그램

- 사용자가 애플리케이션을 실행하면 운영체제(O/S)로부터 실행에 필요한 메모리를 할당받아 애플리케이션의 코드를 실행하는 것.

- 하나의 프로그램이 다중 프로세스를 만들기도 한다.

 

멀티 태스킹 (multi tasking)

- 두가지 이상의 작업을 동시에 처리하는 것.

 

멀티 프로세스   -   어플리케이션 단위의 멀티 태스킹

- 독립적으로 프로그램을 실행하고 여러가지 작업을 처리

- 운영체제에서 할당받은 자신의 메모리를 가지고 실행하여, 서로 독립적

- 하나의 프로세스에 오류가 발생해도 다른 프로세스에 영향을 미치지 않는다

 

멀티 스레드    -   한 개의 어플리케이션 내부에서의 멀티 태스킹

- 스레드(thread) : 한 가지 작업을 실행하기 위해 순차적으로 실행할 코드

- 한 개의 프로그램을 실행하고 내부적으로 여러 가지 작업 처리

- 하나의 프로세스 내에서 여러가지 작업을 처리

- 하나의 스레드에서 오류가 발생하면 다른 스레드도 같이 종료되기 때문에, 예외처리를 잘 해야함.

 

메인 (main) 스레드

모든 자바 프로그램은 메인 스레드가 main() 메소드를 실행하며 시작되며, main() 메소드의 첫 코드부터 아래로 순차적으로 실행된다.

마지막 코드가 실행되거나, return 문을 만나면 종료된다.

싱글 스레드는 메인 스레드가 종료하면 프로세스도 종료되며, 

멀티 스레드는 실행중인 스레드가 하나라도 있다면, 프로세스가 종료되지 않는다.

 

작업 스레드 생성 방법

 

- Thread 클래스로부터 직접 생성

Runnable 인터페이스를 매개값으로 갖는 Thread 생성자 호출

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class BeepTask implements Runnable {
    //인터페이스를 구현하는 구현 클래스
    
    @Override
    public void run() {
        // 스레드가 실행할 명령문을 기술
        for (int i = 0; i < 5; i++)
        {
            System.out.println("삐~");
            try{
            Thread.sleep(1000);
            }
            catch(InterruptedException e )
            {
                
            }
        }
        
    }
    
}
 
cs

 

<main>

Runnable beepTask = new DeepTask();

Thread thread = new Thread(BeepTask);

thread.start(); // 스레드 실행 메소드

 

- Thread 하위 클래스로부터 생성

Thread 클래스 상속 후 run 메소드를 재정의해 스레드가 실행할 코드 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
public class BeepThread extends Thread {
    // Thread를 상속받아서 run() 메소드를 재정의해서 사용
    
    @Override
    public void run()
    {
        for (int i = 0;i < 5; i++)
        {
            System.out.println("삐~");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
 
cs

<main>

Thread thread = new BeepThread();

thread.start();

<익명 함수 이용>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 
public class BeepTaskEx2 {
    public static void main(String[] args)throws InterruptedException {
        // 익명 객체 (인터페이스)를 바로 대입해서 스레드 생성
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run()
            {
                // 스레드가 실행할 명령문을 기술
                for (int i = 0 ; i < 5; i ++) {
                    System.out.println("삐~");
                    try {
                    Thread.sleep(1000);
                    } catch(InterruptedException e)
                    { }
                }
            }
        });
        thread.start();
 
        new Thread() // 인스턴스 없이 사용하기
        {
            @Override
            public void run()
            {
                for (int i= 0; i < 3; i++) {
                    System.out.println("응애");
                    try {
                        Thread.sleep(1000);
                    }catch (InterruptedException e) {}
                }
            }
        }.run();
    }
}
 
cs

 

스레드의 이름

메인 스레드의 이름 : main

작업 스레드의 이름 (자동 설정) : Thread-n

스레드 이름 확인 : thread.getName();

스레드 이름 변경 : thread.setName("스레드 이름");

코드 실행하는 현재 스레드 객체의 참조 얻기

Thread thread = Thread.currentThread();

반환 내용 : Thread[호출스레드명, 우선운위, 스레드그룹명]

 

스레드 우선 순위

동시성 (Concurrentcy)

멀티 작업을 위해 하나의 코어에서 멀티 스레드가 번갈아 가며 실행하는 성질

병렬성 (parallelis)

멀티 작업을 위해 멀티 코어에서 개별 스레드를 동시에 실행하는 성질

 

스레드 스케줄링

스레드의 개수가 코어의 수보다 많을 경우, 스레드를 어떤 순서로 동시성으로 실행할 것인가 결정하기 위해 사용

스케줄링에 의해 스레드들은 번갈아 가며 run() 메소드를 조금씩 실행

 

우선순위 방식 (Priority) - 코드로 제어 가능

우선 순위가 높은 스레드가 실행 상태를 더 많이 가지도록 스케줄링

1 ~ 10까지 가질 수 있으며 기본은 5.

하지만 우선순위가 높다고 해서 항상 먼저 실행되는 것은 아님.

우선실행될 확률이 올라가는 것일 뿐...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package schedule;
 
public class LoopThreadEx {
    public static void main(String[] args)
    {
        for (int i = 1; i <= 10; i++)
        {
            Thread thread = new LoopThread("thread_" + i);
            
            if (i != 10)
                thread.setPriority(Thread.MIN_PRIORITY);
            else
                thread.setPriority(Thread.MAX_PRIORITY);
            
            thread.start();
        }
    }
}
cs

 

순환 할당 (Round-Robin) - 코드로 제어할 수 없음

시간 할당량 (Time-Slice) 정해서 하나의 스레드를 정해진 시간만큼 실행

 

동기화 메소드와 동기화 블록

동유객체를 사용할 때, 멀티 스레드가 하나의 객체를 공유하면 문제가 생길 수 있다.

스레드가 사용 중인 객체를 다른 스레드가 변경하는 일을 방지하기 위해서 synchronized 키워드를 사용한다.

이 키워드를 사용하면 단 하나의 스레드만 메소드 혹은 블록을 실행할 수 있어, 다른 스레드는 메소드나 블록 실행이 끝날 때 까지 대기해야한다.

동기화 메소드

public synchronized void method() {

}

동기화 블록

synchronized(공유 객체) {

// 임계영역 : 단 하나의 스레드만 실행 가능

}

// 여러 스레드가 실행 가능한 영역

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package control;
 
public class DataBox {
    private String data;
    
    public synchronized String getData()
    {
        if (this.data == null) {
            // 데이터 값이 존재하지 않으면 
            try {
                wait(); // 대기상태로 전환
            } catch(InterruptedException e) { }
        }
    
        String returnValue = data;
        System.out.println("ConSumerThread가 읽은 데이터 : " + returnValue);
        data = null// 데이터를 반환한 다음 데이터 초기화
        notify(); // 대기상태인 스레드 실행대기로 전환
        return returnValue;
    }
    public synchronized void setData(String data) {
        if (this.data != null) {
            // 데이터가 존재한다면
            try {
                wait(); // 대기상태로 전환
            } catch (InterruptedException e) {} 
        }
        this.data = data;
        System.out.println("ProducerThread가 생성한 데이터 : " + data);
        notify(); // 일시 정지 상태인 스레드를 실행대가로 전환
    }
    
    // 스레드의 실행 순서는 예측이 불가능하다.
    // 만약 처음에 ConsumerThread가 세번 연속 실행이 되었을 경우,
    // 데이터가 존재하지 않기 때문에, 첫번째 ConsumerThread는 wait()에 의해 대기상태가 된다.
    // 두번째,세번째 ConsumerThread는 synchronized 키워드에 의하여 getData을 실행할 수 없다.
    // 이후 ProducerThread에 의해 데이터가 생성되고, notify()에 의해 첫번째 소비자 스레드가 실행된다.
    // 이후 흐름 동일.
}
 
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package control;
 
public class ProducerThread extends Thread {
    private DataBox dataBox;
    public ProducerThread(DataBox dataBox) {
        this.dataBox = dataBox;
    }
    
    @Override
    public void run()
    {
        for (int i = 1; i <= 3; i++)
        {
            String data = "Data" + i;
            dataBox.setData(data);
        }
    }
}
 
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package control;
 
public class ConsumerThread extends Thread {
    private DataBox dataBox;
    public ConsumerThread(DataBox dataBox)
    {
        this.dataBox = dataBox;
    }
    @Override
    public void run()
    {
        for (int i = 1; i <= 3; i++)
        {
            String data = dataBox.getData();
        }
    }
}
 
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package control;
 
public class ControlThread {
    public static void main(String[] args)
    {
        DataBox dataBox = new DataBox();
        
        ProducerThread prodThread = new ProducerThread(dataBox);
        ConsumerThread consThread = new ConsumerThread(dataBox);
        
        prodThread.start();
        consThread.start();
    }
}
 
cs

 

 

스레드 상태

 

구분 메소드 설명
일시 정지로 보냄 sleep(long millis) 주어진 시간(밀리세컨드 단위)동안 스레드를 일시 정지 상태도 만듦.
시간이 지나면 자동으로 실행상태로 전환
join() join() 메소드를 호출한 스레드는 일시 정지 상태.
join 메소드를 가진 스레드가 종료되면 실행 대기 상태로 전환
wait() 동기화 블록 내에서 스레드를 일시 정지 상태로 만듦
일시정지에서 벗어남 interrupt() 일시 정지 상태일 경우, exception을 발생시켜 ready() 혹은 종료 상태로 전환
notify(), notifyAll() wait() 메소드로 일시 정지 상태인 스레드를 실행 대기 상태로 만듦
실행 대기로 보냄 yield() 실행 상태에서 다른 스레드에게 실행을 양보하고 실행 대기 상태로 전환

 

sleep() : 얼마동안 멈출것인지 밀리 세컨드 단위로 지정.

일시 정지 상태에서 정지가 끝나기 전에 interrupt() 메소드가 호출되면 interruptException 발생. 따라서 예외처리가 필요함.

 

 

데몬 스레드 (daemon)

주 스레드의 작업을 돕는 보조적인 역할을 수행하는 스레드.

주 스레드가 종료되면 데몬 스레드는 강제적으로 자동 종료됨.

ex) 워드프로세서의 자동저장, 미디어플레이어의 동영상 및 음악 재생, 가비지 컬렉터 등...

 

스레드를 데몬 스레드로 만들기

주 스레드가 데몬이 될 스레드의 setDaemon(true) 호출

반드시 start() 메소드 호출 전에 setDaemon(true)를 호출해야 함. 그렇지 않으면 IllegalThreadStateException 발생.

isDaemon() 메소드의 리턴값 조사 - true면 데몬 스레드.

2024-06-01 03:58:37

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

객체의 교환성을 높여주기 때문에 다형성을 구현하는 매우 중요한 역할을 한다.

 

인터페이스의 역할

1. 개발 코드가 객체에 종속되지 않게 함 -> 객체 교체할 수 있도록 하는 역할

2. 개발 코드 변경 없이 리턴값 또는 실행 내용이 다양해 질 수 있음

 

인터페이스 선언

[public] interface 인터페이스명 { ... }

 

인터페이스의 구성 멤버

1. 상수 필드     -    모든 필드는 public static final이 자동적으로 붙는다 (안붙이면 컴파일러가 붙임), 선언과 동시에 초기화 해줘야 함    

2. 추상 메소드      - public abstract가 자동으로 붙음

3. 디폴트 메소드        - 실행블록을 가지고 있는 메소드 (구현클래스에서 재정의하지 않아도 상관없음)

4. 정적 메소드

(인터페이스는 인스턴스 필드를 가질 수 없다!!!)

 

 

구현 클래스 선언

implement 키워드로 명시한다.

public class 구현클래스명 implements 인터페이스명 { ... }

 

익명 구현 객체

명시적인 구현 클래스 작성은 생략하고 바로 구현 객체를 얻는 방법

이름없는 구현 클래스 선언과 동시에 객체 생성

ex) new Thread(new Runnable (public void run() {...} )).start();

2024-06-01 03:11:01

추상 클래스(abstract class)는 실체 클래스들의 공통되는 필드와 메소드를 정의한 클래스이다.

추상 클래스는 실체 클래그의 부모 클래스 역할을 하며 객체로 존재할 수 없다.

 

추상 클래스 용도

1. 실체 클래스의 공통된 필드와 메소드의 이름을 통일

2. 실체 클래스를 작성할 때 시간 절약

3. 실체 클래스 설계 규격을 만들고자 할 때

 

추상 클래스 선언

클래스 선언에 abstract 키워드 사용

New 연산자로 객체를 생성할 수 없기 때문에, 상속을 통해 자식 클래스만 생성이 가능하다.

ex) public abstract class 클래스명 { }

 

추상 클래스의 코든 메소드는 반드시 실체 클래스에서 구현 되어야 한다

'생각 두 접시' 카테고리의 다른 글

[java] 타입 변환과 다형성  (0) 2024.06.01
[java] final  (0) 2024.06.01
[java] 메소드 재정의 @Override  (0) 2024.06.01
[java] Getter / Setter  (0) 2024.05.31
[java] 접근 제한자  (0) 2024.05.31
2024-06-01 02:53:17

다형성: 같은 타입이지만, 실행 결과가 다양한 객체를 이용할 수 있는 성질

 

부모 타입에는 모든 자식 객체가 대입이 가능하다. 그렇기 때문에 자식 타입은 부모 타입으로 자동 타입 변환이 가능하다 (like int -> double O | double -> int X)

 

자동 타입 변환 (Promotion)

부모 클래스 : Animal 

자식 클래스 : Cat

Cat cat = new Cat();

Animal animal = cat; (Animal animal = new Cat() 도 가능)

 

바로 위의 부모가 아니더라도 상속 계층의 상위면 자동 타입 변환이 가능하다. 변환 후에는 부모 클래스 멤버만 접근 가능하다.

 

강제 타입 변환 (Casting)

부모 타입을 자식 타입으로 변환하는 것

조건

자식 타입을 부모 타입으로 자동 변환 후, 다시 자식 타입으로 변환할 때

ex) Cat cat = new Cat();

Animal animal = cat;

cat = (Cat)animal

 

객체 타입 확인 (instanceof)

부모 타입 이면 모두 자식 타입으로 강제 타입 변환할 수 았는 것이 아니다.

ex) Parent parent = new Parent(); // 부모 참조변수 parent가 부모 인스턴스를 참조하는 중

Child child = (Child) parent;  // 따라서 캐스팅의 조건을 충족시키지 못해, 캐스팅 불가능

 

먼저 자식타입인지 확인 후 강제 타입변환을 실행해야 한다.

boolean result = 좌항(객체) instanceof 우항(타입)

'생각 두 접시' 카테고리의 다른 글

[java] 추상 클래스  (0) 2024.06.01
[java] final  (0) 2024.06.01
[java] 메소드 재정의 @Override  (0) 2024.06.01
[java] Getter / Setter  (0) 2024.05.31
[java] 접근 제한자  (0) 2024.05.31
2024-06-01 00:11:27

final 키워드는 다양한 용도로 쓰이는데,

 

1. final 필드 : 수정 불가 필드 

final이 붙은 필드는 더이상 수정이 불가능한 상수의 성질을 갖게 된다.

하지만, c++이나 c#처럼 static의 성질 (메모리 고정) 을 가지지 못하여, static final로 사용해야 한다.

 

2. final 클래스 : 부모로 사용(상속) 불가능

 

3. final 메소드 : 자식이 재정의(Override) 할 수 없는 메소드

'생각 두 접시' 카테고리의 다른 글

[java] 추상 클래스  (0) 2024.06.01
[java] 타입 변환과 다형성  (0) 2024.06.01
[java] 메소드 재정의 @Override  (0) 2024.06.01
[java] Getter / Setter  (0) 2024.05.31
[java] 접근 제한자  (0) 2024.05.31
2024-06-01 00:06:31

메소드 재정의는 부모 클래스의 상속 메소드를 수정해 자식 클래스에서 재정의 하는 것이다.

 

메소드 재정의 조건

- 부모 클래스의 메소드와 동일한 시그니처 ( 리턴 타입, 메소드 이름, 매개변수 리스트 ) 를 가져야 한다.

- 접근 제한을 더 강하게 오버라이딩 불가능하다 ( public -> private X | default -> public 가능) 역은 성립.

- 새로운 예외(Exception) throws 불가 {위의 접근제한과 비슷. 부모 클래스보다 더 포괄적인 에러를 throws 불가}

 

@Override 어노테이션

컴파일러에게 부모 클래스의 메소드 선언부와 동일한지 검사 지시

 

메소드 재정의 효과

부모 메소드는 숨겨지고, 재정의된 자식 메소드 실행 (super.메소드() 사용시 부모 클래스의 메소드 사용 가능)

예제)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package Practice;
 
public class AirPlane {
    public void land()
    {
        System.out.println("착륙합니다");
    }
    public void Fly()
    {
        System.out.println("일반비행합니다");
    }
    public void takeOff()
    {
        System.out.println("이륙합니다");
    }
}
 
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package Practice;
 
public class SonicAirplane extends AirPlane {
    public static final int NORMAL = 1;
    public static final int SUPERSONIC = 2;
    
    int flyMode = NORMAL;
    
    @Override
    public void Fly()
    {
        if (flyMode == SUPERSONIC)
            System.out.println("음속비향합니다");
        else
            super.Fly();
    }
}
 
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package Practice;
 
import week10.SonicAirPlane;
 
public class AirPlaneEx {
    public static void main(String[] args) {
        SonicAirplane sPlane = new SonicAirplane();
        sPlane.takeOff();
        sPlane.Fly();
        sPlane.land();
        
        sPlane.flyMode = SonicAirPlane.SUPERSONIC;
        sPlane.Fly();
        sPlane.flyMode = SonicAirPlane.NORMAL;
        sPlane.Fly();
    }
}
 
cs

 

 

 

'생각 두 접시' 카테고리의 다른 글

[java] 타입 변환과 다형성  (0) 2024.06.01
[java] final  (0) 2024.06.01
[java] Getter / Setter  (0) 2024.05.31
[java] 접근 제한자  (0) 2024.05.31
[java] 패키지  (0) 2024.05.31
2024-05-31 23:36:31

객체 지행 프로그램에서 상속은 자식 (하위, 파생) 클래스가 부모 (상위) 클래스의 멤버를 물려받는 것을 의미한다. 

자식이 부모를 선택해서 물려받을 수 있으며, 부모 클래스의 필드와 메소드를 상속받는다.

 

상속의 효과

- 부모 클래스를 재사용해 자식 클래스를 빨리 개발 가능

- 반복된 코드 중복을 줄임

- 유지 보수 편리성 제공

- 객체 다형성 구현 가능

 

부모 클래스의 private한 필드와 메소드, 다른 패키지의 default 필드와 메소드는 상속을 받을 수 없다.

(사실 protected나 public한 메소드를 이용하면 간접적으로 제어할 수 있다. like getter/setter)

 

자식 클래스가 상속할 부모의 클래스를 지정할 때 extends 키워드를 사용한다.

ex) public class child extends parent 

java는 단일 상속만 지원하며, 여러개의 부모클래스를 상속받을 수 없다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package Practice;
 
public class Phone {
    // private으로 설정하면 상속이 불가능하다
    // 대신 getter setter를 사용하면 간접적으로 제어가 가능하다
    public String model;
    public String color;
    
    public void bell()
    {
        System.out.println("벨이 울립니다");
    }
    public void sendVoice(String msg)
    {
        System.out.println("나 : " + msg);
    }
    public void reciveVoice(String msg)
    {
        System.out.println("너 : " + msg);
    }
    public void hangUp()
    {
        System.out.println("전화를 끊습니다");
    }
    
}
 
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package Practice;
 
public class SmartPhone extends Phone {
    private boolean wifi;
    
    public SmartPhone(String model, String color)
    {
        this.model = model;
        this.color = color;
        //super(model, color); 부모 클래스에 생성자가 있는경우 부모 클래스의 생성자 호출 가능
    }
    public boolean isWifi()
    {
        return wifi;
    }
    public void setWifi(boolean wifi) {
        this.wifi = wifi;
        System.out.println("wifi 상태 변경");
    }
    public void internet()
    {
        if (wifi == true)
            System.out.println("인터넷 연결");
        else
            System.out.println("인터넷 연결 실패");
    }
    
}
 
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package Practice;
 
public class SmartPhoneEx {
    public static void main(String[] args)
    {
        SmartPhone myPhone = new SmartPhone("S24""yellow");
        
        System.out.println("모델 : " + myPhone.model);
        System.out.println("색상 : " + myPhone.color);
        
        System.out.println("wifi : " + myPhone.isWifi());
        
        myPhone.bell();
        myPhone.sendVoice("Hello");
        myPhone.reciveVoice("World");
        myPhone.hangUp();
        
        myPhone.setWifi(true);
        myPhone.internet();
    }
}
 
cs

 

부모 클래스에 생성자가 존재한다면, super(매개값, ...) 으로 부모 클래스의 생성자를 호출 가능하다.

super 생성자는 반드시 자식 생성자의 첫 줄에 위치해야 하며, 부모 생성자가 존재하지 않는다면 컴파일 에러가 난다.

2024-05-31 22:51:52

일반적으로 클래스를 선언할 때 필드는 일반적으로 private으로 접근을 제한하고, 메소드를 통해서 필드에 접근해야 한다.

 

Getter

private 필드의 값을 리턴해주는 역할을 한다. 필요한 경우 필드의 값을 가공하기도 한다.

get필드명() 또는 is필드명() {필드 타입이 boolean인 경우} 의 형태를 띈다.

 

Setter

외부에서 주어진 값을 필드 값으로 수정해준다. 필요한 경우 유효성을 검사한다. (필드의 값을 대입만해주고, 증감은 다른 메소드로 하는것이 권장된다.)

set필드명(매개변수) 의 형태를 띈다.

매개변수의 타입은 필드의 타입과 동일해야 한다.

예제)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package Practice;
 
public class CarBasic {
    // 클래스의 각 필드를 private으로 선언하여 외부 접근을 제한한다
    private String company;
    private String model;
    private String color;
    private int maxSpeed;
    
    // 외부에서 값이 필요한 경우 값을 제공하기 위한 getter() 메소드 정의
    public String getCompany() {
        return company;
    }
    
    public String getModel() {
        return model;
    }
    public String getColor() {
        return color;
    }
    public int getMaxSpeed() {
        return maxSpeed;
    }
    
    // 외부호부터 주어진 값을 필드값으로 덕용하기 위해 setter() 메소드 정의
    // 필요한 경우 외부값의 유효성 검사가 가능하다
    public void setCompany(String company) {
        this.company = company;
    }
    
    public void setModel(String model) {
        this.model = model;
    }
    public void setColor(String color) {
        this.color = color;
    }
    public void setMaxSpeed(int maxSpeed) {
        if (maxSpeed > 250)
            maxSpeed = 250;
        this.maxSpeed = maxSpeed;
    }
}
 
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package Practice;
 
public class CarBasicEx {
    public static void main(String[] args)    
    {
        CarBasic car = new CarBasic();
        
        car.setCompany("현대");
        car.setModel("소나타");
        car.setColor("회색");
        car.setMaxSpeed(300); // 유효성 검사로 250으로 값 변경
        
        System.out.println(car.getCompany());
        System.out.println(car.getModel());
        System.out.println(car.getColor());
        System.out.println(car.getMaxSpeed());
 
    }
}
 
cs

'생각 두 접시' 카테고리의 다른 글

[java] final  (0) 2024.06.01
[java] 메소드 재정의 @Override  (0) 2024.06.01
[java] 접근 제한자  (0) 2024.05.31
[java] 패키지  (0) 2024.05.31
중복 요소 제거와 특정 키를 기준으로 오름차순 정렬하기  (0) 2024.03.20
2024-05-31 20:34:43

접근제한자는 클래스 및 클래스의 구성 멤버에 대한 접근을 제한하는 역할이다.

다른 클래스에서 클래스를 사용하지 못하도록 막거나 (클래스 제한)

클래스로부터 객체를 생성하지 못하도록 막거나 (생성자 제한)

특정 필드와 메소드를 숨김 처리한다 (필드 / 메소드 제한)

 

defaul

클래스 선언 시 아무 제한자도 명시하지 않았다면 자동적으로 컴파일러가 붙이는 제한자.

같은 패키지 내부에서만 호출이 가능하다                                                                                                

 

public 

접근의 제한이 없어, 모든 패키지에서 호출이 가능하다.

 

protected

같은 클래스 내부에서는 public 취급, 

자식 클래스가 아닌 다른 패키지의 클래스는 접근이 제한된다.

private

클래스 내부에서만 호출이 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
package Practice;
 
public class ClassA {
    ClassA c1 = new ClassA(true);
    ClassA c2 = new ClassA(true);
    ClassA c3 = new ClassA("문자열");
    
    ClassA(int data){}
    public ClassA(boolean data) {};
    private ClassA(String data) {};
}
 
cs
1
2
3
4
5
6
7
8
9
10
11
package Practice;
 
public class ClassB {
    ClassA c1 = new ClassA(true);
    ClassA c2 = new ClassA(19);
    // default인 boolean 생성자와
    // public인 int 생성자는 호출이 가능하다.
//    ClassA c3 = new ClassA("문자열");
    // 하지만 private인 문자열 생성자는 호출이 불가능하다.
}
 
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
package practice2;
 
import Practice.ClassA;
 
public class ClassB {
    ClassA c1 = new ClassA(true);
    // public 생성자 호출 가능
//    ClassA c2 = new ClassA(12);
    // default 생성자 호출 불가능 : package가 다름
//    ClassA c3 = new ClassA("문자열");
    // private 생성자 호출 불가능
}
 
cs

 

'생각 두 접시' 카테고리의 다른 글

[java] 메소드 재정의 @Override  (0) 2024.06.01
[java] Getter / Setter  (0) 2024.05.31
[java] 패키지  (0) 2024.05.31
중복 요소 제거와 특정 키를 기준으로 오름차순 정렬하기  (0) 2024.03.20
static에 관하여  (0) 2024.03.20