1. java.lang패키지 

- 가장 기본이 되는 패키지이며, import문 없이도 사용이 가능하다.

- 최상위 객체인 Object클래스 외에도, String, Math, Wrapper클래스가 있다.

 

1-1. Object클래스의 주요 메서드

+equals() 객체의 주소값을 비교한다.
+hashCode() 객체의 해쉬코드를 반환한다.
*모든 객체는 자신을 구분하는 고유의 해시코드를 가진다.
*자바에서는 해싱 기법을 통해 다양한 객체를 구분하여 저장한다.
+getClass() 객체의 인스턴스를 반환한다.
+toString() "클래스이름+@+해쉬코드"문자열을 반환한다.
#clone() 객체를 얕게 복사하여 반환한다.
(객체 내 포함된 객체까지는 복사되지 않으므로, 겉의 객체만 복사되면, 안의 객체는 사실상 동일한 곳을 참조하므로 복사된 객체를 수정할 때 기존 객체의 안쪽 객체 정보까지 수정될 수 있다.)

 

1-2. String클래스

- 이부분은 별도로 정리하였다.

- 간략하게 String은 "변경 불가하다"라는 점과, 그렇기에 StringBuffer와 StringBuilder로 처리할 수 있다는 점만 기억하자..

https://why-dev.tistory.com/31?category=928637 

 

[자바의 정석_복습] String 객체에 대한 이해

심플한 개발 [자바의 정석_복습] String 객체에 대한 이해 본문 JAVA/문자열, 배열 [자바의 정석_복습] String 객체에 대한 이해 심플한 개발 2022. 3. 15. 19:08 Prev 1 ··· 5 6 7 8 9 10 Next

why-dev.tistory.com

 

1-3. Math클래스

+round() : long 소수점 첫째자리에서 반올림을 한다.
(사용시, 10^x 만큼 곱하고 나누어 원하는 만큼 반올림하면 된다.)
+ceil() 올림
+floor() 버림
.... 기타

 

1-4. Wrapper클래스

- Boolean, Character, Number가 있으면 Number안에 정수형, 실수형 변수객체들이 있다.

- 문자열을 숫자로 변환하는 법 : Integer.parseInt("문자열")

- 오토박싱과 언박싱

https://why-dev.tistory.com/45

 

[자바_문법] Wrapper 클래스 이해

Wrapper클래스  Wrapper : Boolean, Byte, Integer, Long, Float, Double Wrapper클래스의 오토-언박싱과 오토-박싱  - Auto-Boxing : [Auto-Boxing 예제_Object객체배열 안에 다양한 타입의 기본형 리터럴 입력..

why-dev.tistory.com

 

 

 

[참조]

자바의 정석, 남궁성  -- 요약한 내용입니다.

'Language > Java' 카테고리의 다른 글

[자바_문법] 쓰레드  (0) 2022.04.17
[자바의정석_예제] 객체지향프로그래밍2  (0) 2022.04.13
[자바_API] 입출력 I/O  (0) 2022.04.05
[자바_API] 네트워킹  (0) 2022.04.04
[자바의정석_복습] 예외처리  (0) 2022.03.28

1. 스트림이란? 데이터를 운반하는데 사용되는 연결통로

  [생각] BJ는 온라인방송을 할 때, 왜 "스트리밍 중"이라고 할까?

 

2. 바이트기반 스트림_InputStream/OutPutStream 추상클래스 상속

입력스트림 출력스트림 입출력 대상의 종류
FileInputStream FileOutputStream 파일
ByteArrayInputStream ByteArrayOutputStream 메모리(byte배열)
PipedInputStream PipedOutputStream 프로세스(프로세스간의 통신)
AudioInputStream AudioOutputStream 오디오장치
.... .... ....

(1) InputStream 메서드

리턴타입 메소드  
int read() 입력 스트림에서 1byte씩 읽고 byte값을 int으로 반환
int read(byte[] b) 입력 스트림에서 1byte씩 읽어 byte배열에 저장, 읽은 갯수를 반환
int read(byte[] b, int off, int len) 입력 스트림에서 off부터 시작하여, len개를 읽어 byte 배열에 저장,
읽은 갯수를 반환
void close() 시스템의 자원을 반환하고 입력 스트림을 닫는다. (파일)

▶ read() 메소드

InputStream is = new FileInputStream("C:/test.jpg");
int readByte;
//모든 InputStream 하위 객체 read() : 읽은 내용이 없으면 -1 반환
while((readByte = is.read()) != -1){}

▶ 키보드에서 읽어오기 : System.in

package mymain.input;

import java.io.InputStream;

public class _01_KeyboardInputTest {

	public static void main(String[] args) throws Exception {
		int ch;
		
		//키보드의 입력값을 받는 inputStream
		//System객체 내에 포함관계로 inputStream이 생성되어 있는 상태
		InputStream is = System.in; 
		
		System.out.println("종료하려면 [Ctrl+Z]");
		
		while((ch = is.read()) != -1) {
			System.out.printf("%c",ch);
		}
	}

▶ 파일에서 읽어오기 : FileInputStream("파일경로")

package mymain.input;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class _02_FileInputTest {
	public static void main(String[] args) throws IOException {
		InputStream is = new FileInputStream("src/mymain/input/_02_FileInputTest.java");
		
		int ch;
		
		while((ch = is.read())!=-1) {
			System.out.printf("%c",ch);
		}
		
		is.close();
	}
}

▶ 네트워크에서 읽어오기 : URL(String url) > openStream()

package mymain.input;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

public class _03_NetWorkInputStream {
	public static void main(String[] args) throws IOException {
		URL url = new URL("https://www.naver.com");
		InputStream is = url.openStream();
		
		int ch;
		
		while((ch = is.read())!=-1) {
			System.out.printf("%c",ch);
		}
	}
}

 

(2) OutputStream 메서드

리턴타입 메소드  
void write() 출력 스트림으로 1byte씩 보낸다.
void write(byte[] b) 출력 스트림에 byte[] b의 값을 보낸다.
void write(byte[] b, int off, int len) 출력 스트림에 off부터 시작해서 len개 만큼 보낸다.
void flush() 버퍼에 잔류하는 모든 바이트를 출력
void close() 시스템의 자원을 반납하고 출력 스트림을 닫는다. (파일)

▶ read() 메소드

OutputStream os = new FileOutputStream("C:/test.txt");
byte[] data = "ABC".getBytes();
for(int i = 0; i < data.length; i++){
	os.write(data[i]);
}

 

▶ 모니터로 출력하기 : System.out

package mymain.output;

import java.io.IOException;
import java.io.OutputStream;

public class _01_MonitorTest {
	public static void main(String[] args) throws IOException {
		OutputStream os = System.out;
		
		//자바 -> 출력 스트림 -> 키보드버퍼로 문자를 전송
		os.write(65);
		
		String msg = "안녕";
		byte[] msg_bytes = msg.getBytes();
		os.write(msg_bytes);
		
		int n = 1004;
		String s = String.valueOf(n);
		os.write(s.getBytes());
		
		boolean bOk = true;
		String b = String.valueOf(bOk);
		os.write(b.getBytes());
		
		//키보드 커퍼를 비우면서 콘솔로 전송
		os.flush();
	}
}

▶ 파일로 출력하기 : FileOutputStream("파일경로");

package mymain.output;

import java.io.FileOutputStream;
import java.io.OutputStream;

public class _02_FileOutTest {

	public static void main(String[] args) throws Exception{
		OutputStream os = new FileOutputStream("a.txt");
		
		os.write('A');
		
		String name = "홍길동";
		byte[] sArr = name.getBytes();
		os.write(sArr);
		
		int n = 1994;
		os.write(String.valueOf(n).getBytes());
		
		os.flush();
		
		os.close();
	}

}

 

(3) 바이트 배열 단위로 읽어오기/보내기

가. InputStream/OutputStream의 read(byte[] b), write(byte[] b) 사용

package mymain.input;

import java.io.FileInputStream;
import java.io.InputStream;

public class _04_InputStream_Array {
	public static void main(String[] args) throws Exception{
		InputStream is = new FileInputStream("src/mymain/input/_04_InputStream_Array.java");
		
		int readByteNo;
		byte[] readBytes = new byte[8];
        //           is.read(readBytes, 1, 8); <- index 1부터 8개
		readByteNo = is.read(readBytes);
		
		for(int i = 0; i < readBytes.length; i++) 
			System.out.printf("%c",readBytes[i]);
		
		is.close();
	}
}
package mymain.output;

import java.io.FileOutputStream;
import java.io.OutputStream;

public class _03_OutputStream_Array {
	public static void main(String[] args) throws Exception{
		OutputStream os = new FileOutputStream("a2.txt");
		
		byte[] output = "ABC".getBytes();
		
		// os.write(output,1,2); /*: index1부터 2개*/
		os.write(output);
		
		os.close();
	}
}

 

나. ByteArrayInputStream/ByteArrayOutputStream 객체 사용

package mymain.input;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;

public class _04_InputStream_Array2 {
	public static void main(String[] args) throws Exception{
		byte[] inSrc = {0,1,3,4,5,6};
		byte[] outSrc = null;
		
		ByteArrayInputStream input = null;
		ByteArrayOutputStream output = null;
		
		input = new ByteArrayInputStream(inSrc);
		output = new ByteArrayOutputStream();
		
		int data = 0;

		while((data = input.read()) != -1) {
			output.write(data);
		}
		
		outSrc = output.toByteArray();
		
		System.out.println("Input Source : "+Arrays.toString(inSrc));
		System.out.println("Output Source : "+Arrays.toString(outSrc));
	}
}

>> 결과

Input Source : [0, 1, 3, 4, 5, 6]
Output Source : [0, 1, 3, 4, 5, 6]

 

 

3. 문자기반 스트림_Reader,Writer 추상클래스 상속

입력스트림 출력스트림 입출력 대상의 종류
FileReader FileWriter 파일
ByteArrayReader ByteArrayWriter 메모리(byte배열)
PipedReader PipedWriter 프로세스(프로세스간의 통신)
StringReader StringWriter 문자열
.... .... ....

 

4. 보조스트림_Filterxxxxx, Bufferedxxxxx, Objectxxxxx

입력스트림 입출력 대상의 종류
Filterxxxxx 필터를 이용한 입출력 처리
Bufferedxxxxxx 버퍼를 이용한 입출력 향상 (버퍼에 바이트/문자 올려두고, 한 줄씩 출력 가능-nextLine())
Objectxxxxxx 객체 직렬화/역직렬화

 

 

 

[참조]

이것이 자바다 

자바의 정석, 남궁성 지음

1. 네트워킹이란? 

두 대 이상의 컴퓨터를 케이블로 연결하여 네트워크를 구성하는 것

* 자바에서는 java.net 패키지를 활용해 네트워크 어플의 데이터 통신을 쉽게 작성 가능하다.

https://www.youtube.com/watch?v=yR4hnj5XNP4&t=5s 


  [참조 : OSI 7 계층, TCP 4 layer]
  https://velog.io/@dyllis/OSI-7%EA%B3%84%EC%B8%B5-%EC%A0%95%EB%A6%AC
  - OSI 7계층 : 물리계층 - > 데이타 링크 계층/ -> 네트워크계층/ -> 전송계층 / -> 세션 계층 -> 표현 계층 -> 응용계층

 

2. 클라이언트와 서버

* 서비스란? 서버가 클라이언트로부터 요청받은 작업을 처리하여 그 결과를 제공하는 것

- 클라이언트와 서버와의 관계

클라이언트 <-> 서버
[1] 연결을 요청
[3] 처리 요청
  [2] 연결 수락
[4] 처리/응답 (서비스 제공)

- 서버의 모델

명칭 서버 기반 모델 (server-based model) P2P모델(peer-to-peer model)
내용 전용 서버를 둠 전용 서버 없이 각 클라이언트가 서버역할 동시수행
장/단점 - 안정적인 서비스 제공 가능
- 공유데이터의 관리와 보완이 용이
- 서버 구축 비용과 관리 비용이 든다.
- 서버 구축 및 운용비용을 절감 가능
- 자원의 활용을 극대화 가능
- 자원의 관리가 어려움
- 보안이 취약

 

3. IP주소 : "내 컴퓨터"를 나타내는 주소. 

https://www.youtube.com/watch?v=IAS3U5ZiI8c 

코딩하는거니님의 IP에 대한 설명

- 4byte로 0~255사이로 표현 (ex. 255.255.255.0)

- 앞의 3byte는 네트워크 주소 + 뒤 1byte는 호스트 주소

- 명령프롬프트에서 "ipconfig/All" 또는 "ipconfig"를 치면 확인 가능

 

3-1. java.net패키지의 InetAddress클래스

[1] 로컬 컴퓨터에서 IP 주소 얻으려 할 때

//객체 생성
InetAddress ip = InetAddres.getLocalHost();

//객체 이름, 주소 추출 : String으로 반환
String ipName = ip.getHostName();
String ipAddress = ip.getHostAddress();

 

[2] 도메인 이름으로 IP 주소 얻으려 할때

//도메인에서 단일 ip 주소 가져오기
InetAddress ip = InetAddress.getByName("www.naver.com");

//도메인에서 여러개의 ip주소 가져오기
InetAddress[] ipArr = InetAddress.getAllByName("www.naver.com");

 

4. URL(Uniform Resource Locator)

- 형태 : 프로토콜://호트스명:포트번호/경로명/파일명?쿼리스트링#참조 

- 예시 ) http://www.naver.com:80/sample/hello.html?refer=codechobo#index1

프로토콜 서버와 통신할 때 사용되는 통신규약(HTTP)
호스트명 자원을 제공하는 서버명(ex.www.naver.com)
포트번호 통신에서 사용되는 서버의 포트 번호
경로명 경로
파일명 파일명 (ex. index.html)
쿼리 URL에서 ? 이후의 부분 
참조 URL에서 # 이후의 부분

※ Filezilla에서 보는 호스트와 포트, 사용자명 개념

→ 호스트 : 도메인을 작성하거나, ip주소를 작성하는 공간

→ 사용자명 : 해당 호스트 사용자명 (보통 회사에서 지정해주는 게 있다.)

→ 비밀번호 : 접속 시 비밀번호

→ 포트 : 통신에서 사용되는 서버의 포트 번호 (일반적으로 FTP포트는 21이 가장 많다)

 

5. 소켓 프로그래밍

[1] 소켓에 대하여

- 소켓이란?

  프로세스 간의 통신에 사용되는 양쪽 끝단으로

  네트워크 기능(OS의 네트워크 라이브러리)을 용이하게 이용하기 위한 각 언어별 모듈(객체)이다.

- 모든 소켓은 각각 자신만의 InputStream, OutputStream을 가지고 있다.

- JVM은 각 운영체제별로 다르게 작동하며, 각 운영체제의 네트워크 라이브러리에 맞춘 소켓을 사용한다.

[2] 포트란?

- 같은 컴퓨터 내에서 프로그램을 식별하는 번호

- 0~65535 범위 (총 65536개) 값을 가질 수 있다.

- 세 가지 범위로 구분

(1) Well Known : 0~1023, ICANN가 애플리케이션용으로 미리 예약한 포트로 FTP, Telnet 등에서 사용

(2) Registed : 1024~49151, 회사에서 등록해서 사용 가능한 포트값

(3) Dynamic or Private : 49152~65535, 운영체제가 부여하는 동적 포트 또는 개인 목적의 포트

 

6. TCP와 UDP 프로토콜

- 클라이언트와 서버를 연결하는 프로토콜에는 여러가지 종류가 있다. 

- TCP,UDP 외에도 통신 프로토콜로 HTTP 등이 있다.

항목 TCP UDP
연결방식 연결기반
- 연결 후 통신(전화기)
비연결기반
- 연결 없이 통신 (소포)
특징 데이터의 경계를 구분 안함 (바이트스트림)
신뢰성 높은 데이터 전송
- 데이터의 전송순서가 보장됨
- 데이터의 수신여부를 확인함
  (데이터가 손실되면 재전송됨)
- 패킷을 관리할 필요가 없음
UDP보다 전송속도가 느림
데이터 전송용량의 제한이 없음
데이터의 경계를 구분함(datagram)
신뢰성 낮은 데이터 전송
- 데이터의 전송순서가 바뀔 수 있음
- 데이터의 수신여부를 확인안함
  (데이터가 손실되어도 알 수 없음)
- 패킷을 관리해주어야 함
TCP보다 전송 속도가 빠름
1회 전송량 512byte
관련 클래스 Socket

ServerSocket
DatagramSocket
DatagramPacket
MulticastSocket
통신 방식 Uni-cast (1:1) BroadCast(불특정 다수) 
- local broadcast
pf. xxx.xxx.xxx.255 로 일괄 전달
- global broadcast
pf. 255.255.255.255 로 일괄 전달

MultiCast(특정 다수) 
pf. 회원 가입 대상자들만 전달
pf. 224.0.0.1 ~ 239.255.255.255

[참고] 

  유니캐스트 VS 브로드캐스트 VS 멀티캐스트
  https://m.blog.naver.com/wnrjsxo/221250742423

 

7. TCP 소켓 프로그래밍

- "이것이 자바다" 영상의 아래 그림이 TCP를 이해하는데 많은 도움을 주는 것 같다. 

[이것이 자바다] 참조

[1] 송신 방법

package tcpProtocol;

import java.io.OutputStream;
import java.net.Socket;

public class BasicSend {

	public static void main(String[] args) throws Exception{
		//[1] 소켓을 연다.(연결할 서버소켓의 주소와 포트를 작성)
		Socket socket = new Socket("localhost",50000);
		OutputStream os = socket.getOutputStream();
		
		for(int i = 1; i <= 3; i++) {
			//[2] 소켓의 OutputStream을 통해 byte단위의 데이터를 전송한다.
			String data = "데이터"+i;
			os.write(data.getBytes("UTF-8"));
		}
		os.flush();
		
		//[3] 소켓 연결 끊기
		//socket.close(); --> 의도적인 종료 : -1 값을 전달한다.
		socket.close();
	}

}

 

[2] 수신 방법

package tcpProtocol;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class BasicAccept {

	public static void main(String[] args) throws Exception{
		//[1] 서버 소켓을 연다.
		ServerSocket serverSocket = new ServerSocket(50000);
		
		try {
			//[2] 소켓을 연다.
			Socket socket = serverSocket.accept();
			InputStream is = socket.getInputStream();
			
			//무한 루프로 수신 대기
			System.out.println("[수신 데이터]");
			while(true) {
				//[3] InputStream을 통해 바이트단위 데이터를 가져온다.
				byte[] byteArr = new byte[300]; //한글 3byte->100자씩 읽을 것
				int len = is.read(byteArr);
				if(len == -1) break;
				String data = new String(byteArr,0,len,"UTF-8");
				//[4] 수신 data 콘솔에 출력
				System.out.println(data);
			}
		} catch (IOException e) {
			System.out.println("[연결 종료]");
		}
	
	}

}

 

[연습 예제_1] TCP 1:1 전송방식으로 로컬컴퓨터에서 에코메시지 전달하기

<Client>

package tcpProtocol;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.*;

public class Client extends JFrame{
	
	JTextArea textMonitor;
	JTextField textInput;
	JButton button;
	Socket socket;
	
	Client(){
		/* Initial Window UI Design  */
		super("Chat for Client");
		setLocation(300,300);
		setVisible(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		init_UiDesign();
		pack();
		
		/* TCP Socket Communication */
		init_buttonAction();
		init_socket();
		
	}//end Client()
	
	/////////////////////////////////////////////////////
	
	/* TCP Socket Communication Method */
	
	private void init_buttonAction() {
		
		button.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String textMessage = String.format("[사용자] %s%n", textInput.getText().trim());
				if(textMessage.isEmpty()) {
					JOptionPane.showMessageDialog(textMonitor,"메세지를 입력하세요.");
					return;
				}else {
					//textMonitor.append(textMessage);
					echo_message();
					textInput.setText("");
					return;
				}
			}
		});
	}
	
	private void init_socket() {
		try {
			socket = new Socket("localhost",50000);
		} catch (UnknownHostException e) {
			System.out.println("해당 호스트를 찾을 수 없습니다.");
		} catch (IOException e) {
			System.out.println("포트가 비정상적으로 닫혀있습니다.");
		}
	}

	protected void echo_message() {
		send_message();
		receive_message(); 
	}


	private void send_message() {
		//send Message to server
		try {
			OutputStream outStream = socket.getOutputStream();
			String userMessage = String.format("[사용자] %s%n", textInput.getText().trim());
				//append message to Monitor
			textMonitor.append(userMessage);
			outStream.write(userMessage.getBytes());
			outStream.flush();
		} catch (IOException e) {
			System.out.println("전송에 오류가 발생했습니다.");
		}
	}
	
	private void receive_message() {
		//receive Message from server
		try {
			byte[] readBytes = new byte[300];
			int readNum = socket.getInputStream().read(readBytes);
			String echoedMessage = new String(readBytes,0,readNum);
			
			//append message to Monitor
			textMonitor.append(echoedMessage);
		} catch (IOException e) {
			System.out.println("수신에 오류가 발생했습니다.");
		}
	}

	

	/* UI Design Method */
	
	private void init_UiDesign() {
		//textMonitor : where chat text reveals
		textMonitor = new JTextArea();
		textMonitor.setBackground(new Color(0x7BC4C4));
		textMonitor.setEditable(false);
		JScrollPane jsp = new JScrollPane(textMonitor);
		textMonitor.setPreferredSize(new Dimension(300,200));
		this.add(jsp);
		
		//textInput : where user types texts & send
		JPanel jpl = new JPanel(new BorderLayout());
		textInput = new JTextField();
		button = new JButton("전송");
		jpl.add(textInput);
		jpl.add(button,"East");
		this.add(jpl,"South");
	}

	public static void main(String[] args) {
		new Client();
	}//end main
}

 

<Server>

package tcpProtocol;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.*;

public class Server extends JFrame{
	
	JTextArea textMonitor;
	JTextField textInput;
	JButton button;
	ServerSocket serverSocket;
	Socket socket;
	
	Server(){
		/* Initial Window UI Design  */
		super("Chat for Server");
		setLocation(300,300);
		setVisible(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		init_UiDesign();
		pack();
		
		/* TCP Socket Communication */
		init_socket();
		
	}//end Client()
	
	
	/////////////////////////////////////////////////////
	
	/* TCP Socket Communication Method */
	
	private void init_socket() {
		try {
			serverSocket = new ServerSocket(50000);
			socket = serverSocket.accept();
			while(true) {
				//receive Message from client
				byte[] readBytes = new byte[300];
				int readNum = socket.getInputStream().read(readBytes);
				String[] userMessage = new String(readBytes,0,readNum).split("]");
				
				//append message to Monitor
				textMonitor.append(new String(readBytes,0,readNum));
				
				//send Message to client
				OutputStream outStream = socket.getOutputStream();
				String echoedMessage = String.format("[에코]%s%n",userMessage[1]);
					//append message to Monitor
				textMonitor.append(echoedMessage);
				outStream.write(echoedMessage.getBytes());
				outStream.flush();
			}
			
		} catch (IOException e) {
			JOptionPane.showMessageDialog(this, e.getMessage());
		}
		
	}

	/* UI Design Method */
	
	private void init_UiDesign() {
		//textMonitor : where chat text reveals
		textMonitor = new JTextArea();
		textMonitor.setBackground(new Color(0x7BC4C4));
		textMonitor.setEditable(false);
		JScrollPane jsp = new JScrollPane(textMonitor);
		textMonitor.setPreferredSize(new Dimension(300,200));
		this.add(jsp);
		
		//textInput : where user types texts & send
		JPanel jpl = new JPanel(new BorderLayout());
		textInput = new JTextField();
		button = new JButton("전송");
		jpl.add(textInput);
		jpl.add(button,"East");
		this.add(jpl,"South");
	}

	public static void main(String[] args) {
		new Server();
	}//end main
}

>>결과

 

 

8. UDP 소켓 프로그래밍

- UDP는 소포와 같이 서버소켓을 통한 연결 없이 수신, 송신만 가능한 형태이다.

- 통신 선로가 고정적이지 않음

- 데이터 손실이 발생 가능

- 대신 TCP보다는 빠르게 전송이 가능하다

이것이 자바다 참조

[1] 송신하는 법

//송신하는 법
//[1] DatagramSocket를 연다.
DatagramSocket datagramSocket = new DatagramSocket();
//만약, multi-cast방식으로 전달할 경우, 
//MulticastSocket multicastSocket = new MulticastSocket();
InetAddress ia = InetAddress.getByName("localhost"); //수신되는 곳의 주소

//[2] 전달할 데이터를 패킷으로 패킹한다.
String data = "전달 데이터";
byte[] byteArr = data.getBytes("UTF-8"); //UTF-8방식으로 바이트 변환
DatagramPacket packet = new DatagramPacket(
	byteArr, byteArr.length,ia,포트번호
);

//[3] DatagramSocket을 통해 패킷을 전송한다.(바이트단위로 전송된다)
datagramSocket.send(packet);

//[4] DatagramSocket을 닫아준다.
datagramSocket.close();

[2] 수신하는 법

//수신하는 법
//[1] DatagramSocket을 연다.
DatagramSocket datagramSocket = new DatagramSocket(포트번호);

//[2] 패킷을 받을 배열과 길이를 지정한다.
DatagramPacket datagramPacket = new DatagramPacket(받은 배열을 저장할 바이트 배열,배열의 길이);

//[3] 패킷을 받는다.
datagramSocket.receive(datagramPacket);

//[4] 소켓을 닫는다.
datagramSocket.close();

 

[연습 예제_간단한 데이터 송수신]

<Client>

package udpProtocol;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class Client {

	public static void main(String[] args) throws Exception{
		//[1] 데이터그램 소켓으로 가야하는 곳을 지정
		DatagramSocket datagramSocket = new DatagramSocket();
		InetAddress ia = InetAddress.getByName("localhost");
		
		for(int i = 1; i <= 3; i++) {
			//[2] 데이터그램 패킷으로 데이터를 묶어둔다. 
			String data = "데이터"+i;
			byte[] byteArr = data.getBytes("UTF-8");
			DatagramPacket datagramPacket = new DatagramPacket(
				byteArr, byteArr.length,ia,8000
			);	
			
			//[3] 패킷을 소켓을 통해 전송한다.
			datagramSocket.send(datagramPacket);
			
		}//end for
		
		//[4] 소켓을 닫는다.
		datagramSocket.close();
		
	}//end main

}

<Server>

package udpProtocol;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Server {

	public static void main(String[] args) throws Exception{
		//[1] 소켓을 연다.
		DatagramSocket datagramSocket = new DatagramSocket(8000);
		
		//[2] 패킷 단위로 데이터를 받는다.
		//쓰레드를 형성해서 무한 루프로 데이터를 받는다.
		Thread thread = new Thread() {
			@Override
			public void run() {
				System.out.println("수신 시작");
				try {
					while(true) {
						DatagramPacket packet = new DatagramPacket(new byte[100],100);
						datagramSocket.receive(packet);
						String data = new String(packet.getData(),0,packet.getLength(),"UTF-8");
						System.out.println("[받은 내용 : "+packet.getSocketAddress()+"]"+data);
					}
				} catch (IOException e) {
					System.out.println("[수신 종료]");
				}
			}
		};//end thread
		
		thread.start();
		
		Thread.sleep(10000);
		datagramSocket.close();
	}//end main

}

>> 수신 결과

수신 시작
[받은 내용 : /127.0.0.1:55273]데이터1
[받은 내용 : /127.0.0.1:55273]데이터2
[받은 내용 : /127.0.0.1:55273]데이터3
[수신 종료]

 

[참조]

- 자바의 정석, 남궁성 지음

- 이것이 자바다

- 코딩하는 거니

- 티스토리 블로그 

- 그 외 : 국비지원 수업 내용 참조

>> 실행결과

차수 : 5
---snail1---
[   1   2   3   4   5]
[  16  17  18  19   6]
[  15  24  25  20   7]
[  14  23  22  21   8]
[  13  12  11  10   9]
---snail2---
[  25  24  23  22  21]
[  10   9   8   7  20]
[  11   2   1   6  19]
[  12   3   4   5  18]
[  13  14  15  16  17]
또?(y/n) : n
----END----

[Snail 객체]

package myutil;

public class Snail {
	//Right -> Down -> Left -> Up
	//이 과정을 반복하되,
	//만약 움직이려는 방향에 값이 있을 경우, 현재 자리에서 이동하지 않고,
	 //값을 넣지 않고 방향을 전환한다.
	//Right : col++
	//Down : row++
	//Left : col__
	//Up : row--
	
	//이동 정보에 대한 상수 선언
	public static final int RIGHT = 1;
	public static final int DOWN = 2;
	public static final int LEFT = 3;
	public static final int UP = 4;
	
	//현재 이동 방향 정보를 저장할 변수
	int direction;
	
	int chasu;	
	int[][] snail_array;
	
	public void setChasu(int chasu) {
		this.chasu = chasu;
		
		System.out.println("---snail1---");
		
		//달팽이 만들기
		make_snail();
		
		//출력
		display();
		
		System.out.println("---snail2---");
		
		//달팽이 만들기
		make_snail2();
		
		//출력
		display();
	}
	
	private void make_snail() {
		//달팽이 배열 생성
		snail_array = new int[chasu][chasu];
		
		int row = 0;
		int col = -1;
		int su = 1;
		
		direction = RIGHT;
		
		//[0][0]부터 채워나가기
		for(int i = 0; i < chasu*chasu; i++) {
			if(direction == RIGHT) { //오른쪽 채우기
				col++;
				if(col == chasu || snail_array[row][col]!=0) {//이동하다 막히면
					row++;
					col--;
					direction = DOWN;
				}
			}else if(direction == DOWN) { //아래쪽 채우기
				row++;
				if(row == chasu || snail_array[row][col]!=0) {
					row--;
					col--;
					direction = LEFT;
				}
			}else if(direction == LEFT) { //왼쪽 채우기
				col--;
				if(col < 0 || snail_array[row][col]!=0) {
					row--;
					col++;
					direction = UP;
				}
			}else if(direction == UP) {//위쪽 채우기
				row--;
				if(snail_array[row][col]!=0) {
					row++;
					col++;
					direction = RIGHT;
				}
			}
			
			snail_array[row][col] = su++;
		}//end for()
	}//end snail()
	
	private void make_snail2() {
		//달팽이 배열 생성
		snail_array = new int[chasu][chasu];
		
		int row = 0;
		int col = -1;
		int su = chasu*chasu;
		
		direction = RIGHT;
		
		//[0][0]부터 채워나가기
		for(int i = 0; i < chasu*chasu; i++) {
			if(direction == RIGHT) { //오른쪽 채우기
				col++;
				if(col == chasu || snail_array[row][col]!=0) {//이동하다 막히면
					row++;
					col--;
					direction = DOWN;
				}
			}else if(direction == DOWN) { //아래쪽 채우기
				row++;
				if(row == chasu || snail_array[row][col]!=0) {
					row--;
					col--;
					direction = LEFT;
				}
			}else if(direction == LEFT) { //왼쪽 채우기
				col--;
				if(col < 0 || snail_array[row][col]!=0) {
					row--;
					col++;
					direction = UP;
				}
			}else if(direction == UP) {//위쪽 채우기
				row--;
				if(snail_array[row][col]!=0) {
					row++;
					col++;
					direction = RIGHT;
				}
			}
			
			snail_array[row][col] = su--;
		}//end for()
	}

	public void display() {
		for(int i = 0; i < chasu; i++) {
			System.out.print("[");
			for(int j = 0; j < chasu; j++) {
				System.out.printf("%4d",snail_array[i][j]);
			}
			System.out.print("]");
			System.out.println();
		}//end for()
	}
}//end Snail

[Main 함수]

package mymain;

import java.util.Scanner;
import myutil.Snail;

public class _11_Question_Snail {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int chasu;
		String yn = "y";
		Snail snail = new Snail();
		
		while(true) {
			System.out.print("차수 : ");
			chasu = scanner.nextInt();
						
			//달팽이 객체 - 차수 전달(setter)
			snail.setChasu(chasu);
			//달팽이 출력
			
			//또?
			System.out.print("또?(y/n) : ");
			yn = scanner.next();
			if(!yn.equalsIgnoreCase("y")) break;
		}//end while
		
		System.out.println("----END----");
		scanner.close();
	}//end main
	
}

■ 사용할 객체

▶ KeyAdaptor

- KeyListener를 구현한 추상클래스이다. 

- getKeyCode() : void    ----  Virtual Code를 확인할 수 있다.

  [참고 : 키보드 정보가 들어오는 방식]
   - 각 회사의 키보드 -> OS/JVM에서 Virtual Key Code로 받음(각 회사 키보드 동일하게 인식)
   - 키보드의 shift+[  ] 예를 들어, 소문자 a를 인식하는 게 아니다. (문자는 모두 대문자로 인식)
   - 말그대로 어떤 키보드를 눌렀는지를 값으로 받는다.

▶ KeyEvent

- VK_xxxxx : Virtual Code Key를 의미하는 상수로, 언더바(_) 다음에 "LEFT","RIGHT","Q","R"등 키보드 키에 대한 상수를 받을 수 있다.

▶ Dimension

- Dimension객체 생성 후, 인스턴스 변수 width/height를 통해 현재 사용하는 컴퓨터의 화면 해상도 얻기 

▶ Toolkit

- Dimension객체를 생성할 때 사용할 클래스다.

- Toolkit : 자원(이미지등) 정보 구하는 객체

- getDefaultToolkit().getScreenSize() : 툴키트 안의 해상도 사이즈를 구하는 메소드이다.

▶ Point

- (x,y)좌표를 입력할 수 있는 객체이다.

 

 

■ 키보드 좌(<-)/우(->)/상/하를 누를 때 윈도우창 이동시키기 (단, 모니터 화면 밖으로 나갈 수 없다.)

package window;

import java.awt.Dimension;
import java.awt.HeadlessException;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;

public class MoveExceptMonitor extends JFrame{
	int screen_w,screen_h; //모니터 화면 해상도 크기
	
	public MoveExceptMonitor() throws HeadlessException {
		super("KeyEvent 연습");
		this.setSize(400,400);
		this.setLocation(200,200);
		this.setVisible(true);
		this.addWindowListener(new WindowAdapter() {

			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
			
		});
		
		//화면 해상도 구하기
		Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
		screen_w = d.width;
		screen_h = d.height;
		
		//키보드초기화
		//키보드 입력시 이벤트를 어떻게 발생시킬 것인지 작성
		init_key_event();
	}
	
	private void init_key_event() {
		KeyAdapter adapter = new KeyAdapter() {

			@Override
			public void keyPressed(KeyEvent e) {
				//눌린 키 정보 얻어보기
				int key = e.getKeyCode();
				
				//현재 윈도우의 위치
				//Point pt = MoveExceptMonitor.this.getLocation();
				Point pt = getLocation();
				
				//현재 객체의 너비/높이
				int sizeWidth = getWidth(); //JDK가 알아서 외부클래스로 인식한다.
				int sizeHeight = getHeight();
				
				if(key==KeyEvent.VK_LEFT) {
					pt.x = pt.x - 10;
					if(pt.x < 0) {
						pt.x = 0;
					}
				}else if(key==KeyEvent.VK_RIGHT) {
					pt.x = pt.x + 10;
					if(pt.x+sizeWidth > screen_w) {
						pt.x = screen_w - sizeWidth;
					}
				}else if(key==KeyEvent.VK_UP) {
					pt.y = pt.y - 10;
					if(pt.y < 0) {
						pt.y = 0;
					}
				}else if(key==KeyEvent.VK_DOWN) {
					pt.y = pt.y + 10;
					if(pt.y+sizeHeight > screen_h) {
						pt.y = screen_h - sizeHeight;
					}
				}
				
				//바뀐 포인트 값으로 윈도우 위치 이동
				setLocation(pt.x,pt.y);
			}
			
		};
		this.addKeyListener(adapter);
	}

	public static void main(String[] args) {
		new MoveExceptMonitor();
	}
}

■ xxxListener/xxxEvent/Action 관계

- 비유 참고 링크 : https://stackoverflow.com/questions/23033439/what-is-the-difference-between-actionlistener-and-actionevent-for-a-button

   [비유] 상점 주인
   - 상점 주인이 가게에 들어와 직원들을 살핀다.
   - 그는 뭔가 문제가 발생한다면 행동을 할 준비를 하고 있다.(ActionListner)
   - 직원A가 일할 시간에 또 사무실에서 잠을 자고 있다.
   - 그는 마음먹은대로 행동을 돌입해야겠다 생각한다.(AcitionEvent)
   - 그는 직원A에게 다음번에 자르겠다 경고한다.(Action)

 

■ xxxListner와 xxxAdapter의 차이점

- XXXListener는 인터페이스다.

- XXXAdapter는 XXXListener를 구현한 추상클래스이며, 메소드들의 구현부에 {  }만 작성되어 있다.

- XXXListener을 상속할 때는 내부 메소드를 모두 구현해야하지만, XXXAdapter를 상속할 때는 쓰고 싶은 메소드만 골라쓰면 되는 장점이 있다.

 

 

 

 

■ ActionListener를 구현하는 방법

 

1. 인스턴스 내부클래스 사용

package window;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class EventTest extends JFrame{
	
	class ButtonListener implements ActionListener{

		@Override
		public void actionPerformed(ActionEvent e) {
			JOptionPane.showMessageDialog(EventTest.this, "Visible");
		}
		
	}

	public EventTest(){
		//윈도우 기본 세팅
		super("EventListenr-인스턴스 내부 클래스");
		setLocation(200,200);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);
		
		//버튼 추가
		JButton jbt = new JButton("Click This");
		this.add(jbt,"North");
		
		//버튼 이벤트 추가
		jbt.addActionListener(new ButtonListener());
		
		setSize(400,400);
	}

	public static void main(String[] args) {
		new EventTest();
	}

}

 

 

>> 실행결과

 

2. 로컬 내부클래스 사용

package window;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class EventTest extends JFrame{

	public EventTest(){
		//윈도우 기본 세팅
		super("EventListenr-로컬 내부 클래스");
		setLocation(200,200);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);
		
		//버튼 추가
		JButton jbt = new JButton("Click This");
		this.add(jbt,"North");
		
		//버튼 이벤트 추가
		class ButtonListener implements ActionListener{

			@Override
			public void actionPerformed(ActionEvent e) {
				JOptionPane.showMessageDialog(EventTest.this, "Visible");
			}
			
		}
		jbt.addActionListener(new ButtonListener());
		
		setSize(400,400);
	}

	public static void main(String[] args) {
		new EventTest();
	}

}

 

3. 익명클래스 사용

package window;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class EventTest extends JFrame{

	public EventTest(){
		//윈도우 기본 세팅
		super("EventListenr-익명 클래스");
		setLocation(200,200);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);
		
		//버튼 추가
		JButton jbt = new JButton("Click This");
		this.add(jbt,"North");
		
		//버튼 이벤트 추가
		ActionListener listener = new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				JOptionPane.showMessageDialog(EventTest.this, "Hello My World");
			}
		};
		jbt.addActionListener(listener); 
		
		setSize(400,400);
	}

	public static void main(String[] args) {
		new EventTest();
	}

}

 

4. 람다식 사용

- (매개변수 -> 구현부)를 한 번에 쓰는 방식 

package window;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class EventTest extends JFrame{

	public EventTest(){
		//윈도우 기본 세팅
		super("EventListenr-익명 클래스");
		setLocation(200,200);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);
		
		//버튼 추가
		JButton jbt = new JButton("Click This");
		this.add(jbt,"North");
		
		//버튼 이벤트 추가
		//jbt.addActionListener(ActionListner i);
		//                      ActionListener i 안에 매개변수 e가 있는 메소드로 가서,
		//                      구현부를 작성하기.
		jbt.addActionListener((e)->{JOptionPane.showMessageDialog(EventTest.this, "Visible");}); 
		
		setSize(400,400);
	}

	public static void main(String[] args) {
		new EventTest();
	}

}

 

 

■ 4가지 방법을 모두 한 번에 볼 수 있는 예제

package mymain;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class _04_Hello_Nation extends JFrame {
	
	//Member로서의 내부클래스 선언
	class ButtonEventObject implements ActionListener{

		@Override
		public void actionPerformed(ActionEvent e) {
			//JOptionPane.showMessageDialog(null, "안녕하세요!!"); //null이면, 모니터의 정중앙 -> 윈도우창에 넣으면 창의 정중앙
			JOptionPane.showMessageDialog(_04_Hello_Nation.this, "안녕하세요!!");
			//내부클래스에서 외부클래스를 호출할 때는 _04_Hello_Nation.this
			//내부클래스에서 내부클래스를 호출할 때는 this
		}
		
	}

	public _04_Hello_Nation() {
		super("각 나라 인사말");
		
		GridLayout gl = new GridLayout(6,1);
		this.setLayout(gl);
		
		JButton jbt_kor = new JButton("한국어 인사말");
		JButton jbt_eng = new JButton("영  어 인사말");
		JButton jbt_jpn = new JButton("일본어 인사말");
		JButton jbt_chn = new JButton("중국어 인사말");
		JButton jbt_fra = new JButton("프랑스 인사말");
		JButton jbt_ger = new JButton("독일어 인사말");
		
		this.add(jbt_kor);
		this.add(jbt_eng);
		this.add(jbt_jpn);
		this.add(jbt_chn);
		this.add(jbt_fra);
		this.add(jbt_ger);
		
		//한국어 인사말
		//jbt_kor 버튼 눌렀을 때 이벤트 등록(JVM에게 등록)
		//이벤트 소트.addXXXListener (처리객체가 갖고 있는 interface)
		ButtonEventObject listener = new ButtonEventObject();
		jbt_kor.addActionListener(listener);
		
		//영어 인사말
		//로컬 내부 클래스(Local Inner Class)
		class EngButtonEventObject implements ActionListener{

			@Override
			public void actionPerformed(ActionEvent e) {
				//System.out.println(e);
				JOptionPane.showMessageDialog(_04_Hello_Nation.this, "Hi Everyone!");
			}
			
		}
		jbt_eng.addActionListener(new EngButtonEventObject());
		
		//일본어 인사말
		//익명 내부 클래스
		ActionListener listener2 = new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				JOptionPane.showMessageDialog(_04_Hello_Nation.this, "곤니치와");				
			}
		};
		jbt_jpn.addActionListener(listener2);
		
		//중국어 인사말
		jbt_chn.addActionListener( new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				JOptionPane.showMessageDialog(_04_Hello_Nation.this, "니하오마");
			}
		} );
		
		//프랑스어 인사말
		//람다식(Lambda) : 함수 또는 객체 축약식 
		jbt_fra.addActionListener(e->JOptionPane.showMessageDialog(_04_Hello_Nation.this, "봉쥬르"));
		
		//독일어 인사말
		jbt_ger.addActionListener((e) -> {JOptionPane.showMessageDialog(_04_Hello_Nation.this, "구덴 탁");});
		
		//람다식 예시
		//int a = 1, b = 2;
		//int n = (a,b) -> {return a + b;};

		//위치             x   y
		super.setLocation(200, 200);

		//크기
		super.setSize(400, 400);

		//보여주기
		this.setVisible(true);

		//종료
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
	}

	public static void main(String[] args) {
		new _04_Hello_Nation();
	}
}

 

 

[참조]

- 국비지원 수업 내용 참조

 공통부분

- 윈도우창이기에 컨테이너는 JFrame을 사용한다.

- 아래의 예제들에서 JFrame의 세팅값(위치/크기/보임상태/종료버튼방식)은 모두 동일하게 할 것이다.

 

■ BorderLayout

- JFrame컨테이너의 디폴트 배치관리자는 BorderLayout이다.

- BorderLayout은 컴포넌트 간격을 지정하지 않을 거면 초기화를 딱히 해줄게 없다.

- 컴포넌트를 넣어줄 때 어느 영역(North/South/West/East/Center)에 위치시킬지 지정해준다.

package window;

import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;

public class BorderLayoutTest extends JFrame{
	
	BorderLayoutTest(){

		//JFrame의 기본 세팅 메소들 
		this.setTitle("BorderLayout Test");
		this.setLocation(200,200);
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		//버튼 컴포넌트를 5개 추가 - add()
		//[레이아웃] 디폴트로 BorderLayout으로 설정되어 있음
		//[1] 먼저 버튼 객체부터 생성한다.
		//    **버튼 생성메소드 JButton("버튼 안에 들어갈 문자열")
		//                               이미지나 아이콘도 넣을 수 있다.
		JButton jbtNorth = new JButton("NORTH");
		JButton jbtSouth = new JButton("SOUTH");
		JButton jbtWest = new JButton("WEST");
		JButton jbtEast = new JButton("EAST");
		JButton jbtCenter = new JButton("CENTER");
		//[2] 버튼을 컨테이너에 넣어둔다. **이때, 버튼이 들어갈 위치를 지정한다.
		this.add(jbtNorth,BorderLayout.NORTH);
		this.add(jbtSouth,"South");
		this.add(jbtWest,BorderLayout.WEST);
		this.add(jbtEast,"East");
		this.add(jbtCenter); //생략시 디폴트 CENTER로 지정
		
		//[유의점] 버튼 컴포넌트들을 먼저 JFrame에 넣어주고 JFrame 사이즈를 잡아줘야 한다.
		//         why? BorderLayout에서는 윈도우창 크기에 따라서 버튼의 너비가 자동 설정되기 때문.
		this.setSize(400,400);
		
		
	
	}

	public static void main(String[] args) {
		new BorderLayoutTest();
	}

}

>> 실행 결과

 

■ FlowLayout

- JFrame컨테이너의 디폴트 배치관리자는 BorderLayout이다.

- Container의 setLayout() 메소드를 사용해서 레이아웃을 FlowLayout으로 변경한다.

  *레이아웃도 객체이기 때문에 레이아웃 객체 생성을 먼저 해줘야한다.

- FlowLayout을 생성할 때 컴포넌트들의 정렬방식과 수평/수직 간격을 초기화해준다.

  *기본적으로 최상단부터 나열시키는데, 정렬방식은 그의 좌(LEADING), 중간(CENTER), 끝(TRAILING) 중 하나를 고를 수 있다.

package window;

import java.awt.FlowLayout;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class FlowLayoutTest extends JFrame{
	
	FlowLayoutTest() {
		//JFrame 기본 세팅
		this.setTitle("FlowLayout Test");
		this.setLocation(400,400);
		this.setVisible(true);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		
		//Container 레이아웃 변경
		//[참고] setLayout()의 매개변수는 LayoutManager 인터페이스다.
		//[생성시] 정렬방식, 수직/수평간격 지정
		this.setLayout(new FlowLayout(FlowLayout.CENTER,10,10));;
		
		//컴포넌트들을 생성해서 넣어준다.
		JLabel label = new JLabel("Select Language");
		this.add(label);
		
		String[] comLang = {"Java","C","C++","PHP","Javascript","python"};
		JComboBox<String> comLangBox = new JComboBox<String>(comLang);
		comLangBox.setSelectedIndex(0);
		this.add(comLangBox);
		
		this.setSize(400,400);
	}
	
	public static void main(String[] args) {
		new FlowLayoutTest();
	}
}

>> 실행결과

 

■ GridLayout

- Container의 setLayout() 메소드를 사용해서 레이아웃을 GridLayout으로 변경한다.

  *이번에도 레이아웃 객체생성을 먼저한다.

- Grid레이아웃을 생성할 때, 행/열 갯수, 수평/수직 간격을 초기화한다.

- Grid는 행을 우선으로 해서 컨포넌트들의 열의 너비를 지정하므로 이점을 유의한다.

package window;

import java.awt.Color;
import java.awt.GridLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class GridTest extends JFrame{
	
	public GridTest() {
		super("GridLayout Test");
		setVisible(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setLocation(200,200);
		
		//Grid로 레이아웃 변경
		GridLayout g = new GridLayout(3,3,10,10);
		this.setLayout(g);
		
		//컴포넌트 생성, 추가
		for(int i = 0; i < 10; i++) {
			JPanel jp1 = new JPanel();
			jp1.add(new JLabel("PANEL"));
			jp1.setSize(30,30);
			Color c = new Color(0xfe9cc3);
			jp1.setBackground(c);
			this.add(jp1);
		}
		
		
		setSize(400,400);
		
	}

	public static void main(String[] args) {
		new GridTest();
	}

}

>> 실행 결과

 

■ CardLayout

- JFrame 윈도우창의 디폴트 BorderLayout배치는 그대로 둔다.

- 윈도우 창 상단에 패널+버튼들로 탭을 만든다. *패널 - FlowLayout

- 윈도우 창 하단에 패널+패널들로 카드를 만든다. *패널 - CardLayout

  *묶어주는 안에 카드를 넣을 때는, 문장열로 카드명을 지정한다.

package window;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class CardTest extends JFrame{

	public CardTest(){
		super("GridLayout Test");
		setVisible(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setLocation(200,200);
		
		//메뉴상단만들기
		JPanel menu = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 20));
		JButton jbt1 = new JButton("< Previous");
		JButton jbt2 = new JButton("CARD");
		jbt2.setBackground(Color.MAGENTA);
		JButton jbt3 = new JButton("Next >");
		menu.add(jbt1);
		menu.add(jbt2);
		menu.add(jbt3);
		this.add(menu,"North");
		
		//카드 만들기
		JPanel cardSet = new JPanel(new CardLayout());
		cardSet.add(new Screen1(),"s1");
		cardSet.add(new Screen2(),"s2");
		cardSet.add(new Screen2(),"s3");
		this.add(cardSet);
		
		
		setSize(400,400);
	}

	public static void main(String[] args) {
		new CardTest();
	}

}

class Screen1 extends JPanel{

	public Screen1(){
		this.setLayout(new BorderLayout());
		Color c = new Color(0xe43e22);
		JLabel label = new JLabel("안녕!",JLabel.CENTER);
		this.setBackground(c);
		this.add(label,"Center");
	}
	
}
 
class Screen2 extends JPanel{
	public Screen2() {
		this.setLayout(new BorderLayout());
		Color c = new Color(0x1ab6a8);
		JLabel label = new JLabel("잘 지냈어?",JLabel.CENTER);
		this.setBackground(c);
		this.add(label,"Center");
	}
}

class Screen3 extends JPanel{
	public Screen3() {
		this.setLayout(new BorderLayout());
		Color c = new Color(0x985396);
		JLabel label = new JLabel("이번주 주말에 뭐해?",JLabel.CENTER);
		this.setBackground(c);
		this.add(label,"Center");
	}
}

>> 실행 결과

 

더보기
class SutdaCard{
	//카드의 숫자.(1~10사이의 정수)
	int num; 
	//광이면 true, 아니면 false
	boolean isKwang;
}

 

 

더보기
package objectprogm1;

public class Q6_2 {

	public static void main(String[] args) {
		SutdaCard card1 = new SutdaCard(3, false);
		SutdaCard card2 = new SutdaCard();
		
		System.out.println(card1.info());
		System.out.println(card2.info());
	}

}

class SutdaCard{
	final static int MIN_NUM = 1;
	final static int MAX_NUM = 10;
	int num; 
	boolean isKwang;
	
	SutdaCard(){
		this(1, true);
	}
	
	SutdaCard(int num, boolean isKwang){
		this.num = num;
		this.isKwang = isKwang;
	}
	
	String info() {
		return num + (isKwang? "K" : "");
		/*
		   아래에서는 String.format() 사용
		if(isKwang) {
			return String.format("%dK",this.num);
		}else {
			return String.format("%d",this.num);
		}
		*/
	}
}

 

 

더보기

class Student{
String name;
int ban;
int no;
int kor;
int eng;
int math;
}

 

더보기
class Student{
	String name;
	int ban;
	int no;
	int kor;
	int eng;
	int math;
	
	int getTotal() {
		return kor+eng+math;
	}
	
	float getAverage() {
		return (int)(getTotal()/3f*10+0.5)/10f;
	}
}

 

 

더보기
package objectprogm1;

public class Q6_5 {

	public static void main(String[] args) {
		Student s = new Student("홍길동",1,1,100,60,76);
		
		System.out.println(s.info());

	}

}

class Student{
	String name;
	int ban;
	int no;
	int kor;
	int eng;
	int math;
	
	Student(){
		this("아무나",0,0,100,100,100);
	}
	
	Student(String name, int ban, int no, int kor, int eng, int math){
		this.name = name;
		this.ban = ban;
		this.no = no;
		this.kor = kor;
		this.eng = eng;
		this.math = math;
	}
	
	String info() {
		return String.format("%s,%d,%d,%d,%d,%d,%d,%.1f",this.name,this.ban,this.no,this.kor,this.eng,this.math,this.getTotal(),this.getAverage());
	}
	
	int getTotal() {
		return kor+eng+math;
	}
	
	float getAverage() {
		return (int)(getTotal()/3f*10+0.5)/10f;
	}
}

 

더보기
package objectprogm1;

public class Q6_6 {
	
	//두 점 (x,y)와 (x1,y1)간의 거리를 구한다.
	static double getDistance(int x, int y, int x1, int y1) {
		double squareDistance = (x1-x)*(x1-x)+(y1-y)*(y1-y);
		return Math.sqrt(squareDistance);
	}

	public static void main(String[] args) {
		System.out.println(getDistance(1,1,2,2));
	}

}

 

더보기
package objectprogm1;

class MyPoint{
	int x;
	int y;
	
	MyPoint(int x, int y){
		this.x = x;
		this.y = y;
	}
	
	double getDistance(int x1, int y1) {
		double squareDistance = (x1-this.x)*(x1-this.x)+(y1-y)*(y1-y);
		return Math.sqrt(squareDistance);
	}
}

public class Q6_7 {
	public static void main(String[] args) {
		MyPoint p = new MyPoint(1,1);
		
		System.out.println(p.getDistance(2,2));
	}
}

 

더보기

- 클래스 변수 : width, height
- 인스턴스 변수 : kind, num
- 지역변수 : k, n, card, args

 

더보기

static 변수 : weapon, armor 
 static 메소드 : weaponUp(), armorUp()
 //이유 : 모든 병사의 공격력과 방어력이 같다 = 모든 객체 공통으로 적용되는 것

 

더보기

[6-10] b, e
 b //초기화를 위한 것
 e //오버로딩 가능

 

더보기

 [6-11] b

 

더보기

[6-12] c, d
 d//이름만 다르고 타입이 갖으면 결국 같은 메소드

 

더보기

[6-13] b, c, d

 

더보기

[6-14] c,e

 

더보기

[6-15] a

 

더보기

[6-16] a, e
 d //지역변수는 자신이 선언된 블럭이나 메소드가 종료되면 소멸되므로 메모리 부담이 적다
 e //인스턴스변수를 설명한 것,, 지역변수는 호출스택에 생성된다.

 

더보기

[6-17] b
 f //열려있는건 다 열려있지만 실행은 f만 하고 있다.

 

더보기

[정답] 라인 A, B, D

[해설] 

- 라인 A : static변수의 초기화에 인스턴스 변수를 사용할 수 없다.

             꼭 사용해야 한다면 객체를 생성해야 한다.

- 라인 B : static메서드에서는 인스턴스 변수를 사용할 수 없다.

- 라인 C : static메서드에서는 인스턴스메서드를 사용할 수 없다.

 

더보기

[6-19] 
 ABC123
 After change:ABC123

 

더보기

예제 답에서는 arr원본 배열을 shuffle해주었는데, 나는 복사한 배열을 shuffle해서 전달해주었다.

shuffle하는 원리는 동일하다.

package objectprogm1;

public class Q6_20 {
	
	static int[] shuffle(int[] arr) {
		
		//매개변수 유효성 검사
		if(arr == null || arr.length == 0) {
			return arr;
		}
		
		//arr을 복사
		int[] sArr = new int[arr.length];
		for(int i = 0; i < arr.length; i++) {
			sArr[i] = arr[i];
		}
		
		//복사본을 shuffle하여 전달
		int tmp;
		int ran;
		for(int i = 0; i < sArr.length; i++) {
			ran = (int)(Math.random()*sArr.length);
			tmp = sArr[i];
			sArr[i] = sArr[ran];
			sArr[ran] = tmp;
		}
		return sArr;
	}
	
	
	public static void main(String[] args) {
		int[] original = {1,2,3,4,5,6,7,8,9};
		System.out.println(java.util.Arrays.toString(original));
		
		int[] result = shuffle(original);
		System.out.println(java.util.Arrays.toString(result));
	}
}

 

더보기
package objectprogm1;

class MyTv{
	
	boolean isPowerOn;
	int channel;
	int volume;
	final int MAX_VOLUME = 100;
	final int MIN_VOLUME = 0;
	final int MAX_CHANNEL = 100;
	final int MIN_CHANNEL = 1;
	
	void turnOnOff() {
		isPowerOn = !isPowerOn;
	}
	
	void volumeUp() {
		this.volume++;
		if(volume > MAX_VOLUME)
			volume = MAX_VOLUME;
	}
	
	void volumeDown() {
		this.volume--;
		if(volume < MIN_VOLUME)
			volume = MIN_VOLUME;
	}
	
	void channelUp() {
		this.channel++;
		if(channel > MAX_CHANNEL)
			channel = MAX_CHANNEL;
	}
	
	void channelDown() {
		this.channel--;
		if(channel < MIN_CHANNEL)
			channel = MIN_CHANNEL;
	}
}//end MyTv

public class Q6_21 {

	public static void main(String[] args) {
		MyTv t = new MyTv();
		
		t.channel = 100;
		t.volume = 0;
		System.out.println("CH:"+t.channel+", VOL:"+ t.volume);
		
		t.channelDown();
		t.volumeDown();
		System.out.println("CH:"+t.channel+", VOL:"+ t.volume);
		
		t.volume = 100;
		t.channelUp();
		t.volumeUp();
		System.out.println("CH:"+t.channel+", VOL:"+ t.volume);
	}
}//end class

 

더보기
static boolean isNumber(String str) {

    //매개변수 유효성 검사
    if(str == null || str.equals("")) {
        return false;
    }

    for(int i = 0; i < str.length(); i++) {
        int ch = str.charAt(i);
        if(!(ch>='0'&&ch<='9')) {
            return false;
        }			
    }
    return true;
}

 

더보기
static int max(int[] arr) {

    if(arr == null || arr.length == 0) {
        return -999999;
    }

    int max_num = arr[0];
    for(int i = 1; i < arr.length; i++) {
        if(arr[i]>max_num) {
            max_num = arr[i];
        }
    }

    return max_num;

    /*
    int max_num = 0;
    for(int i = 0; i < arr.length-1; i++) {
        if(arr[i]>arr[i+1]) {
            max_num = arr[i];
        }else {
            max_num = arr[i+1];
        }
    }
    */	
}

 

더보기
static int abs(int value) {
		
    return value<0? -value : value;
    /*
    if(value<0) {
        return -value;
    }else {
        return value;
    }
    */
}

 

+ Recent posts