2024.03.04
*StringBuffer
-스트링 클래스와 달리 스트링버퍼는 수정해도 새로운 문자열이 만들어지지 않음
-> 수정을 많이 해야 하는 경우에는 스트링보다 스트링버퍼 사용
-sb.insert(index, 문자열) : 지정한 인덱스에 문자 삽입
-sb.append(문자열) : 문자 뒤에 문자열 삽입
-sb.replace(시작 인덱스, 끝 인덱스, 문자열) : 시작 인덱스부터 끝 인덱스 전까지 문자열 대체
-sb.deleteCharAt(인덱스) : 지정한 인덱스의 문자를 삭제
- sb.delete(시작 인덱스, 끝 인덱스) : 시작 인덱스부터 끝 인덱스 전까지 문자열 삭제
-StringBuffer를 String으로 변환할 때에는 toString() 메서드 사용
*Wrapper 클래스
: 기본자료형을 객체 형태로 저장
*Wrapper 클래스 생성 방법
char c = 'A';
Character wrap_c = c; // 기본 자료형 데이터 -> 참조 자료형 데이터 (직접 대입)
-생성자를 만들지 않고 String 문자열 암시적 생성하듯이 생성.
-자동적으로 기본자료형에서 참조자료형이 되는걸 auto boxing이라고 함 (캐스팅이라는 말 쓰지 x)
-값을 끄집어낼때도 따로 메서드 사용하지 않고 참조변수를 명시 (auto unboxing)
// auto boxing/unboxing
Integer obj3 = 12;
Integer obj4 = 20;
Integer result2 = obj3 + obj4; // 바로 연산 가능
*java.lang.Math
-Java.lang 패키지는 가장 기본적인 클래스들이 모여있기 때문에 따로 import 하지 않아도 됨
-Math.abs(a) : 절대값
-Math.ceil(a) : 올림
-Math.floor(a) : 내림
-Math.round(a) : 반올림
-Math.max(a, b) : 최대값
-Math.min(a, b) : 최소값
-Math.random() : 0 ~ 1미만의 실수인 무작위 난수 생성
-0~3 까지의 값 중 랜덤한 정수를 얻고싶다면 위 메서드로 얻은 난수에 정수의 개수(4)를 곱해주고 (int)로 형변환
-1~4의 값을 얻고싶다면 +1을 해주면 됨
package kr.s20.object.lang;
import java.util.Random;
public class MathMain02 {
public static void main(String[] args) {
String[] gift = {"스마트폰", "TV", "냉장고", "꽝"};
// 0 1 2 3
//난수 발생 : 0 ~ 1미만의 실수
double ran = Math.random();
System.out.println("발생한 난수 : " + ran);
int index = (int) (ran*4); //0~3
System.out.println("정수로 변환한 난수: " + index);
System.out.println("오늘의 선물 : " + gift[index]);
System.out.println("---------------------");
String[] luck = {"귀인을 만남", "해외여행", "로또 당첨", "피곤한 하루"};
Random r1 = new Random();
// 0부터 인자로 전달된 값의 전까지의 범위로 난수 발생 0 ~ 3
index = r1.nextInt(4);
System.out.println("발생한 난수 : " + index);
System.out.println("오늘의 운세 : " + luck[index]);
}
}
*java.util.Random
Random 클래스로 난수를 얻을 수도 있음
-nextInt(), nextBoolean(), nextFloat() 등의 메서드를 통해 다양한 자료형의 랜덤 값을 얻을 때 유용
*Date 클래스
-현재 날짜/시간 구하기
Date now = new Date();
System.out.println(now.toString());
-Date 클래스의 메서드들은 거의 다 deprecated되어 Calendar 클래스를 사용하는 것을 권장
*java.text.SimpleDateFormat
-DateFormat 클래스를 상속받아 날짜를 좀 더 예쁜 형태로 표현하게 해주는 클래스
-쉽게 한글 포맷으로 쉽게 사용 가능(Locale.KOREA 인자 추가)
SimpleDateFormat sf = new SimpleDateFormat("yyyy년MM월dd일 (E) a hh:mm:ss", Locale.KOREA);
String today = sf.format(now);
System.out.println(today); // 2024년03월04일 (월) 오후 10:30:40

-API: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/text/SimpleDateFormat.html
*java.util.Calendar
-현재 날짜/시간 구하기
Calendar today = Calendar.getInstance();
// 여기서 원하는 값을 상수로 받아와서 사용해야함
int year = today.get(Calendar.YEAR); //연도
int month = today.get(Calendar.MONTH) + 1; //월 (MONTH 상수는 0~11을 반환함)
int date = today.get(Calendar.DATE); //날짜
System.out.printf("%d년 %d월 %d일 ", year, month, date);
int day = today.get(Calendar.DAY_OF_WEEK); //요일 (DAY_OF_WEEK 상수는 1~7을 반환)
String days[] = {"일", "월", "화", "수", "목", "금", "토"};
System.out.print(days[day-1]+"요일 ");
int amPm = today.get(Calendar.AM_PM); //오전 0, 오후 1
String str = amPm == Calendar.AM ? "오전" : "오후";
int hour = today.get(Calendar.HOUR);
int min = today.get(Calendar.MINUTE);
int sec = today.get(Calendar.SECOND);
System.out.printf("%s %d시 %d분 %02d초", str, hour, min, sec);
※MONTH 상수는 0~11 을 반환하기 때문에 실제 월을 구하려면 +1 해줘야함
※DAY_OF_WEEK 상수는 일요일부터 1~7을 반환
-Calendar.getInctance() 메서드를 통해 인스턴스를 생성하고 get() 메서드를 통해 원하는 값을 상수로 받아와 사용
-Calendar 인스턴스에 희망날짜 세팅하기
Calendar cal = Calendar.getInstance();
cal.set(int year, int month, int date);
-특정 달의 마지막 날짜 구하기
int lastOfDate = cal.getActualMaximum(Calendar.DATE);
*java.util.StringTokenizer
-String 클래스의 split() 메서드와 비슷하게 구분자를 이용하여 문자열을 쪼개어주는 기능
String source = "100,200,300,400";
StringTokenizer st = new StringTokenizer(source, ",");
// 구분자를 통해서 잘려진 문자열이 있는지 검증
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
[StringTokenizer와 split() 비교]
StringTokenizer | split() |
java.util에 포함된 클래스다. | String 클래스에 속해있는 메소드 |
문자로 문자열을 구분 | 정규표현식으로 구분 |
오직 단 한 문자의 구분자만 사용 가능 | 정규표현식을 이용하면 두 문자 이상의 구분자도 사용 가능 |
복수의 구분자 지정 가능 | 하나의 구분자만 지정 가능 |
결과값이 문자열 String | 결과값이 문자열 배열 String[] |
빈 문자열을 토큰으로 인식하지 않음 | 빈 문자열을 토큰으로 인식함 |
→ 데이터 양이 적을 때 배열에 담아 반환하는 split는 데이터를 바로 잘라서 반환해주는 StringTokenizer보다 느릴 수 있다.
<실습>
kr.s20.object.lang.StringMain05
package kr.s20.object.lang;
public class StringMain05 {
public static void main(String[] args) {
/*
* [실습]
* 아래 문자열의 대문자->소문자, 소문자->대문자
*/
// 아스키코드와 String 클래스의 메서드 이용한 방법
String str = "abcMDye-4W?EWzz";
String result = "";
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (c >= 'A' && c <= 'Z') {
result += String.valueOf(c).toLowerCase();
} else if (c >= 'a' && c <= 'z') {
result += String.valueOf(c).toUpperCase();
} else {
result += c;
}
}
System.out.println(result);
System.out.println("--------------------");
// 다른 방법: Character wrapper class 이용
String result2 = "";
for (char c : str.toCharArray()) {
if (Character.isUpperCase(c)) { // 대문자이면 true 반환
result2 += Character.toLowerCase(c);
} else if (Character.isLowerCase(c)) { // 소문자이면 true 반환
result2 += Character.toUpperCase(c);
} else {
result2 += c;
}
}
System.out.println(result2);
System.out.println("--------------------");
// 다른 방법: 아스키 코드만 이용
String result3 = "";
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (c >= 'A' && c <= 'Z') {
result3 += (char)(c + 32); // char로 형변환하지 않으면 아스키코드 형태로 표현됨
} else if (c >= 'a' && c <= 'z') {
result3 += (char)(c - 32);
} else {
result3 += c;
}
}
System.out.println(result3);
System.out.println("--------------------");
}
}
-기본 자료형을 wrapper class로 묶으면 다양한 메서드를 이용할 수 있음
*추상클래스
: 일반클래스와 달리 미완성되어 있는 클래스
-일반적으로 한 개 이상의 추상메서드를 가짐
-객체 생성이 불가능하고 상속관계를 맺은 자식 클래스에서 구현해야 사용이 가능
*추상메서드
: 선언부만 있고 구현부가 없는 메서드
public abstract void make();
-어떤 클래스에서 자식클래스에서 꼭 의무적으로 구현해야 할 메서드가 있는 경우 추상클래스를 만듦
-> 의무를 부여
-추상클래스가 추상클래스를 상속하면 추상메서드 구현의 의무를 지지 않음
(어차피 추상클래스라서 메모리에 올라갈 수 없기 때문에)
2024.03.05
*인터페이스
-클래스가 멤버필드(변수,상수)와 실행 가능한 메서드를 구성요소로 한다면 인터페이스는 상수와 추상메서드를 구성요소로 함
-추상메서드는 일반클래스에 구현되어야만 사용이 가능
-인터페이스를 이용하면 정의해야 하는 메소드(프로그램기능)을 표준화하고 강제할 수 있음
*인터페이스의 규칙
1) 모든 멤버 변수는 public static final 이어야 하며, 이를 생략할 수 있다.
2) 모든 메서드는 public abstract 이어야 하며, 이를 생략할 수 있다.(단, static메서드와 default 메서드는 JDK1.8부터 예외)
-인터페이스 타입을 매개변수로 받는다는 것
= 메서드 호출 시 해당 인터페이스를 구현한 클래스의 인스턴스를 매개변수로 제공해야 한다는 의미
-리턴 타입이 인터페이스 타입이라는 것
= 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 의미
-인터페이스는 인터페이스만 상속받을 수 있으며 다중상속, 다중구현 가능
-상속과 구현을 동시에 하는 것도 가능
// 다중상속
interface Inter3 extends Inter1,Inter2{
public int getData();
}
// 다중구현
public class InterfaceMain05 implements Inter3,Inter4{
@Override
public int getA() {
return 10;
}
@Override
public int getB() {
return 20;
}
@Override
public int getData() {
return 30;
}
@Override
public String getMsg() {
return "서울";
}
public static void main(String[] args) {
InterfaceMain05 it = new InterfaceMain05();
System.out.println(it.getA());
System.out.println(it.getB());
System.out.println(it.getData());
System.out.println(it.getMsg());
}
}
*Enum
-클래스처럼 보이게 하는 문자열 상수
-서로 관련있는 상수들끼리 모아 상수들을 대표할 수 있는 이름으로 타입을 정의하는 것
-Enum 클래스 형을 기반으로 한 클래스형 선언
-> enum의 핵심: 상수를 단순히 정수로 치부하지말고 객체 지향적으로 객체화해서 관리하자는 취지
*java.lang.Enum 객체의 메서드
메소드 | 설명 | 리턴 타입 |
name() | 열거 객체의 문자열을 리턴 | String |
ordinal() | 열거 객체의 순번(0부터 시작)을 리턴 | int |
compareTo() | 열거 객체를 비교해서 순번 차이를 리턴 | int |
valueOf(String name) | 문자열을 입력받아서 일치하는 열거 객체를 리턴 | enum |
values() | 모든 열거 객체들을 배열로 리턴 | enum[] |
-Enum 클래스도 Object 클래스를 상속함
(출처: https://inpa.tistory.com/entry/JAVA-☕-열거형Enum-타입-문법-활용-정리)
*내부클래스
-특정 클래스 내에 또 다른 클래스가 정의되는 것
종류 | 설명 |
Member | 멤버 변수나 멤버 메서드들과 같이 클래스가 정의된 경우에 사용한다. |
Local | 특정한 메서드 내에 클래스가 정의된 경우에 사용 |
Static | static 변수(클래스 변수)와 같이 클래스가 static으로 선언된 경우에 사용 |
Anonymous | 참조할 수 있는 이름이 없는 경우에 사용 |
*멤버 내부클래스
class Outer {
// Outer의 멤버 변수
int x= 100;
// 내부 클래스 (멤버 내부클래스)
class Inner {
// Inner의 멤버 변수
int y = 200;
}
}
public class MemberMain01 {
public static void main(String[] args) {
Outer ot = new Outer();
// Outer의 내부클래스인 Inner 클래스를 객체 생성
Outer.Inner oi = ot.new Inner();
}
}
-멤버 내부클래스의 객체를 생성할 때 외부클래스 객체의 참조변수를 참조해주어야 함
-멤버 내부클래스에서는 외부클래스 내의 다른 멤버 변수에 접근할 수 있음
*로컬 내부클래스
-로컬 내부클래스에서 외부 클래스의 멤버 변수에는 자유롭게 접근 가능
-로컬 내부클래스가 포함된 메서드의 지역 변수를 호출할 때 자동으로 상수화가 진행되어 데이터를 변경할 수 없음
(값을 가져와서 쓸 수는 있지만 변경 불가)
-그 이유는 메서드가 수행을 마쳐서 지역변수가 소멸된 시점에도, 로컬 내부클래스의 인스턴스가 소멸된 지역변수를 참조하려는 경우가 발생할 수 있기 때문
public class LocalMain02 {
// 멤버 변수
int a = 100;
// 멤버 메서드
public void innerTest() {
int b = 500; //지역변수
// 로컬 내부클래스
class Inner {
public void getData() {
//멤버 변수 호출
System.out.println("변경 전 : " + a);
a = 200;
System.out.println("변경 후 : " + a);
System.out.println("-------------------");
//지역 변수 호출
System.out.println("지역 변수 변경 전 : " + b);
// 로컬 내부클래스가 포함된 메서드의 지역 변수를 호출할 때
// 자동으로 상수화가 진행되어 데이터를 변경할 수 없음
// b = 1000;
}
}
// 내부클래스 객체 생성
Inner i = new Inner();
i.getData();
}
*static 내부클래스 (멤버 내부클래스의 변형)
(일반 클래스에는 스태틱을 붙일 수 없음)
-외부클래스의 객체를 생성하지 않고 내부클래스에 접근/호출
public class StaticMain {
// static 내부클래스
public static class Inner {
// 인스턴스 변수
int iv = 100;
// static 변수
static int cv = 200;
// static 메서드
public static void make() {
System.out.println("하하하");
}
}
public static void main(String[] args) {
// static 내부클래스 객체 생성
Inner i = new Inner();
// 인스턴스 변수 호출
System.out.println(i.iv);
// static 변수 호출
System.out.println(Inner.cv);
// static 메서드 호출
Inner.make();
}
}
*Anonymous 내부클래스
-자기 이름을 사용하지 않고 부모 이름을 빌려다 쓰는 클래스 (따로 부모클래스가 없으면 최고조상인 Object를 상속받을 수도 있음)
-생성자 뒤에 중괄호가 있으면 100% 익명 내부클래스가 생성된 것
-내부클래스를 정의하는 부분과 생성하는 부분을 합친 것
-> 생성자 뒤에 있는 중괄호는 클래스 정의부 & 앞부분은 객체 생성 부분
class Inner7 {
public void disp() {
System.out.println("부모클래스의 disp");
}
}
public class AnonymousMain {
public void make() {
// 익명 내부클래스
// Inner7 클래스가 상속된 이름 없는 클래스를 객체 생성
Inner7 i = new Inner7() { //클래스 정의부
@Override
public void disp() {
System.out.println("익명 내부클래스의 disp");
}
};
i.disp();
}
*java.util.Arrays 클래스
-Arrays.sort(a) : 배열 오름차순 정렬
*예외처리
구분 | 설명 |
예외(Exception) | 가벼운 오류이며 프로그램적으로 처리 |
오류(Error) | 치명적인 오류이며 JVM에 의존하여 처리 |
-예외는 발생할 것을 미리 예측 가능 (불안정하게 프로그램이 종료되는 것을 방지 가능)
-오류는 예측이 불가능하여 발생하면 프로그램이 중단됨
-> 프로그래머가 집중해야할 것은 예외처리 (예외가 발생하더라도 프로그램이 안정적으로 동작할 수 있도록 설계)
-예외가 발생하면 예외 발생 지점에서 프로그램이 강제로 종료됨
-예외가 발생하면 예외 정보를 담고 있는 예외 객체가 생성되고 예외 문구가 콘솔에 출력됨
(e.g. java.lang.ArrayIndexOutOfBoundsException)
*try-catch
-우리가 원하는 정보를 출력한 다음 프로그램을 안정적으로 종료할 수 있게 도와줌
public class ExceptionMain03 {
public static void main(String[] args) {
//예외처리
try {
System.out.println(args[0]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("입력한 데이터가 없습니다.");
}
System.out.println("프로그램 종료");
}
}
-다중 catch 블럭
public class ExceptionMain03 {
public static void main(String[] args) {
int var = 50;
//예외처리
//다중 catch문
//예외가 발생하면 예외객체가 전달되는 catch블럭으로 이동해서 수행문을 실행함
try {
int data = Integer.parseInt(args[0]); //String -> int 변환
System.out.println(var/data);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("입력한 데이터가 없습니다.");
} catch (NumberFormatException e) {
System.out.println("숫자가 아닙니다.");
}
System.out.println("프로그램 종료");
}
}
2024.03.06
-다중 catch문을 사용할 때 Exception과 하위 예외 클래스를 동시에 명시할 때
하위 예외 클래스를 먼저 명시하고 가장 뒤에 Exception을 명시해야 동작상의 문제가 발생하지 않음
*멀티 catch
-하나의 catch 블럭에서 여러 개의 예외를 처리할 수 있도록 예상되는 예외클래스를 여러 개 명시하는 방식
try {
int value1 = Integer.parseInt(args[0]);
int value2 = Integer.parseInt(args[1]);
int result = value1 + value2;
System.out.println(value1 + "+" + value2 + "=" + result);
} catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
System.out.println("실행 매개값의 수가 부족하거나 숫자를 변환할 수 없습니다.");
} catch (Exception e) {
System.out.println("알 수 없는 예외 발생");
}
*finally
-예외가 발생하든 발행하지 않든 무조건 수행하는 부분
-Database처리나 File처리를 한다면 꼭 필요한 부분
(Database를 열었다거나 또는 File을 열었다면 꼭 닫아주고 프로그램이 종료되어야 하기 때문)
-시스템에 부하를 줄 수 있는 부분을 주로 처리 (자원 정리)
-자바는 생성한 객체를 임의로 소멸시킬 수 없음 (가비지 콜렉터의 역할)
-> 갑자기 예외가 발생해서 사용할 수 없는 객체를 작업을 못하게 만들어 메모리에 부하 발생을 줄임 (자원 정리)
c.f close() 메서드
*throws
-메서드 안에서 예외처리(try~catch)를 하지 않고 예외를 보관하여 메서드가 호출된 곳으로 예외를 양도하는 방법
-메서드가 하나가 아닌 여러개일 때 여러개 메서드에서 모두 try~catch를 반복적으로 넣어야하는 문제를 해결해줌
-메서드명 뒤에 명시
package kr.s26.exception;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class ExceptionMain06 {
public void printData() throws IOException, NumberFormatException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("단 입력: ");
// String -> int
int dan = Integer.parseInt(br.readLine()); // readline()은 한 라인에 입력한 데이터를 String으로 반환
System.out.println(dan + "단");
System.out.println("--------------");
for (int i = 1; i <= 9; i++) {
System.out.println(dan + "*" + i + "=" + dan * i);
}
}
public static void main(String[] args) {
ExceptionMain06 em = new ExceptionMain06();
try {
em.printData();
} catch (IOException e) {
System.out.println("입력시 오류 발생");
} catch (NumberFormatException e) {
System.out.println("숫자를 입력하세요");
}
}
}
*BufferedReader로 입력받기
-IOException을 무조건 예외처리 해주어야 함
(※ IOException: 입출력 작업 중에 발생하는 예외,
파일이 존재하지 않거나 파일에 접근할 수 없는 경우 등의 입출력 관련 오류 시 발생)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class ExceptionMain06 {
public void printData() throws IOException, NumberFormatException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("단 입력: ");
*예외의 종류
-Exception 클래스와 그 자손들은 예외처리 필수(Checked 예외)
-RuntimeException 클래스와 그 자손들은 예외처리 선택(Unchecked 예외)
*throw 예외 던지기
-사용자(프로그래머)가 의도적으로 예외를 발생시킬 때 throw문을 사용해 인위적으로 예외를 발생시킴
package kr.s26.exception;
public class ExceptionMain07 {
public void methodA(String[] n) throws Exception {
if (n.length > 0) { // 데이터 입력한 경우
for (String s : n) {
System.out.println(s);
}
} else { // 데이터 입력 안한 경우
// 예외를 인위적으로 발생시킴
throw new Exception("배열에 요소가 없습니다.");
}
}
public static void main(String[] args) {
ExceptionMain07 em = new ExceptionMain07();
try {
em.methodA(args);
} catch(Exception e) {
// 예외 문구 출력
// System.out.println(e.toString());
System.out.println(e.getMessage());
}
}
}
-> 이 프로그램에서는 데이터를 입력 안 한 것을 예외로 보겠다!
*사용자 정의 예외클래스
-예외의 종류를 구분하기 위해 사용
-Exception 클래스를 상속받아 필요한 기능만 넣어서 만들 수 있음
class NegativeNumberUseException extends Exception {
public NegativeNumberUseException(String str) { // 메세지를 넘겨주는 생성자만 정의
super(str);
}
}
public class ExceptionMain08 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("0 이상의 정수 입력: ");
try {
int num = input.nextInt();
if (num >= 0) {
System.out.println("입력한 숫자 : " + num);
} else { // 음수 입력
// 사용자 정의 예외 클래스에 예외 문구를 저장해서 객체로 생성해서 예외를 발생시킴
throw new NegativeNumberUseException("음수를 사용할 수 없습니다.");
}
} catch (NegativeNumberUseException e) {
System.out.println(e.getMessage());
} catch (Exception e) {
System.out.println("알 수 없는 예외 발생!");
} finally {
if (input != null) {
input.close();
}
}
}
}
*컬렉션(Java Collections Framework)
-데이터를 많이 저장할 수 있는 클래스들의 집합

-컬렉션 쪽은 인터페이스 형태로 값만 저장
-맵 쪽은 식별자(key)와 값(value) 같이 저장
*java.util.ArrayList (리스트)
-데이터를 1차원으로 늘어놓은 형태의 자료구조 (배열과 유사)
-배열과 달리 길이가 고정되어 있지 않음 => 가변길이
-데이터의 저장, 추가, 삭제, 변경이 모두 가능
-인터페이스
- (auto boxing) 기본 자료형은 자동으로 오토박싱됨 e.g. int -> Integer
-데이터 타입이 모두 달라서 Object 타입으로 저장됨
-일반적으로는 한가지 데이터타입을 선택해서 저장
*list 구조의 특징
-저장된 순서 유지
-중복 저장 허용
-실수로 다른 타입의 데이터를 저장하면 코드 실행시 다운캐스팅 과정에서 런타임에러 발생
-> 제네릭 표현으로 해결
*제네릭 표현
-객체를 생성할 때 객체에 저장할 수 있는 요소의 타입을 지정
-제네릭 표현은 객체 타입만 허용
e.g. int (x), Integer (o)
ArrayList<String> list = new ArrayList<String>();
list.add("장영실"); // String
list.add("홍길동"); // String
list.add(1000); // Integer 에러
*요소의 추가
// 요소의 추가
list.add("홍길동");
list.add("김유신");
list.add("박문수");
list.add("장영실");
list.add("홍길동");
*요소의 삭제
-Integer 타입의 ArrayList에서 요소를 삭제할 때, 숫자를 그대로 넣으면 인덱스로 취급함
// 요소의 삭제
list.remove(2); // 인덱스
list.remove("홍길동"); // 요소
list2.remove(2); // 인덱스
list2.remove(Integer.valueOf(40)); // 요소, int -> Integer
*요소의 변경
// 요소의 변경
// list명.set(인덱스, 데이터);
list2.set(1, 30);
-인덱스를 차례대로 검증하면서 삭제하고 싶을 때 인덱스 0부터 체크하여 삭제하면 놓치는 데이터가 발생할 수 있음
-> 가장 마지막 인덱스부터 순회
// 짝수 삭제
// for (int i = 0; i < list.size(); i++) {
// if (list.get(i) % 2 == 0) {
// list.remove(i);
// }
// }
for (int i = list.size() - 1; i >= 0; i--) {
if (list.get(i) % 2 == 0) {
list.remove(i);
}
}
-indexOf()/lastIndexOf()
// 인덱스 탐색
int index1 = list.indexOf("사과");
System.out.println("첫번째 사과 : " + index1); //1
int index2 = list.lastIndexOf("사과");
System.out.println("마지막 사과 : " + index2); //4
// 망고가 존재하지 않으면 -1 반환
int index3 = list.indexOf("망고");
System.out.println("망고 : " + index3); //-1
-contains()
// ArrayList에 머루가 저장되어 있으면 true 반환, 없으면 false 반환
boolean f1 = list.contains("머루");
System.out.println("머루 : " + f1);
boolean f2 = list.contains("망고");
System.out.println("망고 : " + f2);
*정렬
-java.util.Collections 클래스 사용
// 정렬(사전 순서대로)
Collections.sort(list);
// 정렬(현재 순서의 역순으로)
Collections.reverse(list);
*java.util.Vector
-ArrayList와 마찬가지로 List 인터페이스를 구현했기 때문에 구조가 거의 동일
-ArrayList의 동작속도가 더 빠름
2024.03.07
*java.util.Stack
-후입선출 LIFO (Last-In First-Out)
-stk.push() :데이터 삽입
-stk.pop() :스택에 저장된 마지막 요소 반환하고 제거
-stk.isEmpty()
*큐(Queue)
-선입선출 FIFO(First-In First-Out)
-java.util.LinkedList를 이용해서 구현
-linked.offer() :데이터 삽입
-linked.peek() :큐에 저장된 첫번째 요소를 검색
-linked.poll() :큐에 저장된 첫번째 요소 반환하고 제거
*Set
-java.util.HashSet에서 Set 인터페이스를 구현해서 만듦
-중복값 불허(중복이면 저장을 하지 않음)
-java.util.Iterator를 이용해 데이터 검색
Iterator<String> ir = hs.iterator();
while(ir.hasNext()) {
System.out.print(ir.next() + " ");
}
-전통적으로는 이터레이터를 사용했으나 지금은 확장for문도 사용 가능
-Collections로 정렬하기 위해서 HashSet을 ArrayList 타입으로 형변환
//HashSet은 Collections를 이용해 sort 할 수 없어서 형변환
//HashSet -> Set -> Collection
List<Integer> list = new ArrayList<Integer>(hs);
//오름차순 정렬
Collections.sort(list);
*Map
-java.util.HashMap 사용
-key와 value의 쌍을 저장
-저장된 순서가 유지되지 않음
HashMap<String, Integer> map = new HashMap<String, Integer>();
-map.put(k, v) :데이터 저장
-map.get(k) :데이터 검색
-key를 중복해서 입력할 시 나중에 입력한 값으로 덮어씀
-key와 value에 null을 허용
-java.util.Iterator를 이용해 데이터 검색
-키값만 뽑아내기 (키를 통해서 밸류를 구하기 위해)
//키값을 뽑아내기 위해 HashMap -> Set -> Iterator
Set<Integer> s = map.keySet();
Iterator<Integer> keys = s.iterator();
while(keys.hasNext()) {
Integer key = keys.next();
System.out.println(key);
}
*java.util.Hashtable
-key를 중복해서 입력할 시 나중에 입력한 값으로 덮어씀
-key와 value에 null을 허용하지 않음
-hashmap과 거의 유사하고 가능한 hashmap을 사용하는 편이 좋음
-java.util.Enumeration 이용해 키값 뽑아낼 수 있음
(Enumeration 인터페이스는 Iterator 인터페이스의 부모 클래스)
//Enumeration을 이용하여 key 구하기
Enumeration<String> en = h.keys();
while (en.hasMoreElements()) {
System.out.println(en.nextElement());
}
2024.03.08
*multi catch문에서 에러 메세지 각각 지정하기
-instanceof 연산자 사용
} catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
if (e instanceof ArrayIndexOutOfBoundsException) {
System.out.println("입력한 데이터가 없습니다.");
} else if (e instanceof NumberFormatException) {
System.out.println("숫자가 아닙니다.");
}
}
*java.io.File
-절대경로: String path = "C:\\javaWork\\sample.txt";
-상대경로: String path = "sample.txt";
-f1.createNewFile(): 제공된 경로를 기반을 파일을 생성.
파일이 생성되면 true 반환, 생성되지 않으면 false 반환. 경로가 잘못되면 IOException 발생
public class FileMain02 {
public static void main(String[] args) {
//절대경로
// String path = "C:\\javaWork\\sample.txt";
//상대경로
String path = "sample.txt";
File f1 = new File(path);
System.out.println("---------파일 생성---------");
try {
/*
* 제공된 경로를 기반을 파일을 생성.
* 파일이 생성되면 true 반환, 생성되지 않으면 false 반환
* 경로가 잘못되면 IOException 발생
*/
System.out.println(f1.createNewFile());
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("---파일 정보---");
System.out.println("절대경로: " + f1.getAbsolutePath());
System.out.println("상대경로: " + f1.getPath());
System.out.println("디렉토리명: " + f1.getParent());
System.out.println("파일명: " + f1.getName());
}
}
-f1.renameTo(f2): 파일명을 변경할 수 있으면 변경하고 true를 반환, 불가능하면 false를 반환
인자에 파일명을 String으로 넣는게 아니라 File 객체를 생성해서 그걸 인자로 넣어줘야 함
public class FileMain03 {
public static void main(String[] args) {
//상대경로
String path = "sample.txt"; //원래 파일명
String new_path = "example.txt"; //새 파일명
File f1 = new File(path);
System.out.println("-----파일명 변경-----");
File f2 = new File(new_path);
//파일명을 변경할 수 있으면 변경하고 true 반환,
//변경이 불가능하면 false 반환
System.out.println(f1.renameTo(f2));
}
}
-f1.delete(): 삭제할 수 있으면 삭제하고 true를 반환, 불가능하면 false를 반환
if (f1.delete()) {
System.out.println(f1.getName() + " 파일 삭제");
} else {
System.out.println("파일을 삭제하지 못했습니다.");
}
-f1.mkdir(): 새로운 디렉토리를 생성할 수 있으면 생성하고 true를 반환, 불가능하면 false를 반환
-f1.delete(): 디렉토리 삭제도 파일 삭제와 동일
*스트림
-데이터를 목적지로 입출력하기 위한 방법
-스트림에 데이터를 쓸 수 있고, 스트림에서 데이터를 읽을 수 있음
-출력 스트림(output stream): 스트림에 데이터를 쓸 경우
-입력 스트림(input stream): 스트림에서 데이터를 읽을 경우
-FIFO 구조
-스트림은 넣어진 데이터가 처리되기 전까지는 스트림에 사용되는 스레드는 지연상태에 빠짐
-IOException이 발생할 수 있어서 꼭 예외처리를 해주어야 함
*스트림의 분류
-용도에 의한 분류
① 1차 스트림 : 디바이스에 직접 연결되는 스트림
② 2차스트림 : 1차 스트림과 연결을 통해 디바이스에 연결되는 스트림
-전송 방향에 의한 분류
① 입력 스트림 : 디바이스로부터 데이터를 읽어오는 스트림
② 출력스트림 : 디바이스로 데이터를 출력하는 스트림
-전송 단위에 의한 분류
① 바이트스트림 : 1 Byte 단위로 입력, 출력하는 스트림
② 문자스트림 : 한 문자(2 Byte) 단위로 입력, 출력하는 스트림
*바이트스트림(기본)
-한글을 처리할 때는 2바이트가 필요해서 바이트 배열로 처리해야 함
*java.io.InputStream
-추상클래스라서 직접 객체 생성 할 수 없음
-> System.in 으로 InputStream을 반환해서 사용함
-System.in.read(): 문자 하나를 입력 받아서 아스키 코드로 반환(표준입력방법)
-> char로 캐스팅해서 사용
-엔터키가 \r과 \n으로 구성되어 있어 엔터를 치면 \r\n이 전달되어 버림
->엔터 키를 read() 받아서 사용하지 않는 방법으로 처리
public static void main(String[] args) {
System.out.print("영문자 1개 입력: ");
try {
int a = System.in.read();
System.out.println(a + ", " + (char) a);
System.in.read(); //enter 처리(입력받고 사용하지 않기) \r 13
System.in.read(); //enter 처리(입력받고 사용하지 않기) \n 10
System.out.print("숫자 1개 입력: ");
int b = System.in.read() - 48; //아스키코드로 반환된 것을 10진수로 변환
System.out.println(b);
} catch (IOException e) {
e.printStackTrace();
}
}
*InputStream으로 여러 문자 입력받기
-while문 이용
int input = 0;
try {
//명시적으로 -1을 만들려면 ctrl+z
while ((input = System.in.read())!=-1) {
System.out.println(input + ", " + (char)input);
}
-초기 input 값을 0으로 설정해두고 input이 -1이 될 때 while문을 빠져나오도록 설정
-명시적으로 -1을 받아오기 위해서는 콘솔창에 ctrl+z 입력
-Scanner는 JDK 5.0 이후에 도입됨
-범용적으로는 BufferedReader가 많이 사용됨
*java.io.FileInputStream
-파일의 정보를 한 문자씩 읽어 들여 아스키 코드로 반환
public static void main(String[] args) {
FileInputStream fis = null;
int readbyte;
try {
fis = new FileInputStream("file.txt");
//파일의 정보를 한 문자씩 읽어 들여 아스키 코드로 반환
//영문 이외의 문자는 crash
while ((readbyte = fis.read()) != -1) {
System.out.print((char) readbyte);
}
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//자원정리
if (fis != null) {
try {
fis.close();
} catch (IOException e) {}
}
}
}
-사운드나 그림, 동영상 등을 처리할 때 바이트스트림 사용
*byte 배열 이용하기 (한글 입력)
-파일명.available(): 파일의 바이트 수를 읽어옴
-> 바이트 배열의 사이즈 설정 가능
-파일명.read(바이트배열): 파일로부터 읽어 들인 데이터를 byte[]에 저장
byte[] readbyte2;
try {
fis = new FileInputStream("file.txt");
//영문 이외의 문자도 처리 가능
readbyte2 = new byte[fis.available()];
//파일로부터 읽어 들인 데이터를 byte[]에 저장
fis.read(readbyte2);
// byte[] -> String
System.out.println(new String(readbyte2));
}
*java.io.FileOutputStream
-파일로 출력하기
-String을 getBytes() 메서드 사용하여 바이트 배열로 만들고 파일명.write(바이트배) 메서드 사용하여 파일에 데이터 기록
//파일 생성
fos = new FileOutputStream("fileout.txt");
String message = "Hello File! 파일에 내용 기술 ...";
//파일에 데이터 기록
// String -> byte[]
fos.write(message.getBytes());
*파일 생성모드 (2)
1) 덮어쓰기
//덮어쓰기
fos = new FileOutputStream("fileout.txt");
2) 이어쓰기
-두번째 인자를 true로 설정 (기본값은 false로 덮어쓰기 모드임)
//이어쓰기
fos = new FileOutputStream("fileout.txt", true);
*java.io.BufferedOutputStream: 버퍼 사용해서 파일로 출력
-계란을 판에 담아서 한번에 옮기는 방법
(<->FileOutputStream은 계란을 하나하나 옮기는 방법)
-데이터량이 많을 경우 더 효율적인 방법
-버퍼를 활용해서 일정량을 메모리 공간에 담은 다음 그 일정량 단위로 파일에 flush
-FileOutputStream으로 파일을 생성한 다음 생성한 파일을 BufferedOutputStream에 넘겨줌
-write()를 통해 버퍼에 데이터를 담은 flush()를 해서 버퍼를 비우고 버퍼에 있는 데이터를 파일에 출력해주어야 함.
-flush()하지 않으면 버퍼에 담겨있는 데이터를 파일에 저장하지 않음
-BOS의 close() 메서드가 실행되면 버퍼를 최종적으로 검사해주어 버퍼에 남은 데이터가 있으면 자동적으로 flush()가 수행됨
-자원정리를 할때는 BOS를 먼저 정리하고 FOS를 정리해서 에러를 방지
*문자 입력 스트림
-입력 클래스에는 이름에 모두 Reader가 붙어있고 출력 클래스에는 모두 Writer가 붙어 있음
-System.in으로 받아온 스탠다드 인풋을 InputStreamReader에서 2바이트 문자로 반환함.
그걸 BufferedReader가 라인 바이 라인으로 받아옴.
(즉, 표준 입력-1바이트(System.in) -> 문자스트림(InputStreamReader)으로 가공
-> 메서드로 라인바이라인으로 읽어옴(BufferedReader)
br = new BufferedReader(new InputStreamReader(System.in));
-문자 출력 스트림은 거의 사용하지 않음
*java.io.FileReader
-파일로부터 데이터를 한 문자씩 읽어들여 유니코드로 반환
fr = new FileReader("file.txt");
//파일로부터 데이터를 한 문자씩 읽어들여 유니코드로 반환
while ((readChar = fr.read()) != -1) {
System.out.print((char) readChar);
}
*java.io.FileWriter
-FileOutputStream과 달리 버퍼 기능을 가지고 있음
-write() 메서드는 버퍼에 출력을 하는 기능
-flush()를 명시해야 함
*toString() 메서드 오버라이딩
-데이터를 읽어오는 코드를 줄일 수 있음
*문자열 포맷하기
-String.format("포맷 스트링", arguments)
-printf()와 동일
'Web Development > SIST' 카테고리의 다른 글
[Java|HTML|CSS] 6주차 수업: 2024.03.25 - 2024.03.29 (0) | 2024.03.25 |
---|---|
[Oracle|PL/SQL|Java] 5주차 수업: 2024.03.18 - 2024.03.22 (0) | 2024.03.22 |
[Java|Oracle] 4주차 수업: 2024.03.11 - 2024.03.15 (0) | 2024.03.22 |
[Java] 2주차 수업: 2024.02.26 - 2024.02.29 (0) | 2024.03.04 |
[Java] 1주차 수업: 2024.02.16 - 2024.02.23 (1) | 2024.02.26 |