Part 1. 자바 API 활용 및 API 만들기
CH4. 인터페이스 기반의 프로그래밍
- 인터페이스 기반의 프로그래밍이란
개념:
인터페이스 기반의 프로그래밍은 객체 지향 프로그래밍(OOP)에서 중요한 개념으로, 인터페이스를 통해 클래스 간의 계약(Contract)을 정의하는 방법입니다. 인터페이스는 메서드 시그니처만을 포함하며, 이를 구현하는 클래스는 해당 메서드의 구체적인 구현을 제공합니다. 이를 통해 구현체의 변경에 영향을 받지 않고, 유연하고 확장 가능한 코드를 작성할 수 있습니다.
예시:
/* - Person 인터페이스를 정의하고, 이를 구현한 Student와 Teacher 클래스를 통해 다형성(polymorphism)을 실현합니다. main 메서드에서 Person 타입의 변수를 사용함으로써 구현체에 의존하지 않고 유연하게 코드를 작성할 수 있습니다. 이 예제에서 Person 인터페이스는 사람의 공통 동작을 정의하고, Student와 Teacher 클래스는 각각 학생과 교사의 구체적인 동작을 구현합니다.
- */
- // 인터페이스 정의
- interface Person {
- void speak();
- void work();
- }
- // Student 클래스는 Person 인터페이스를 구현
- class Student implements Person {
- @Override
- public void speak() {
- System.out.println("I am studying.");
- }
- @Override
- public void work() {
- System.out.println("I am doing my homework.");
- }
- }
- // Teacher 클래스는 Person 인터페이스를 구현
- class Teacher implements Person {
- @Override
- public void speak() {
- System.out.println("I am teaching.");
- }
- @Override
- public void work() {
- System.out.println("I am preparing lessons.");
- }
- }
- // 인터페이스 기반 프로그래밍을 활용한 예제
- public class InterfaceExample {
- public static void main(String[] args) {
- Person student = new Student();
- Person teacher = new Teacher();
- student.speak();
- student.work();
- teacher.speak();
- teacher.work();
- }
- }
- 데이터베이스 연결 Driver란 무엇인가
개념:
데이터베이스 연결 드라이버(Database Connection Driver)는 애플리케이션이 특정 데이터베이스 관리 시스템(DBMS)과 통신할 수 있도록 해주는 소프트웨어 컴포넌트입니다. JDBC(Java Database Connectivity)는 자바에서 데이터베이스에 연결하고 쿼리를 실행할 수 있도록 하는 API로, 데이터베이스 드라이버는 JDBC API와 데이터베이스 사이의 중간 역할을 합니다.
예시:
/* - MySQL 데이터베이스에 연결하기 위해 JDBC 드라이버를 로드하고, DriverManager를 통해 데이터베이스에 연결한 후, SQL 쿼리를 실행하여 결과를 출력합니다. 드라이버는 com.mysql.cj.jdbc.Driver를 사용합니다.
- */
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.sql.Statement;
- public class DatabaseConnectionExample {
- public static void main(String[] args) {
- String url = "jdbc:mysql://localhost:3306/mydatabase";
- String username = "root";
- String password = "password";
- Connection connection = null;
- Statement statement = null;
- ResultSet resultSet = null;
- try {
- // MySQL JDBC 드라이버를 로드
- Class.forName("com.mysql.cj.jdbc.Driver");
- // 데이터베이스에 연결
- connection = DriverManager.getConnection(url, username, password);
- System.out.println("Database connected!");
- // 쿼리 실행을 위한 Statement 객체 생성
- statement = connection.createStatement();
- // SQL 쿼리 실행
- String sql = "SELECT * FROM users";
- resultSet = statement.executeQuery(sql);
- // 결과 처리
- while (resultSet.next()) {
- int id = resultSet.getInt("id");
- String name = resultSet.getString("name");
- String email = resultSet.getString("email");
- System.out.println("ID: " + id + ", Name: " + name + ", Email: " + email);
- }
- } catch (ClassNotFoundException | SQLException e) {
- e.printStackTrace();
- } finally {
- // 리소스 정리
- try {
- if (resultSet != null) resultSet.close();
- if (statement != null) statement.close();
- if (connection != null) connection.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- }
- 인터페이스를 이용하여 데이터베이스 접속
개념:
인터페이스를 사용하여 데이터베이스 접속을 관리하면 코드의 재사용성과 유연성을 높일 수 있습니다. 인터페이스를 통해 데이터베이스 연결과 관련된 동작을 정의하고, 이를 구현하는 클래스를 통해 구체적인 데이터베이스 연결 로직을 제공할 수 있습니다. 이를 통해 다양한 데이터베이스나 연결 방법을 쉽게 교체할 수 있습니다.
예시:
/* - DatabaseConnection 인터페이스를 정의하고, MySQLConnection 클래스에서 이를 구현하여 MySQL 데이터베이스에 연결하고 연결을 종료하는 로직을 작성했습니다. 이를 통해 다른 데이터베이스 연결 방법을 쉽게 교체할 수 있습니다. 예를 들어, PostgreSQL 데이터베이스에 연결하려면 PostgreSQLConnection이라는 클래스를 추가로 구현하면 됩니다.
- */
- // DatabaseConnection 인터페이스 정의
- interface DatabaseConnection {
- Connection connect() throws SQLException;
- void disconnect(Connection connection);
- }
- // MySQLConnection 클래스는 DatabaseConnection 인터페이스를 구현
- class MySQLConnection implements DatabaseConnection {
- private String url;
- private String username;
- private String password;
- public MySQLConnection(String url, String username, String password) {
- this.url = url;
- this.username = username;
- this.password = password;
- }
- @Override
- public Connection connect() throws SQLException {
- // MySQL JDBC 드라이버를 로드
- try {
- Class.forName("com.mysql.cj.jdbc.Driver");
- } catch (ClassNotFoundException e) {
- throw new SQLException("Unable to load MySQL Driver", e);
- }
- // 데이터베이스에 연결
- return DriverManager.getConnection(url, username, password);
- }
- @Override
- public void disconnect(Connection connection) {
- if (connection != null) {
- try {
- connection.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- }
- // 인터페이스 기반으로 데이터베이스 접속을 관리하는 예제
- public class InterfaceDatabaseExample {
- public static void main(String[] args) {
- DatabaseConnection dbConnection = new MySQLConnection(
- "jdbc:mysql://localhost:3306/mydatabase", "root", "password");
- Connection connection = null;
- try {
- // 데이터베이스에 연결
- connection = dbConnection.connect();
- System.out.println("Database connected!");
- // Statement 객체 생성 및 SQL 쿼리 실행
- Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("SELECT * FROM users");
- // 결과 처리
- while (resultSet.next()) {
- int id = resultSet.getInt("id");
- String name = resultSet.getString("name");
- String email = resultSet.getString("email");
- System.out.println("ID: " + id + ", Name: " + name + ", Email: " + email);
- }
- resultSet.close();
- statement.close();
- } catch (SQLException e) {
- e.printStackTrace();
- } finally {
- // 데이터베이스 연결 종료
- dbConnection.disconnect(connection);
- }
- }
- }
Part 2. Collection Framework API 이해 및 활용
CH1. 모아, 모아 컬랙션(Collection) API
- Wrapper 클래스란
개념:
Wrapper 클래스는 자바의 기본 자료형을 객체로 다룰 수 있도록 해주는 클래스입니다. 기본 자료형(int, float, double 등)에는 객체가 아니기 때문에 메서드를 사용할 수 없지만, Wrapper 클래스를 사용하면 이러한 기본 자료형을 객체로 변환할 수 있습니다. 주요 Wrapper 클래스에는 Integer, Float, Double, Boolean 등이 있습니다.
예시:
/* - int 타입을 Integer 객체로 변환하고, 다시 int로 변환하는 예제입니다.
- */
- public class WrapperExample {
- public static void main(String[] args) {
- // int를 Integer로 변환 (Boxing)
- int primitiveInt = 5;
- Integer wrapperInt = Integer.valueOf(primitiveInt);
- // Integer를 다시 int로 변환 (Unboxing)
- int unboxedInt = wrapperInt.intValue();
- System.out.println("Primitive int: " + primitiveInt);
- System.out.println("Wrapper Integer: " + wrapperInt);
- System.out.println("Unboxed int: " + unboxedInt);
- }
- }
- 숫자와 문자열의 상호 변환
개념:
숫자와 문자열의 상호 변환은 종종 필요한 작업입니다. 숫자를 문자열로 변환하거나 문자열을 숫자로 변환할 때 Wrapper 클래스의 메서드를 사용합니다. 예를 들어, Integer 클래스의 parseInt 메서드를 사용하면 문자열을 정수로 변환할 수 있습니다.
예시:
/* - 문자열을 정수로 변환하고, 정수를 문자열로 변환하는 예제입니다.
- */
- public class StringNumberConversion {
- public static void main(String[] args) {
- // 문자열을 숫자로 변환
- String numberStr = "123";
- int number = Integer.parseInt(numberStr);
- System.out.println("String to int: " + number);
- // 숫자를 문자열로 변환
- int anotherNumber = 456;
- String anotherNumberStr = Integer.toString(anotherNumber);
- System.out.println("Int to string: " + anotherNumberStr);
- }
- }
- Collection Framewok API란
개념:
자바 컬렉션 프레임워크는 데이터를 저장하고 조작하는데 사용되는 클래스와 인터페이스의 집합입니다. 주요 인터페이스로는 List, Set, Map 등이 있으며, 이들을 구현한 여러 클래스가 있습니다. 컬렉션 프레임워크는 데이터 구조를 표준화하여 다양한 데이터 구조를 편리하게 사용할 수 있도록 합니다.
예시:
/* - ArrayList와 HashSet, HashMap을 사용하는 간단한 예제입니다.
- */
- import java.util.*;
- public class CollectionFrameworkExample {
- public static void main(String[] args) {
- // List 예제 (ArrayList)
- List<String> list = new ArrayList<>();
- list.add("Apple");
- list.add("Banana");
- list.add("Apple"); // 중복 허용
- System.out.println("List: " + list);
- // Set 예제 (HashSet)
- Set<String> set = new HashSet<>();
- set.add("Apple");
- set.add("Banana");
- set.add("Apple"); // 중복 불허
- System.out.println("Set: " + set);
- // Map 예제 (HashMap)
- Map<String, Integer> map = new HashMap<>();
- map.put("Apple", 1);
- map.put("Banana", 2);
- map.put("Apple", 3); // 키 중복 시 마지막 값으로 덮어씀
- System.out.println("Map: " + map);
- }
- }
- 순서가 있고 중복 가능한 List API
개념:
List 인터페이스는 순서가 있는 컬렉션을 나타내며, 요소의 중복을 허용합니다. 주요 구현 클래스로는 ArrayList, LinkedList 등이 있습니다. List는 인덱스를 사용하여 요소에 접근할 수 있습니다.
예시:
/* - ArrayList를 사용하는 예제입니다.
- */
- import java.util.*;
- public class ListExample {
- public static void main(String[] args) {
- // ArrayList 생성
- List<String> list = new ArrayList<>();
- list.add("Apple");
- list.add("Banana");
- list.add("Apple"); // 중복 허용
- // 요소 접근
- System.out.println("First element: " + list.get(0));
- // 요소 제거
- list.remove("Banana");
- // 반복문을 사용한 요소 출력
- for (String fruit : list) {
- System.out.println(fruit);
- }
- }
- }
- 순서가 없고 중복 불가능한 Set API
개념:
Set 인터페이스는 순서가 없고 중복을 허용하지 않는 컬렉션을 나타냅니다. 주요 구현 클래스로는 HashSet, LinkedHashSet, TreeSet 등이 있습니다. Set은 고유한 요소들로만 구성됩니다.
예시:
/* - HashSet을 사용하는 예제입니다.
- */
- import java.util.*;
- public class SetExample {
- public static void main(String[] args) {
- // HashSet 생성
- Set<String> set = new HashSet<>();
- set.add("Apple");
- set.add("Banana");
- set.add("Apple"); // 중복 불허
- // 요소 존재 여부 확인
- System.out.println("Contains Apple: " + set.contains("Apple"));
- // 요소 제거
- set.remove("Banana");
- // 반복문을 사용한 요소 출력
- for (String fruit : set) {
- System.out.println(fruit);
- }
- }
- }
- Key-Value로 관리하는 Map API
개념:
Map 인터페이스는 키-값 쌍을 저장하는 컬렉션을 나타냅니다. 키는 중복을 허용하지 않지만, 값은 중복을 허용할 수 있습니다. 주요 구현 클래스로는 HashMap, LinkedHashMap, TreeMap 등이 있습니다. Map은 키를 사용하여 값을 빠르게 검색할 수 있습니다.
예시:
/* - HashMap을 사용하는 예제입니다.
- */
- import java.util.*;
- public class MapExample {
- public static void main(String[] args) {
- // HashMap 생성
- Map<String, Integer> map = new HashMap<>();
- map.put("Apple", 1);
- map.put("Banana", 2);
- map.put("Apple", 3); // 키 중복 시 마지막 값으로 덮어씀
- // 값 접근
- System.out.println("Value for Apple: " + map.get("Apple"));
- // 키-값 쌍 제거
- map.remove("Banana");
- // 반복문을 사용한 키-값 쌍 출력
- for (Map.Entry<String, Integer> entry : map.entrySet()) {
- System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
- }
- }
- }
CH2. 자바 제네릭(Generic) 이란
- 왜 제네릭을 사용해야 하는가?
개념:
제네릭(Generic)은 자바에서 클래스나 메서드에서 사용할 데이터 타입을 파라미터화할 수 있게 해주는 기능입니다. 제네릭을 사용하면 코드의 재사용성을 높이고, 컴파일 시 타입 안전성을 보장하며, 타입 캐스팅을 줄일 수 있습니다. 이를 통해 코드의 가독성과 유지보수성을 향상시킬 수 있습니다.
예시:
/* - 제네릭을 사용하지 않은 경우와 제네릭을 사용한 경우의 비교 예제입니다.
- 제네릭을 사용하지 않으면 컴파일 시 타입 체크가 되지 않아 런타임 오류가 발생할 수 있습니다. 제네릭을 사용하면 컴파일 시점에서 타입을 체크하여 타입 안전성을 보장합니다.
- */
- import java.util.ArrayList;
- public class GenericExample {
- public static void main(String[] args) {
- // 제네릭을 사용하지 않는 경우
- ArrayList list = new ArrayList();
- list.add("Hello");
- list.add(123); // 컴파일러는 문제를 인식하지 못함
- // 값을 가져올 때마다 타입 캐스팅 필요
- String str = (String) list.get(0);
- int num = (int) list.get(1);
- // 제네릭을 사용하는 경우
- ArrayList<String> genericList = new ArrayList<>();
- genericList.add("Hello");
- // genericList.add(123); // 컴파일러가 타입 체크를 통해 오류를 감지
- // 타입 캐스팅 불필요
- String genericStr = genericList.get(0);
- }
- }
- 자바 제네릭 타입이란
개념:
자바 제네릭 타입은 클래스나 메서드에서 사용할 수 있는 파라미터화된 타입입니다. 이를 통해 클래스나 메서드가 여러 타입을 처리할 수 있게 합니다. 제네릭 타입은 타입 매개변수로 지정되며, 객체 생성 시 구체적인 타입을 지정합니다.
예시:
/* - 제네릭 클래스를 정의하고 사용하는 예제입니다.
- Box<T> 클래스는 제네릭 클래스로, T 타입 매개변수를 사용하여 다양한 타입의 값을 저장할 수 있습니다. stringBox는 문자열을 저장하고, intBox는 정수를 저장합니다.
- */
- // 제네릭 클래스 정의
- class Box<T> {
- private T value;
- public void set(T value) {
- this.value = value;
- }
- public T get() {
- return value;
- }
- }
- // 제네릭 클래스를 사용하는 예제
- public class GenericTypeExample {
- public static void main(String[] args) {
- // 문자열을 저장하는 Box
- Box<String> stringBox = new Box<>();
- stringBox.set("Hello");
- String str = stringBox.get();
- System.out.println("String value: " + str);
- // 정수를 저장하는 Box
- Box<Integer> intBox = new Box<>();
- intBox.set(123);
- int num = intBox.get();
- System.out.println("Integer value: " + num);
- }
- }
- 제네릭 멀티 타입 파라미터
개념:
제네릭 멀티 타입 파라미터는 클래스나 메서드에서 두 개 이상의 타입 파라미터를 사용할 수 있게 해주는 기능입니다. 이를 통해 서로 다른 타입의 객체를 처리하는 코드를 작성할 수 있습니다.
예시:
/* - 두 개의 제네릭 타입 파라미터를 사용하는 클래스를 정의하고 사용하는 예제입니다.
- Pair<K, V> 클래스는 두 개의 제네릭 타입 파라미터를 사용하여 키와 값을 저장할 수 있습니다. pair 객체는 문자열과 정수를 저장하고, anotherPair 객체는 정수와 문자열을 저장합니다.
- */
- // 두 개의 제네릭 타입 파라미터를 가진 클래스 정의
- class Pair<K, V> {
- private K key;
- private V value;
- public Pair(K key, V value) {
- this.key = key;
- this.value = value;
- }
- public K getKey() {
- return key;
- }
- public V getValue() {
- return value;
- }
- }
- // 제네릭 멀티 타입 파라미터를 사용하는 예제
- public class GenericMultiTypeExample {
- public static void main(String[] args) {
- // 문자열과 정수를 저장하는 Pair
- Pair<String, Integer> pair = new Pair<>("Age", 30);
- System.out.println("Key: " + pair.getKey() + ", Value: " + pair.getValue());
- // 정수와 문자열을 저장하는 Pair
- Pair<Integer, String> anotherPair = new Pair<>(1, "One");
- System.out.println("Key: " + anotherPair.getKey() + ", Value: " + anotherPair.getValue());
- }
- }
- 제네릭 제한된 타입 파라미터
개념:
제네릭 타입 파라미터는 특정 타입의 하위 클래스나 특정 인터페이스를 구현한 클래스만 사용할 수 있도록 제한할 수 있습니다. 이를 통해 제네릭 타입의 범위를 좁히고, 타입 안전성을 더욱 강화할 수 있습니다. 이러한 제한된 타입 파라미터는 extends 키워드를 사용하여 지정합니다.
예시:
/* - 제한된 타입 파라미터를 사용하는 제네릭 클래스의 예제입니다.
- NumericBox<T> 클래스는 Number 클래스나 그 하위 클래스만 타입 파라미터로 사용할 수 있습니다. intBox 객체는 Integer 값을 저장하고, doubleBox 객체는 Double 값을 저장합니다. String 타입은 Number의 하위 클래스가 아니므로 사용할 수 없습니다.
- */
- // Number 클래스나 그 하위 클래스만 사용할 수 있는 제네릭 클래스 정의
- class NumericBox<T extends Number> {
- private T number;
- public void set(T number) {
- this.number = number;
- }
- public T get() {
- return number;
- }
- public double doubleValue() {
- return number.doubleValue();
- }
- }
- // 제한된 타입 파라미터를 사용하는 예제
- public class GenericBoundedTypeExample {
- public static void main(String[] args) {
- // Integer를 저장하는 NumericBox
- NumericBox<Integer> intBox = new NumericBox<>();
- intBox.set(123);
- System.out.println("Integer value: " + intBox.get());
- System.out.println("Double value: " + intBox.doubleValue());
- // Double을 저장하는 NumericBox
- NumericBox<Double> doubleBox = new NumericBox<>();
- doubleBox.set(45.67);
- System.out.println("Double value: " + doubleBox.get());
- System.out.println("Double value: " + doubleBox.doubleValue());
- // String은 Number의 하위 클래스가 아니므로 사용할 수 없음
- // NumericBox<String> strBox = new NumericBox<>(); // 컴파일 오류
- }
- }
'Backend > Backend 관련 학습 내용' 카테고리의 다른 글
DB 데이터베이스1 (0) | 2024.11.29 |
---|---|
Collection Framework API 이해 및 활용 & 람다와 스트림 API 활용 (0) | 2024.11.29 |
기존 채팅 시스템에서의 WebSocket(웹소켓) 프로토콜의 STOMP 보안 문제점과 인증 레이어 설계 (0) | 2024.11.29 |
[BackEnd] CI/CD Jenkins (0) | 2024.04.15 |
다채널 CCTV 사람 객체 이상행동 감지 및 추적 (1) | 2024.03.23 |