Home 7/25 JAVA 강의
Post
Cancel

7/25 JAVA 강의

7월 25일 (화) 자바 개념 정리 - Event Handler, Comparator, Comparable


Compare 예제 코드

|Comaparable|Comparator| |———–|————| |int compareTo(T o)|int compare(T o1, T o2)| |this context|x| |확장성 부족|비교만을 위한 클래스 생성 가능, 상위 객체를 인자로 받는 Comparator 가능|

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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package a2.comp;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class TestCompare {

	public static void main(String[] args)
	{
		ArrayList<A> a = new ArrayList<A>();
		a.add(new A("temp", 1));
		a.add(new A("tempa", 2));
		a.add(new A("tempb", 2));
		a.add(new A("temp", 4));
		a.add(new A("temp", 5));
		
		Collections.sort(a);
		System.out.println(a);
		
		ArrayList<B> b = new ArrayList<B>();
		b.add(new B("temp"));
		b.add(new B("temp"));
		b.add(new B("temp"));
		b.add(new B("temp"));
		b.add(new B("temp"));
		
		/* 
		 * 상속 관계가 존재하지 않는 A,B 클래스 사이에서
		 * B 클래스가 Comparable<A> 인터페이스를 구현한다면,
		 * compareTo(A o)의 인자로 비교가 불가하므로 에러가 발생한다.
		 */
		// Collections.sort(b);
		
		ArrayList<AA> aa = new ArrayList<AA>();
		aa.add(new AA(1));
		aa.add(new AA(2));
		aa.add(new AA(2));
		aa.add(new AA(4));
		aa.add(new AA(5));
		aa.add(new BB(1,2));				// 자식 클래스가 부모 클래스 ArrayList에 들어가는 건 가능(부모는 자식을 품을 수 있다)
		Comparator<AA> compAA = new AA();	// 기본 생성자가 없으면 객체 생성시 인자를 줘야 에러 안난다
		Collections.sort(aa, compAA);		// comparator에 의한 비교라면 두번째 인자로 객체를 넘겨줘야 함
		System.out.println(aa);
		
		Comparator<AA> compD = new D();		// 다른 기준으로 sort (내림 차순)
		Collections.sort(aa, compD);
		System.out.println(aa);
		
		ArrayList<BB> bb = new ArrayList<BB>();
		bb.add(new BB(1,4));				// 자식은 부모를 품을 수 없다 (단, 명시적 캐스팅을 하면 컴파일은 가능하나 런타임 에러를 일으킨다.)
		bb.add(new BB(1,3));
		bb.add(new BB(2,4));
		bb.add(new BB(0,2));
		bb.add(new BB(1,3));
		
		// 구현한 인터페이스의 Comparator type이 AA라 <AA>가 들어간다
		Comparator<AA> compBB = new BB(0,0);	// 기본 생성자가 없어서 인자를 주면서 객체 생성해야 된다.
		Collections.sort(bb, compBB);
		System.out.println(bb);
	}
}

class A implements Comparable<A>{
	String s;
	int n;
	
	A(String s, int n) {
		this.s = s;
		this.n = n;
	}
	@Override
	public int compareTo(A o) {
		if(this.n != o.n)
			return - this.n + o.n;
		return this.s.compareTo(o.s);
	}
	@Override
	public String toString() {
		return "A : " + this.s + "," + this.n;
	}

	
	
}

class B implements Comparable<A>{
	String s;
	
	B(String s) {
		this.s = s;
	}
	@Override
	public int compareTo(A o) {
		return this.s.compareTo(o.s);
	}
}

class AA implements Comparator<AA> {
	
	int aa;
	AA() {
		
	}
	
	AA(int aa) {
		this.aa = aa;
	}
	@Override
	public int compare(AA o1, AA o2) {
		return o1.aa - o2.aa;
	}
	
	@Override
	public String toString() {
		return "AA : " + this.aa;
	}
	
}

/**
 * 상속 받고 싶다면 AA 클래스 비교 함수를 구현해야한다.
 * 아니면 인터페이스를 아예 오버라이드하지 않고 상위 클래스의 compare함수를 쓴다.
 */
class BB extends AA implements Comparator<AA> {
	
	int bb;
	BB(int aa, int bb) {
		super(aa);
		this.bb = bb;
	}
	@Override
	public int compare(AA o1, AA o2) {
		return (((BB)o1).bb) - (((BB)o2).bb);
	}
	
	@Override
	public String toString() {
		return "BB : " + this.aa + "," + this.bb;
	}
	
}

/*
Compartor<BBB>를 구현할 수 없다
AA 클래스에서 Comparator<AA>를 구현했으므로,
Override를 하려면 AA 클래스를 인자로 받아야한다
class BBB extends AA implements Comparator<BBB> {
	@Override
	public int compare(BBB o1, BBB o2) {
		return 0;
	}
}
*/

/**
 * 다양한 기준으로 비교하고 싶은 경우
 * 비교 연산만을 위한 클래스를 작성한다
 */
class D implements Comparator<AA> {

	@Override
	public int compare(AA o1, AA o2) {
		return o2.aa - o1.aa;
	}
	
}

Event Handler 예제 코드

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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package a1.event;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class TestEventHandler {

	public static void main(String[] args) {
		// JFrame frame01 = new MyFrame01();
		// JFrame frame02 = new MyFrame02();
		// JFrame frame03 = new MyFrame03();
		// JFrame frame04 = new MyFrame04();
		// JFrame frame05 = new MyFrame05();
	}

}

/**
 * 1. 독립적인 클래스 작성
 * 
 * JFrame을 상속받은 MyFrame ActionListener를 상속받은 MyListener
 * 
 * 리스너 인터페이스를 구현하여 완전한 클래스로 이벤트 리스너를 구현한다 GUI 컴포넌트에 리스너를 추가한다
 */
class MyFrame01 extends JFrame {

	private JButton button;

	public MyFrame01() {
		this.setSize(300, 200);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		button = new JButton("버튼");
		button.addActionListener(new MyListener01());

		this.add(button);
		this.setVisible(true);
	}
}

class MyListener01 implements ActionListener {

	@Override
	public void actionPerformed(ActionEvent e) {
		JButton button = (JButton) e.getSource();
		button.setText("버튼이 눌림");
	}
}

/**
 * 2. Inner 클래스 작성
 * 
 * 1의 방법에서 리스너 클래스를 Frame 클래스의 내부로 옮긴다
 *
 */
class MyFrame02 extends JFrame {

	private JButton button;

	public MyFrame02() {
		this.setSize(300, 200);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		button = new JButton("O");
		button.addActionListener(new MyListener02());

		this.add(button);
		this.setVisible(true);
	}

	private class MyListener02 implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			JButton b = (JButton) e.getSource();
			if (b.getText().equals("X")) {
				b.setText("O");
			} else {
				b.setText("X");
			}

			// MyFrame02의 멤버를 호출할 수 있다.
			if (button.getBackground() == Color.GRAY)
				button.setBackground(Color.GREEN);
			else
				button.setBackground(Color.GRAY);
		}
	}
}

/**
 * 3. JFrame을 상속받으면서 ActionListener도 구현하는 경우
 */
class MyFrame03 extends JFrame implements ActionListener {

	private JButton button;

	public MyFrame03() {
		this.setSize(300, 200);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		button = new JButton("버튼");
		button.addActionListener(this);

		this.add(button);
		this.setVisible(true);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		System.out.println((e.getSource()));
		if (button == (JButton) (e.getSource())) {
			button.setText("누름");
		}
	}
}

/**
 * 4. 익명 클래스를 통해 이벤트 리스너를 구현하는 경우
 * 
 * 	1) 따로 구현한 이벤트 클래스의 클래스 시그니쳐를 제외한 코드 전부를 잘라낸다
 * 	2) new ActionListener() 뒤에 이를 붙여넣는다
 */
class MyFrame04 extends JFrame {

	private JButton button;

	public MyFrame04() {
		this.setSize(300, 200);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		button = new JButton("버튼");
		button.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				if (button == e.getSource()) {
					button.setText("눌림");
				}
			}
		});

		this.add(button);
		this.setVisible(true);
	}
}

/**
 * 람다 표현식으로 이벤트 리스너를 구현하는 경우
 *	1) 올 수 있는 인터페이스나 클래스가 하나밖에 없고, 함수도 하나 밖에 없는 경우
 *		함수 파라미터를 괄호 안에 작성하고 화살표로 연결한 뒤 괄호 내에 함수를 작성한다	
 */
class MyFrame05 extends JFrame {
	private JButton button;

	public MyFrame05() {
		this.setSize(300, 200);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		button = new JButton("버튼");
		button.addActionListener((e)-> {
			((JButton)(e.getSource())).setText("눌림");
		});

		this.add(button);
		this.setVisible(true);
	}
}
This post is licensed under CC BY 4.0 by the author.