-
TECHIT 앱 스쿨 2기: Android 9일차 (23.05.04)[THEC!T] 앱 스쿨2기 : Android 2023. 5. 5. 03:42728x90
자료 출처 : 안드로이드 앱스쿨 2기 윤재성 강사님 수업 내용
오늘의 시작은 동기와 비동기로 시작하였습니다만 글의 내용의 시작은 try ~ catch 문 부터 시작 하겠습니다.
예외 : 프로그램 언어적으로 해결이 가능한 경우
ex) 코드를 잘못 작성한 경우
오류 : 프로그램 언어적으로 해결이 불가능함.
ex) 정전으로 인한 서버 다운과 같은 경우
하기 에서는 이해를 돕기위해 오류라는 단어를 사용하였습니다.
try ~ catch
프로그램이 수행 중에 오류(예외) 가 발생하거나 발생 가능성이 있다면 JVM은 해당 오류(예외) 가 OS(운영체제) 나
JVM에 영향이 전파되는 것을 막기 위하여 해당 프로그램을 강제 종료시킵니다.
이때 오류(예외) 가 발생하였을 때 프로그램이 강제 종료 되지 않게 하고, 개발자가 준비한 오류(예외) 발생 시 수행되어야 하는 코드가 수행될 수 있도록 하여 오류(예외) 를 대비할 수 있게 해주는 것이 예외 처리 라고 합니다.
이때 try ~ catch 문을 이용하여 작성 할 수 있습니다.
try 문 에는 예외가 발생할 가능성이 있는 부분들을 작성하며, 만약 예외가 발생한다면 발생한 부분과 하기 부분은 실행되지 않으며, catch 문에 작성한 코드가 실행됩니다.
catch 문 에는 예외가 발생 하였을 때 동작할 내용을 작성합니다.
그리고 try ~ catch 문 전후에 작성한 코드들은 정삭 작동 됩니다.
package com.test.main; public class StudyClass { public static void main(String[] args) { // TODO Auto-generated method stub int [] arr = new int [3]; System.out.println("try ~ catch 문 이전 작동여부 확인"); try { // 예외가 발생할 가능성이 있는 코드를 작성한다. System.out.printf("예외 발생 코드 동작여부 확인 arr[4] = %d\n",arr[4]); // 예외가 발생한 이후 코드의 진행여부 확인. System.out.println("예외가 발생하고나서 동작여부 확인"); } catch(Exception e) { System.out.println("에러 발생"); } System.out.println("try ~ catch 문 이후 작동여부 확인"); } }
출력 결과
try ~ catch 문 이전 작동여부 확인 에러 발생 try ~ catch 문 이후 작동여부 확인
catch (Exception e) 라고 되어 있는데 여기서 Exception 은 클래스 이며, e는 Exception 클래스를 사용하여 만든 객체 입니다.
만약 e를 출력한다면 에러의 종류와 원인이 나오게 됩니다.
상기 코드에서 catch 문을 다음과 같이 수정해보겠습니다.
catch(Exception e) { System.out.println("에러 발생"); System.out.println(e); }
try ~ catch 문 이전 작동여부 확인 에러 발생 java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 3 try ~ catch 문 이후 작동여부 확인
만약 에러 발생 원인 별로 각기 다른 코드를 실행 하고 싶다면 Exception 대신에 ArrayIndexOutOfBoundsException 같이 적어 주면 됩니다.
그리고 ArrayIndexOutOfBoundsException 같은 클래스들은 상속을 받고 있는데 따라 올라가게 되면 Exception 클래스가 나옵니다.
그렇기에 예상 되는 예외 상황이 아닌 예외 상황이 나올 수 있으므로 하기와 같이 catch 문을 수정하여 좀 더 안전하게 사용할 수 있습니다
try { // 예외가 발생할 가능성이 있는 코드를 작성한다. System.out.printf("예외 발생 코드 동작여부 확인 arr[4] = %d\n",arr[4]); // 예외가 발생한 이후 코드의 진행여부 확인. System.out.println("예외가 발생하고나서 동작여부 확인"); }catch(ArrayIndexOutOfBoundsException e) { System.out.println("ArrayIndexOutOfBoundsException 에러 발생"); System.out.println(e); }catch (ArithmeticException e) { System.out.println("ArithmeticException 발생했습니다."); System.out.println(e); }catch (NullPointerException e) { System.out.println("NullPointerException 발생했습니다."); System.out.println(e); }catch(Exception e) { System.out.println("에러 발생"); System.out.println(e); } System.out.println("try ~ catch 문 이후 작동여부 확인");
출력 결과
try ~ catch 문 이전 작동여부 확인 ArrayIndexOutOfBoundsException 에러 발생 java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 3 try ~ catch 문 이후 작동여부 확인
자바에서 에러를 개발자가 일부러 일어나게 할 수 있다.
바로 throw 입니다.
그리고 만약 메서드에서 예외 상황이 발생할 가능성이 있다면 throws 를 이용하여 작성합니다.
이렇게 되면 추후 해당 메서드를 호출 하는 쪽은 무조건 예외처리를 해야 합니다.
그 중 RunTimeException을 상속받은 것들은 throws 해도 예외처리에 대한 강제성을 줄 수 없기 때문에
Exception도 같이 작성합니다.
-> RunTimeException 내에서 이미 예외처리를 하고 있기 때문에 코드작성에 있어 강제성을 줄 수 없다.
package com.test.main; public class StudyClass { public static void main(String[] args) { // TODO Auto-generated method stub // testMethod3는 예외들을 throws하고 있기 때문에 // 반드시 예외처리를 해줘야 한다. try { ExcepClass t200 = new ExcepClass(); t200.testM3(-100); t200.testM3(200); }catch(Exception e) { e.printStackTrace(); } } } class ExcepClass{ // 기본 메서드 public void testM1() { System.out.println("ExcepClass 내 기본 메서드"); } // 조건에 안맞으면 예외상황 발생 하는 메서드 public void testM2(int a) { if(a > 10) { // throw new ArithmeticException("여기에 문자열 넣으면?"); } System.out.printf("a : %d\n",a); } public void testM3(int a) throws Exception, ArithmeticException { // a1에 전달된 값이 양수가 아니면 오류를 발생시킨다. if(a <= 0) { throw new ArithmeticException("양수만 넣어라..."); } System.out.println("a1은 양수입니다"); } }
출력 결과
java.lang.ArithmeticException: 양수만 넣어라... at com.test.main.ExcepClass.testM3(StudyClass.java:39) at com.test.main.StudyClass.main(StudyClass.java:11)
동기 : 작업을 순차적으로 처리하는 것을 의미합니다.
-> ex) 가게에 직원이 한명이고 손님이 여러명일 때 먼저 온 손님의 메뉴부터 먼저 만든다
비동기 : 동기적인 작업 여러개를 동시에 처리하는 것을 의미합니다.
주의점으로는 비동기적으로 진행되는 각각의 작업이 있을 때 다른 작업의 결과물을 가져오는 작업이 있으면 안되며,
만약 가져와한다면 동기적으로 작업해야한다는 점입니다.-> ex) 가게에 직원과 손님이 여러명일 때 손님1, 손님2 .... 의 메뉴를 동시에 만든다.
자바에서는 비동기 처리를 위해 Thread 라는 클래스와 Runnable 인터페이스를 지원합니다.
자바에서 쓰레드를 사용하는 목적은 크게 2가지가 있습니다.
첫번째 비동기 작업을 지원하기 위해
두번째 오류가 발생 할 수 있는 코드를 쓰레드로 처리하기 위해서 입니다.쓰레드 진행 시 오류가 발생하면 해당 쓰레드만 종료 되기 때문입니다.
비동기 처리를 위해 Thread 라는 클래스와 Runnable 인터페이스 작성 및 사용 방법 입니다.
Thread
클래스에서 Thread 클래스를 상속받아 Thread 를 사용합니다.
package com.study.com; public class StudyClass { public static void main(String[] args) { // TODO Auto-generated method stub // Thread를 상속받은 클래스를 이용한 객체 생성 TestClass1 t1 = new TestClass1(); // start()을 이용하여 해당 쓰레드 실행 t1.start(); // Thread를 상속받은 클래스를 이용한 객체 생성 TestClass2 t2 = new TestClass2(); // start()을 이용하여 해당 쓰레드 실행 t2.start(); } } //Thread를 상속받은 클래스 class TestClass1 extends Thread{ // 쓰래드를 발생시켜 처리할 메서드 public void run() { try { for(int i = 0; i < 10; i++) { Thread.sleep(500); System.out.println("TestClass1"); } } catch(Exception e) { e.printStackTrace(); } } } //Thread를 상속받은 클래스 class TestClass2 extends Thread{ // 쓰래드를 발생시켜 처리할 메서드 public void run() { try { for(int i = 0; i < 10; i++) { Thread.sleep(500); if(i > 5) { throw new Exception(); } System.out.println("TestClass2"); } } catch(Exception e) { e.printStackTrace(); } } }
출력 결과
TestClass1 TestClass2 TestClass1 TestClass2 TestClass1 TestClass2 TestClass1 TestClass2 TestClass1 TestClass2 TestClass1 TestClass2 TestClass1 java.lang.Exception at com.study.com.TestClass2.run(StudyClass.java:42) TestClass1 TestClass1 TestClass1
Runnable
Runnable 인터페이스를 구현한 클래스를 사용하여 작성합니다.
-> Runnable 인터페이스를 지원한 이유는 자바에서 클래스는 다중 상속을 지원하지 않기에, 다른 클래스에 상속을 받은 클래스에서도 비동기 작업을 할 수 있게 하기 위함입니다.
package com.study.com; public class StudtClass2 { public static void main(String[] args) { // TODO Auto-generated method stub // Runnable 인터페이스를 구현한 클래스 TestClass3 t3 = new TestClass3(); Thread thread = new Thread(t3); thread.start(); // Runnable 인터페이스를 구현한 예외를 발생시키는 클래스 TestClass4 t4 = new TestClass4(); Thread thread4 = new Thread(t4); thread4.start(); } } // Runnable 인터페이스를 구현한 클래스 class TestClass3 implements Runnable { @Override public void run() { // TODO Auto-generated method stub try { for(int i = 0; i < 10; i++) { Thread.sleep(300); System.out.println("TestClass3 interface"); } } catch(Exception e) { e.printStackTrace(); } } } //Runnable 인터페이스를 구현한 예외를 발생하는 클래스 class TestClass4 implements Runnable { @Override public void run() { // TODO Auto-generated method stub try { for(int i = 0; i < 10; i++) { Thread.sleep(300); if(i > 5) throw new Exception(); System.out.println("TestClass4 interface"); } } catch(Exception e) { e.printStackTrace(); } } }
출력 결과
TestClass3 interface
TestClass4 interface
TestClass3 interface
TestClass4 interface
TestClass3 interface
TestClass4 interface
TestClass3 interface
TestClass4 interface
TestClass3 interface
TestClass4 interface
TestClass3 interface
TestClass4 interface
TestClass3 interface
java.lang.Exception
at com.study.com.TestClass4.run(StudtClass2.java:49)
at java.base/java.lang.Thread.run(Thread.java:833)
TestClass3 interface
TestClass3 interface
TestClass3 interface
쓰레드의 우선순위
기본 값은 5로 되어 있으며, 0 ~ 10까지 우선순위를 지정할 수 있으며, 숫자가 높을 수록 우선순위가 높아집니다.
하지만 우선순위가 높다고 먼저 처리가 되는 것이 아니라 먼저 처리 될 확률이 올라가는 것 뿐입니다.
package com.test.main; public class MainClass { public static void main(String[] args) { // TODO Auto-generated method stub // 쓰레드 우선순위. // 여러 쓰레드를 가동 시켰을 대 우선적으로 처리될 쓰레드를 지정할 수 있다. Thread1 t1 = new Thread1(); Thread2 t2 = new Thread2(); Thread3 t3 = new Thread3(); // 쓰레드 우선 순위 확인 int p1 = t1.getPriority(); int p2 = t2.getPriority(); int p3 = t3.getPriority(); System.out.printf("변경 전 우선 순위 p1 : %d\n", p1); System.out.printf("변경 전 우선 순위 p2 : %d\n", p2); System.out.printf("변경 전 우선 순위 p3 : %d\n", p3); // 우선순위 설정 t1.setPriority(10); t2.setPriority(1); t3.setPriority(1); int p4 = t1.getPriority(); int p5 = t2.getPriority(); int p6 = t3.getPriority(); System.out.printf("변경 후 우선 순위 p4 : %d\n", p4); System.out.printf("변경 후 우선 순위 p5 : %d\n", p5); System.out.printf("변경 후 우선 순위 p6 : %d\n", p6); // 쓰레드 가동 t1.start(); t2.start(); t3.start(); } } class Thread1 extends Thread{ @Override public void run() { for(int i = 0 ; i < 20 ; i++) { System.out.println("Thread1"); } } } class Thread2 extends Thread{ @Override public void run() { for(int i = 0 ; i < 20 ; i++) { System.out.println("Thread2"); } } } class Thread3 extends Thread{ @Override public void run() { for(int i = 0 ; i < 20 ; i++) { System.out.println("Thread3"); } } }
출력결과 (실행 시 마다 매번 다름)
변경 전 우선 순위 p1 : 5 변경 전 우선 순위 p2 : 5 변경 전 우선 순위 p3 : 5 변경 후 우선 순위 p4 : 10 변경 후 우선 순위 p5 : 1 변경 후 우선 순위 p6 : 1 Thread1 Thread1 Thread1 Thread1 Thread1 Thread1 Thread1 Thread1 Thread1 Thread1 Thread3 Thread3 Thread3 Thread3 Thread3 Thread3 Thread3 Thread3 Thread3 Thread3 Thread3 Thread3 Thread3 Thread3 Thread3 Thread3 Thread3 Thread3 Thread3 Thread3 Thread2 Thread2 Thread2 Thread2 Thread2 Thread2 Thread2 Thread2 Thread2 Thread2 Thread2 Thread2 Thread2 Thread2 Thread2 Thread2 Thread2 Thread2 Thread2 Thread2 Thread1 Thread1 Thread1 Thread1 Thread1 Thread1 Thread1 Thread1 Thread1 Thread1
쓰레드의 동기화
쓰레드는 비동기적 처리를 수행합니다. 이에 다수의 쓰레드가 만약 동일한 메서드를 호출했을 경우, 호출 당한 메서드에서 호출 당한 순서대로 작업을 처리하게 만들 수 있습니다.
즉, 한번에 여러개의 작업이 일어나서는 안되는 경우에 synchronized 라는 키워드를 사용하여 메서드를 작성하면 됩니다.
메서드에서 synchronized 쓰지 않고 동기화를 하지 않았을 경우
package com.test.main; public class MainClass { public static void main(String[] args) { // TODO Auto-generated method stub Thread1 t1 = new Thread1(); Thread2 t2 = new Thread2(); Thread3 t3 = new Thread3(); t1.start(); t2.start(); t3.start(); } } class Thread1 extends Thread { @Override public void run() { TestClass.testMethod("Thread1"); } } class Thread2 extends Thread { @Override public void run() { TestClass.testMethod("Thread2"); } } class Thread3 extends Thread { @Override public void run() { TestClass.testMethod("Thread3"); } } class TestClass{ public static void testMethod(String name) { for(int i = 0; i < 100; i++) { System.out.printf("%s : %d\n", name,i); } } }
결과
Thread1 : 0 Thread1 : 1 Thread1 : 2 Thread1 : 3 Thread1 : 4 Thread2 : 0 Thread2 : 1 Thread2 : 2 Thread2 : 3 Thread2 : 4 Thread2 : 5 Thread2 : 6 Thread2 : 7 Thread2 : 8 Thread2 : 9 Thread2 : 10 Thread2 : 11 Thread2 : 12 Thread2 : 13 Thread2 : 14 Thread2 : 15 Thread2 : 16 Thread2 : 17 Thread2 : 18 Thread2 : 19 Thread3 : 0 Thread3 : 1 Thread3 : 2 Thread3 : 3 Thread3 : 4 Thread3 : 5 Thread3 : 6 Thread3 : 7 Thread3 : 8 Thread3 : 9 Thread3 : 10 Thread3 : 11 Thread3 : 12 Thread3 : 13 Thread3 : 14 Thread3 : 15 Thread3 : 16 Thread3 : 17 Thread3 : 18 Thread1 : 5 Thread1 : 6 Thread1 : 7 Thread1 : 8 Thread1 : 9 Thread1 : 10 Thread1 : 11 Thread1 : 12 Thread1 : 13 Thread1 : 14 Thread1 : 15 Thread1 : 16 Thread1 : 17 Thread1 : 18 Thread1 : 19 Thread3 : 19
메서드에서 synchronized를 사용하여 쓰레드의 동기화를 사용하였을 경우
package com.test.main; public class MainClass { public static void main(String[] args) { // TODO Auto-generated method stub Thread1 t1 = new Thread1(); Thread2 t2 = new Thread2(); Thread3 t3 = new Thread3(); t1.start(); t2.start(); t3.start(); } } class Thread1 extends Thread { @Override public void run() { TestClass.testMethod("Thread1"); } } class Thread2 extends Thread { @Override public void run() { TestClass.testMethod("Thread2"); } } class Thread3 extends Thread { @Override public void run() { TestClass.testMethod("Thread3"); } } class TestClass{ public synchronized static void testMethod(String name) { for(int i = 0; i < 20; i++) { System.out.printf("%s : %d\n", name,i); } } }
출력 결과
Thread1 : 0 Thread1 : 1 Thread1 : 2 Thread1 : 3 Thread1 : 4 Thread1 : 5 Thread1 : 6 Thread1 : 7 Thread1 : 8 Thread1 : 9 Thread1 : 10 Thread1 : 11 Thread1 : 12 Thread1 : 13 Thread1 : 14 Thread1 : 15 Thread1 : 16 Thread1 : 17 Thread1 : 18 Thread1 : 19 Thread2 : 0 Thread2 : 1 Thread2 : 2 Thread2 : 3 Thread2 : 4 Thread2 : 5 Thread2 : 6 Thread2 : 7 Thread2 : 8 Thread2 : 9 Thread2 : 10 Thread2 : 11 Thread2 : 12 Thread2 : 13 Thread2 : 14 Thread2 : 15 Thread2 : 16 Thread2 : 17 Thread2 : 18 Thread2 : 19 Thread3 : 0 Thread3 : 1 Thread3 : 2 Thread3 : 3 Thread3 : 4 Thread3 : 5 Thread3 : 6 Thread3 : 7 Thread3 : 8 Thread3 : 9 Thread3 : 10 Thread3 : 11 Thread3 : 12 Thread3 : 13 Thread3 : 14 Thread3 : 15 Thread3 : 16 Thread3 : 17 Thread3 : 18 Thread3 : 19
java.lang 패키지
자바에서 유일하게 import 하지 않아도 되는 패키지 입니다.
해당 패키지에는 자바 프로그램을 작성할 때 많이 사용하는 것 들이 모여있습니다.
Object
Object는 자바에서 모든 클래스의 기본 클래스 입니다. 따라서 모든 객체의 직/간접적인 상위 클래스 입니다 .
클래스를 생성할 때 상속 받는 코드를 작성하지 않는다면 extends Object가 추가 되어 있다고 생각하면 됩니다.
Wrapper 클래스
Wrapper 클래스는 기본 자료형 값을 관리하기 위한 목적으로 만든 클래스 입니다.
즉 기본 자료형 값을 객체로 만드는 용도로 사용합니다. -> 자바가 객체지향프로그래밍 언어니까....
Wrapper 클래스는 기본 자료형 값과 관련하여 다양한 메서드를 제공합니다.
1. 기본 자료형 값을 문자열로 변환하는 메서드
2. 문자열을 기본 자료형 값으로 변환하는 메서드
3. 기본 자료형을 객체로 만드는 메서드
4. 객체를 기본 자료형으로 만드는 메서드
5. 두 값의 크기를 비교하는 메서드
등등
Wrapper 클래스에서 제공하는 메서드 일부 사용.
package com.test.main; public class MainClass { public static void main(String[] args) { // TODO Auto-generated method stub // 기본 자료형 값을 문자열로 변환한다. // Wrapper 객체의 toString 메서드를 이용해 변환할 수 있다. Integer int1 = 100; String str1 = int1.toString(); System.out.println(str1); Double double1 = 11.11; String str2 = double1.toString(); System.out.println(str2); // Wrapper 클래스의 static 메서드 사용 String str3 = Integer.toString(100); String str4 = Double.toString(11.11); System.out.println(str3); System.out.println(str4); // + 연산자 사용 // 문자열과 문자열 아닌 것을 + 연산을 하면 문자열이 아닌 것이 // 문자열로 변환되고 두 문자열을 합친 새로운 문자열을 만들어 준다. String str5 = 100 + ""; String str6 = 11.11 + ""; System.out.println(str5); System.out.println(str6); // 문자열 값을 기본 자료형 값으로 변환한다. // Wrapper 클래스의 static 메서드를 활용한다. String str7 = "100"; String srt8 = "11.11"; int a100 = Integer.parseInt(str7); double a200 = Double.parseDouble(srt8); System.out.println(a100); System.out.println(a200); } }
String
Strings는 자바에서 문자열을 관리하기 위해 제공되는 클래스 입니다.
Strings으로 만든 객체를 == 연산자를 이용하여 비교하게 되면 false 값이 나옵니다.
== 연산자는 두 객체가 같은 객체인지를 확인하는 연산자 이기 때문입니다.
Wrapper 클래스에 내용 중 자료형 값과 관련하여 제공하는 메서드가 있다고 하였는데
해당 메서드는 equals() 입니다. String 또한 equals() 메서드를 가지고 있습니다.
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
return (anObject instanceof String aString)
&& (!COMPACT_STRINGS || this.coder == aString.coder)
&& StringLatin1.equals(value, aString.value);
}
package com.study.main; public class StudyClass { public static void main(String[] args) { // TODO Auto-generated method stub // String 는 자바에서 문자열을 관리하기 위해 제공되는 클래스이다. // " "로 묶어준 문자열도 String 객체 입니다. String str1 = "study"; String str2 = new String("study"); if(str1 == str2) System.out.println("== 연산자 결과 : 같다"); else System.out.println("== 연산자 결과 : 다르다"); if(str1.equals(str2)) System.out.println("equals 결과 : 같다"); else System.out.println("equals 결과 : 다르다"); } }
출력 결과
== 연산자 결과 : 다르다 equals 결과 : 같다
String 가 가지고 있는 메서드 들을 좀 더 확인해보겠습니다.
package com.study.main; public class StudyClass { public static void main(String[] args) { // TODO Auto-generated method stub // String 는 자바에서 문자열을 관리하기 위해 제공되는 클래스이다. // " "로 묶어준 문자열도 String 객체 입니다. String str1 = "study"; String str2 = new String("study"); if(str1 == str2) System.out.println("== 연산자 결과 : 같다"); else System.out.println("== 연산자 결과 : 다르다"); // equals 두 객체의 값이 같다면 true 다르다면 false를 반환한다. if(str1.equals(str2)) System.out.println("equals 결과 : 같다"); else System.out.println("equals 결과 : 다르다"); // toUpperCase 소문자를 대문자로 변경하여 저장한다. String str3 = "abcd"; String str4 = str3.toUpperCase(); System.out.printf("str3.toUpperCase() 결과 : %s\n", str4); // toLowerCase 대문자를 소문자로 변경하여 저장한다. String str5 = "ABCD"; String str6 = str5.toLowerCase(); System.out.printf("str5.toLowerCase() 결과 : %s\n", str6); // replace 해당 문자를 다른 문자로 바꾸어 저장한다. String str7 = "abcdef"; String str8 = str7.replace("c", "CCCCCC"); System.out.printf("str7.replace() 결과 : %s\n", str8); // indexOf : 지정된 문자열의 위치를 반환한다. String str9 = "9876543210"; System.out.printf("str9.indexOf(\"2\") 결과 : %s\n",str9.indexOf("2")); // startsWith : ~로 시작하는지에 대해 boolean 형으로 반환한다. // endsWith : ~로 끝나는지에 대해 boolean 형으로 반환한다. System.out.printf("str9.startsWith(\"2\") 결과 : %s\n",str9.startsWith("2")); System.out.printf("str9.startsWith(\"9\") 결과 : %s\n",str9.startsWith("9")); System.out.printf("str9.endsWith(\"7\") 결과 : %s\n",str9.endsWith("7")); System.out.printf("str9.endsWith(\"0\") 결과 : %s\n",str9.endsWith("0")); // length : 문자열의 길이를 반환한다. 즉 글자수를 반환한다. System.out.printf("str9.length : %d\n", str9.length()); // substring : 지정한 위치에 있는 문자열 일부를 가져온다 String str10 = "가나다라마바사아자"; System.out.printf("str10.substring(5) : %s\n", str10.substring(5)); System.out.printf("str10.substring(1, 5) : %s\n", str10.substring(1, 5)); // 가:0 나:1 다:2 .... 자:8 위치는 배열처럼 생각하면 된다. // trim : 문자열의 좌우 공백을 제거한다. 문자열 사이의 공백은 제거하지 않는다. String str11 = " 가 나 "; System.out.printf("str11.trim() :%s\n", str11.trim()); } }
출력 결과
== 연산자 결과 : 다르다 equals 결과 : 같다 str3.toUpperCase() 결과 : ABCD str5.toLowerCase() 결과 : abcd str7.replace() 결과 : abCCCCCCdef str9.indexOf("2") 결과 : 7 str9.startsWith("2") 결과 : false str9.startsWith("9") 결과 : true str9.endsWith("7") 결과 : false str9.endsWith("0") 결과 : true str9.length : 10 str10.substring(5) : 바사아자 str10.substring(1, 5) : 나다라마 str11.trim() :가 나
StringBuffer
StringBuffer 는 문자열을 다루는데 있어 String와 달리 직접적인 수정이 가능합니다.
또한 String 의 값을 변경하려면 새로운 객체를 생성해야하지만 StringBuffer 는 새로운 객체를 생성하지 않고 직접 수정이 가능하여 메모리를 효율적으로 사용하기에 좋습니다.
package com.test.main; public class MainClass { public static void main(String[] args) { // TODO Auto-generated method stub // StringBuffer : 관리하는 문자열에 대한 직접적인 조작을 할 수 있다. // String 이 관리하는 문자열은 변경이 불가능하다. // 이에, 추가 변환 삭제 등의 작업을 하게 되면 새로운 문자열이 계속 // 생성된다. // 메모리를 효율적으로 사용하기 위해 자주 변화되는 문자열은 StringBuffer로 // 관리한다. // StringBuffer 생성 StringBuffer buffer1 = new StringBuffer(); StringBuffer buffer2 = new StringBuffer("문자열"); // 문자열 추가 buffer1.append(100); buffer1.append(11.11); buffer1.append("문자열"); System.out.println(buffer1); // StringBuffer -> String String str1 = buffer1.toString(); System.out.println(str1); // 삽입 buffer1.insert(2, 555); buffer1.insert(8, "문자열"); System.out.println(buffer1); // 변경 // 2 ~ 5 - 1까지를 동해물과 백두산으로 바꾼다. buffer1.replace(2, 5, "동해물과 백두산"); System.out.println(buffer1); // 삭제 // 2 ~ 10-1까지 삭제한다. buffer1.delete(2, 10); System.out.println(buffer1); } }
Date 와 Calendar
Date 와 Calendar 의 공통점은 바로 날짜와 시간을 다루는 데 사용하는 클래스라는 점입니다.
차이점으로는 Date는 ms 단위로 컴퓨터가 관리하는 체계로 되어있으며, Calender 은 사람이 관리하는 체계로 되어 있습니다.
Date에서 시간을 계산하는 방식은 유닉스 타임을 기준으로 시간을 계산합니다.
유닉스 타임은 1970-1-1 0시 0분 0초 0ms -> 0ms 으로 계산합니다.
package com.test.main; import java.util.Calendar; import java.util.Date; import java.time.*; public class MainClass { public static void main(String[] args) { // TODO Auto-generated method stub // Date : 컴퓨터 입장에서의 시간 관리 체계 // Calender : 사람 입장에서의 시간 관리 체계 // 현재 시간을 관리하는 Date 객체를 생성한다. Date date1 = new Date(); System.out.println(date1); // date 객체가 관리하는 시간값을 유니스타임으로 가져온다. long time1 = date1.getTime(); System.out.println(time1); // 유닉스 타임을 지정하여 Date 객체를 생성한다. Date date2 = new Date(2000000000000L); System.out.println(date2); // 0을 지정하여 Date 객체를 생성한다. Date date3 = new Date(0); System.out.println(date3); // 최대 시간 Date date4 = new Date(Long.MAX_VALUE); // 최소 시간 Date date5 = new Date(Long.MIN_VALUE); System.out.println(date4); System.out.println(date5); // 현재 시간을 관리하는 Calendar 생성 Calendar c1 = Calendar.getInstance(); System.out.println(c1); int year = c1.get(Calendar.YEAR); int month = c1.get(Calendar.MONTH) + 1; int day = c1.get(Calendar.DAY_OF_MONTH); int hour = c1.get(Calendar.HOUR); int minute = c1.get(Calendar.MINUTE); int second = c1.get(Calendar.SECOND); int ms = c1.get(Calendar.MILLISECOND); System.out.printf("%d-%d-%d %d:%d:%d:%d\n", year, month, day, hour, minute, second, ms); // 2023년 12월 31일 17시 37분 23초 800ms 를 지정한다. Calendar c2 = Calendar.getInstance(); c2.set(Calendar.YEAR, 2023); c2.set(Calendar.MONTH, 11); c2.set(Calendar.DAY_OF_MONTH, 31); c2.set(Calendar.HOUR_OF_DAY, 17); c2.set(Calendar.MINUTE, 37); c2.set(Calendar.SECOND, 23); c2.set(Calendar.MILLISECOND, 800); // Date 객체로 가져온다 Date date100 = c2.getTime(); System.out.println(date100); } }
컬렉션
컬렉션은 객체들을 모아 관리하는 요소들을 말합니다.
1. List : 순서를 통해 객체들을 관리합니다.
2. Map : 이름을 통해 관리합니다.
3. Set : 집합 -> 중복된 객체를 담을 수 없으며, 순서와 이름에 대한 개념이 없습니다.
제네릭
컬렉션들은 제네릭 타입이라는 것을 설정 할 수 있습니다.
제네릭 타입은 컬렉션이 관리할 객체의 타입을 정하는 것 입니다.
그렇기에 제네릭 타입을 정해 놓으면 추후 컬렉션에서 객체를 추출할 때 형변환을 자동으로 해줍니다.
package com.test.main; import java.util.ArrayList; import java.util.HashMap; public class MainClass { public static void main(String[] args) { // TODO Auto-generated method stub // Collection // 객체들을 모아 관리하는 요소들 // List : 순서를 통해 관리한다. // Map : 이름을 통해 관리한다. // Set : 집합(중복된 객체를 담을 수 없고, 순서와 이름에 대한 개념이 없다) // List ArrayList list1 = new ArrayList(); list1.add("문자열1"); list1.add("문자열2"); list1.add("문자열3"); list1.add(100); list1.add(11.11); // 관리하는 객체의 개수 System.out.printf("객체 개수 : %d\n", list1.size()); for(Object obj : list1) { System.out.println(obj); } // 객체를 추출 하여 변수에 담아준다. String str1 = (String)list1.get(0); Integer int1 = (Integer)list1.get(3); Double double1 = (Double)list1.get(4); System.out.println(str1); System.out.println(int1); System.out.println(double1); // Generic type // Collection 들은 Generic type 이라는 것을 설정할 수 있다. // Generic type은 Collection이 관리할 객체의 타입을 지정하는 것으로써 // 객체를 추출할 때 형변환을 자동으로 해준다. ArrayList<String> list2 = new ArrayList<String>(); list2.add("문자열1"); list2.add("문자열2"); list2.add("문자열3"); // list2.add(100); String str10 = list2.get(0); String str11 = list2.get(1); String str12 = list2.get(2); System.out.printf("%s, %s, %s\n", str10, str11, str12); for(String str13 : list2) { System.out.println(str13); } // HashMap // <이름 타입, 객체 타입> HashMap<String, String> map1 = new HashMap<String, String>(); map1.put("key1","문자열 1"); map1.put("key2","문자열 2"); map1.put("key3","문자열 3"); String str100 = map1.get("key1"); String str200 = map1.get("key2"); String str300 = map1.get("key3"); System.out.println(str100); System.out.println(str200); System.out.println(str300); // 리스트에서 객체를 제거한다. System.out.println(list1); // 순서를 지정하여 삭제 list1.remove(1); System.out.println(list1); // 객체를 지정하여 삭제 list1.remove("문자열3"); System.out.println(list1); // 삽입 list1.add(1, "추가된 문자열"); System.out.println(list1); // 모두 삭제 list1.clear(); System.out.println(list1); // HashMap에서 객체 제거 System.out.println(map1); map1.remove("key1"); System.out.println(map1); // 모두 제거 map1.clear(); System.out.println(map1); } }
마무리
오늘 강의를 들으면서 정말 지금까지 배운 내용을 정리를 하지 않았더라면 아찔했겠다라는 생각이 들었습니다.
배웠던 내용을 베이스로 하여 탑을 쌓아가는 느낌을 받았기 때문입니다.
다행히 내일은 어린이날 공휴일이라 수업이 없습니다. 즉 지금까지 배운 내용을 복습하기 딱 좋은 시간이라 볼 수 있습니다. 사실 코틀린을 독학하면서도 중간중간 헷갈리는 부분이 있었으나, 이번에 자바강의를 듣고 정리를 하면서 기존에 알고 있었던 지식이 인터페이스 였다면 지금은 인터페이스를 구현한 클래스가 되어가는 느낌이랄까요??ㅋㅋㅋ
그리고 자바를 알면 알수록 코틀린을 독학 했을 때 이해가 잘 안가던 부분들이 점점 이해가 되고 있으며, 코틀린이 문법적으로 정말 편하게 만들었구나 라는 생각이 들기도 합니다.
일단 내일은 충전의 시간을 충분히 가진 다음 복습을 할 수 있도록 하겠습니다.
그리고 다음주 수업 일정을 봤더니....스트림 과 네트워크로 자바강의는 마무리가 되는데 해당 부분은 예습이 필요할 것 같아 주말에는 예습을 좀 해야 될 것 같습니다.
오늘의 마음가짐 : 추상클래스 같은 개발자가 되지 말자... 인터페이스를 구현한 클래스 같은 개발자나 추상클래스를 상속 받은 클래스 같은 개발자가 되자~!
'[THEC!T] 앱 스쿨2기 : Android' 카테고리의 다른 글
TECHIT 앱 스쿨 2기: Android 11일차 (23.05.09) (0) 2023.05.09 TECHIT 앱 스쿨 2기: Android 10일차 (23.05.08) (0) 2023.05.08 TECHIT 앱 스쿨 2기: Android 8일차 (23.05.03) (0) 2023.05.04 TECHIT 앱 스쿨 2기: Android 7일차 (23.05.02) (0) 2023.05.03 TECHIT 앱 스쿨 2기: Android 6일차 (23.05.01) (0) 2023.05.01