객체지향 프로그래밍에 흔히 사용되는 표준화된 모델링 표기 체계 (객체 모델링에 대한 산출물)
객체 모델링 결과 - UML(학계 : 이론) -> 계속 버전 업이 된다.
클래스 다이어그램 : 클래스의 구성 요소(박스 모델 사용하여 클래스 이름 및 필드, 메서드 작성) 와 클래스 간의 관계(선을 사용하여 상속, 구현, 포함 등 표시)를 묘사하는 다이어그램
시퀀스 다이어그램 : 특정 행동이 어떤 순서로 어떤 객체와 상호작용 하는지 표현하는 행위
유스케이스 다이어그램 : 시스템과 사용자의 상호작용을 다이어그램으로 표현한 것으로 사용자의 관점에서 시스템의 서비스 혹은 기능 및 그와 관련한 외부 요소를 보여주는 것
...
가시화 : 설계 내용을 가시적인 그래프 형태로 작성, 의사소통 자료로 사용
명세화 : SW 개발 단계의 각 과정에 필요한 모델 정확하고 완전하게 명세
구축화 : 다양한 객체지향 프로그래밍 언어로 변환 가능(순공학, 역공학 적용)
문서화 : 프로젝트 참여자들 간의 통제, 평가 및 의사소통에 필요한 문서화 가능
순공학 - (요구사항 정의 - 분석 - 설계 -구현) 단계로 개발하는 것으로 일반적인 개발 절차
다른 클래스 내부에 작성되는 클래스
종류
외부 클래스의 필드 선언 위치에 static 키워드 없이 선언된 클래스
내부 -> 외부 클래스의 멤버에 접근할 때 private 포함한 모든 멤버에 대해 자유롭게 참조 가능
static 멤버 가질 수 없다. 단 static final 멤버는 상수 취급되어 사용 가능
클래스
메인 클래스
public class ex01 {
//외부 클래스
private int outerMember = 1;
private void outerMethod() {
Inner inner = new Inner();
inner.innerMember = 100;
inner.innerMethod();
}
//인스턴스 내부 클래스
class Inner {
int innerMember = 10;
//static int staticMember = 10;
static final int finalstaticMember = 20;
private void innerMethod() {
System.out.println("om : " + outerMember + ", im : " + innerMember);
}
}
//메인 메소드
public static void main(String[] args) {
ex01 ex = new ex01();
ex.outerMethod();
//내부 클래스 접근 가능
Inner inner = ex.new Inner();
inner.innerMethod();
}
}
static 키워드가 붙은 내부 클래스, 인스턴스 내부 클래스와 달리 static 멤버 가질 수 있음
클래스
메인 클래스
메인 클래스에서 외부 클래스 객체를 생성하지 않아도 된다(static 객체 필요 없는 효과)
public class ex01 {
static class StaticInner {
private int iMember = 10;
private static int sMember = 0;
private void innerMethod() {
ex01 sinner = new ex01();
System.out.println("om : " + sinner.oMember +
", im : " + iMember);
}
}
private int oMember = 1;
private void outerMethod() {
StaticInner inner = new StaticInner();
inner.iMember = 100;
inner.innerMethod();
}
public static void main(String[] args) {
StaticInner inner = new StaticInner();
inner.innerMethod();
}
}
클래스 영역 아닌 메서드나 생성자 또는 초기화 블록 내부에 선언된 클래스
static 변수 x, final static 변수 가질 수 있음
내부 클래스 -> 외부 클래스 멤버에 접근하는 것은 전혀 제약이 없고 호춯할 때 외부 객체에 대한 참조도 필요 없다
내부적으로 컴파일러가 final 키워드를 변수에 추가하여 내부에서는 값을 변경할 수 없다.
클래스
메인 클래스
public class ex01 {
int iMember = 1;
static int cMember = 2;
void method() {
int localVar = 3;
class LocalInner {
int innerlocalVar = 4;
void innerMethod() {
System.out.println("외부 인스턴스 멤버 변수 : " + iMember);
System.out.println("외부 클래스 멤버 변수 : " + cMember);
System.out.println("외부 로컬 변수 " + localVar);
System.out.println("내부 인스턴스 멤버 변수 " + innerlocalVar);
iMember++;
cMember++;
//localVar++; //편집 불가능
innerlocalVar++; //편집 가능하나 실행 x
}
}
LocalInner lInner = new LocalInner();
lInner.innerMethod();
}
public static void main(String[] args) {
ex01 ex = new ex01();
ex.method();
System.out.println();
ex.method();
}
}
JRE System Library[java 버전~~] 우클릭 -> Build Path -> Configure Build Path -> JRE System Library[java 버전~~] 클릭하고 edit 눌러서 바꿔주기!
객체화가 이루어지지 않은 클래스( 이 클래스를 이용해 새로운 객체 만들 수 없고 선언과 동시에 바로 클래스를 구성하고 객체 생성함)
-> 주로 일회용으로 더 이상 재사용하지 않는 경우에 적합하게 사용(abstract 클래스나 인터페이스의 구현에 많이 사용됨)
로컬 내부 클래스의 한 종류로 기본 특성은 동일함
인터페이스 InnerB 생성
메인 클래스 생성( InnerB 선언과 동시에 바로 생성해버림)
인터페이스를 메서드 매개변수로 넘기고, 메인 메서드에서 호출 시에 매개변수에서 바로 만들어서 사용 가능
interface SomeInterface {
void printInfo();
}
public class ex01 {
int iMember = 1;
static int cMember = 2;
void OuterMethod(SomeInterface si) {
si.printInfo();
}
public static void main(String[] args) {
ex01 ex = new ex01();
int localVar = 3;
ex.OuterMethod(new SomeInterface() {
@Override
public void printInfo() {
//System.out.println("외부 인스턴스 멤버 변수 : " + iMember);
System.out.println("외부 클래스 멤버 변수 : " + cMember);
System.out.println("외부 로컬 변수 : " + localVar);
cMember++;
//localVar++; 편집 불가능
}
});
}
}
익명 내부 클래스를 조금 더 편리하게 사용하는 것으로 생각해도 된다.
public class MyFunctionalInterMain {
public static void main(String[] args) {
new MyFunctionalInter1() {
@Override
public void method() {
System.out.println("method 호출");
}
}.method();
}
}
public class MyFunctionalInterMain {
public static void main(String[] args) {
//인터페이스를 객체변수로 선언 , 이 때 람다식으로 선언 가능
MyFunctionalInter1 f = new MyFunctionalInter1() {
@Override
public void method() {
System.out.println("method 호출2");
}
};
f.method();
}
}
public class MyFunctionalInterMain {
public static void main(String[] args) {
//람다식
MyFunctionalInter1 f1 = () -> {
System.out.println("method 호출3");
};
f1.method();
//완전 축약 람다식
MyFunctionalInter1 f2
= () -> System.out.println("method 호출4");
f2.method();
}
}
public class MyFunctionalInterMain {
public static void main(String[] args) {
//실행문이 하나일 경우
//완전 축약 람다식
MyFunctionalInter1 f2 = () -> System.out.println("method 호출4");
f2.method();
}
}
이 인터페이스는 람다식에서 사용할 함수형 인터페이스이므로 abstract가 하나만 있는지 검사하라 << 라고 요청하는 어노테이션
두 개를 선언하니 에러가 발생하는 모습
인터페이스 생성
package pack1;
//추상 메서드는 반드시 하나만 있어야 한다.(함수형 인터페이스(람다식)일 경우)
@FunctionalInterface
public interface MyFunctionalInter {
void methodA();
//void methodB();
}
메인 클래스 생성
package pack1;
public class MyFunctionalInterMain {
public static void useFIMethod(MyFunctionalInter fi) {
fi.methodA();
}
public static void main(String[] args) {
useFIMethod(new MyFunctionalInter() {
@Override
public void methodA() {
System.out.println("methodA 호출");
}
});
useFIMethod( () -> {
System.out.println("람다식 이용");
});
//실행문이 하나일 때
useFIMethod(() -> System.out.println("람다식 이용2"));
}
}
위 코드에서 매개변수만 적어주면 된다.
인터페이스 생성
package pack1;
//추상 메서드는 반드시 하나만 있어야 한다.(함수형 인터페이스(람다식)일 경우)
@FunctionalInterface
public interface MyFunctionalInter {
void methodA(String msg);
//void methodB();
}
메인 클래스 생성
package pack1;
public class MyFunctionalInterMain {
public static void useFIMethod(MyFunctionalInter fi) {
fi.methodA("홍길동");
}
public static void main(String[] args) {
useFIMethod( (String msg) -> {
System.out.println("람다식 이용1 : " + msg);
});
//실행문이 하나일 때
useFIMethod(msg -> System.out.println("람다식 이용2 : " + msg));
}
}
에러
컴파일 에러 : 문법 에러 / javac 명령을 사용할 때 나타나는 에러 / eclipse : 빨간줄
런타임(실행) 에러 : 시스템 에러(처리 불가) / 예외(if / exception : 고급 에러 처리) (java 명령을 사용할 때 나타나는 에러) / eclipse : run as 사용 시
예외 처리 방식
try - 예외가 발생할 수 있는 코드 작성
catch - 해당 예외가 발생했을 때 처리할 코드 작성
예외 발생 경우 :
try 블록에서 예외 발생 -> (try안의 나머지 코드는 수행하지 못함) ->JVM 동작하여 예외객체 생성(new)해서 던져버림(throw) -> catch
로 받아서 catch 안 내용 실행
public class Exception1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("시작");
int num1 = 0;
int num2 = 20;
try { //에러 발생하지 않으면 try 구문 실행
int result = num2 / num1;
System.out.println(result);
}
catch (ArithmeticException e) { -->
System.out.println("exception 발생");
}
System.out.println("끝");
}
}
발생된 예외에 대한 구체적인 메세지 반환
public class Exception1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("시작");
int num1 = 0;
int num2 = 20;
try {
int result = num2 / num1;
System.out.println(result);
}
catch (ArithmeticException e) {
System.out.println("exception 발생");
System.out.println(e.getMessage());
e.printStackTrace();
}
System.out.println("끝");
}
}
ex 코드
public class exception2 {
public static void main(String[] args) {
System.out.println("시작");
String name = null;
int num1 = 0;
int num2 = 10;
System.out.println(name.length());
System.out.println(num2/num1);
System.out.println("끝");
}
}
위 코드 경우 첫번째 에러에서 NullPointerException 발생
String name = ""; 일경우(정상) 두번째 에러인 ArithmeticException 발생
위 코드를 처리하기 위해 try ~ catch 사용
public class exception3 {
public static void main(String[] args) {
System.out.println("시작");
String name = null;
int num1 = 0;
int num2 = 10;
try {
System.out.println(name.length());
}
catch(NullPointerException e) {
System.out.println("객체 생성후 메서드 사용");
}
try {
System.out.println(num2/num1);
}
catch(ArithmeticException e) {
System.out.println("0으로 나눌 수 없음");
}
System.out.println("끝");
}
}
불필요한 코드를 줄이기 위해 다중 예외 처리 사용 - 이 경우 if else 와 유사하게 실행(첫번째 catch 실행되면 빠져나감)
public class exception3 {
public static void main(String[] args) {
System.out.println("시작");
String name = null;
int num1 = 0;
int num2 = 10;
//다중 예외 처리, if ~ else if ~ else 와 유사
try {
System.out.println(name.length());
System.out.println(num2/num1);
}
catch(NullPointerException e) {
System.out.println("객체 생성후 메서드 사용");
}
catch(ArithmeticException e) {
System.out.println("0으로 나눌 수 없음");
}
System.out.println("끝");
}
}
에러를 통합적으로 처리할 때
public class exception3 {
public static void main(String[] args) {
System.out.println("시작");
String name = null;
int num1 = 0;
int num2 = 10;
//다중 예외 처리, if ~ else if ~ else 와 유사
try {
System.out.println(name.length());
System.out.println(num2/num1);
}
catch(Exception e) { //에러를 통합적으로 처리
System.out.println("[에러] : " + e.getMessage());
}
System.out.println("끝");
}
}
특정한 것은 처리해주고 나머지는 전부 처리할 때 (else 느낌)
String name에서 Exception 발생하면 첫 catch가 실행,
String name이 정상이면 나머지 Exception catch 실행
한 번에 여러개를 처리할 수 있는 장점이 있지만, 정확한 예외 처리가 어렵다
public class exception3 {
public static void main(String[] args) {
System.out.println("시작");
String name = null;
int num1 = 0;
int num2 = 10;
//다중 예외 처리, if ~ else if ~ else 와 유사
try {
System.out.println(name.length());
System.out.println(num2/num1);
}
catch(NullPointerException e) {
System.out.println("객체 생성후 메서드 사용");
}
catch(Exception e) { --> 나머지는 여기서 처리, 순서 바꿔쓰면 안됨
System.out.println("예외 처리!!");
}
System.out.println("끝");
}
}
try ~ catch 구문은 finally 블록 추가로 가질 수 있음
finally 블록은 예외 발생 여부와 상관없이 반드시 실행되어야 하는 내용을 작성
중간에 return 문을 만날 때에도 먼저 finally 블록을 실행 후 메서드 리턴 됨
import java.util.Random;
public class Finnaly1 {
public static void main(String[] args) {
int num = new Random().nextInt(2);
try {
System.out.println("code 1, num : " + num);
int i = 1 / num;
System.out.println("code 2 - 예외 없음");
return;
}
catch(ArithmeticException e) {
System.out.println("code 3 - 예외 처리 완료");
}
finally { --> 항상 실행되는 구문
System.out.println("code 4 - 언제나 실행");
}
System.out.println("code 5");
}
}
num = 0으로 Exception 발생할 시
정상 처리될 시
public class exception7 {
public void method1(int num) {
System.out.println("method 시작");
//입력값 검사
if(num >= 100) {
System.out.println("100보다 크다");
}
else {
//강제 예외 발생시키기(만들기)
try {
throw new Exception("100보다 작다"); -->강제로 예외 발생시킴
}
catch(Exception e) {
System.out.println("[에러] : " + e.getMessage());
}
}
System.out.println("method 끝");
}
public static void main(String[] args) {
exception7 e = new exception7();
e.method1(10);
System.out.println();
e.method1(200);
}
}
발생한 예외를 호출한 쪽으로 넘긴다(위임한다.)
코딩 중 Unhandled exception 뜨면 try ~ catch 처리를 해줘야 한다.
보통 저 문구가 뜨면 try ~ catch를 사용하고 싶은 영역을 잡고
우클릭 -> Surround With -> try/catch block 누르면 자동으로 생성된다.
public class exception7 {
public void method2(int num) throws Exception { //호출하는 쪽으로 던짐
System.out.println("method 시작");
//입력값 검사
if(num >= 100) {
System.out.println("100보다 크다");
}
else {
//강제 예외 발생시키기(만들기)
throw new Exception("100보다 작다"); // 던져짐
}
System.out.println("method 끝");
}
public static void main(String[] args) {
exception7 ee = new exception7();
try {
ee.method2(10); // 던진 예외를 받음, 대리로 예외 처리해줌
}
catch (Exception e) {
System.out.println("[에러] : " + e.getMessage());
}
}
}
사용자 정의 예외 클래스 / getLocalizedMessage() 오버라이드 처리
public class LoginFailException extends RuntimeException {
enum ErrorCode {
INVALID_ID, INVALID_PASS
}
private ErrorCode errorCode;
public LoginFailException(ErrorCode errorCode, String data) {
super(data);
this.errorCode = errorCode;
}
@Override
public String getLocalizedMessage() {
String msg = this.getMessage();
switch(errorCode) {
case INVALID_ID:
msg += ", 아이디를 확인하세요";
break;
case INVALID_PASS:
msg += ", 비밀번호를 확인하세요";
break;
}
return msg;
}
}
메인 클래스
public class UserManagerWithException {
public boolean login(String id, String pass) {
if(!id.equals("hong")) { --> id가 hong이 아니면 예외 던지기
throw new LoginFailException(LoginFailException.ErrorCode.INVALID_ID, id);
}
else if(!pass.equals("1234")) { --> pass가 1234가 아니면 예외 던지기
throw new LoginFailException(LoginFailException.ErrorCode.INVALID_PASS, pass);
}
return true;
}
public static void main(String[] args) {
UserManagerWithException uManager = new UserManagerWithException();
try {
//boolean result = uManager.login("hong", "1234");
//boolean result = uManager.login("hong2", "1234");
boolean result = uManager.login("hong", "5678");
System.out.printf("로그인 성공 여부 : %b %n",result);
}
catch (LoginFailException e) {
System.out.printf("예외 처리 : %s %n",e.getLocalizedMessage());
}
}
}
비밀번호 에러일 때
배열의 접근을 조금 더 쉽게 하기 위해 쓰임
아스키 코드값 순으로 정렬
import java.util.Arrays;
public class ArrayCopy {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] source = {1, 2, 3, 4, 5};
int[] target = new int[10];
for(int i = 0; i<source.length; i++) {
target[i] = source[i];
}
System.out.println(Arrays.toString(target));
int[] target2 = new int[10];
System.arraycopy(source, 0, target2, 0, source.length);
System.out.println(Arrays.toString(target2));
}
}
list 타입으로 형변환 해준다.
이런 출력 결과를 가지고 싶을 때 배열과 컬렉션을 같이 써서 나타낼 수 있다.
import java.util.ArrayList;
public class DataEx1 {
public static void main(String[] args) {
Student s1 = new Student("1", "홍길동", "010-111-1111", "20", "서울시");
Student s2 = new Student("2", "박문수", "010-222-2222", "22", "경기도");
Student s3 = new Student("3", "이몽룡", "010-333-3333", "25", "강원도");
ArrayList<Student> datas = new ArrayList<>();
datas.add(s1);
datas.add(s2);
datas.add(s3);
for(Student s : datas) {
System.out.println(s.getSeq() + "\t" + s.getName()
+ "\t" + s.getPhone() + "\t" + s.getAge() + "\t" + s.getRegion());
}
}
}
java.text패키지에 포함
숫자, 날짜, 텍스트 데이터를 일정한 형식에 맞게 표현할 수 있는 방법을 객체지향적으로 설계하여 표준화
형식화에 사용될 패턴을 정의
데이터를 정의된 패턴에 맞춰 형식화 / 역으로 형식화된 데이터에서 원래의 데이터를 얻기 가능
숫자에 대한 형식화 클래스
지정된 기호들 조합하여 패턴을 만들고 그것을 이용해 데이터를 문자열로 만들거나 거꾸로 문자열을 데이터로 변환
날짜 / 시간 정보에 대한 패턴을 지정해서 파싱과 포맷팅 처리
DecimalFormat과 동일한 메서드 사용
throws 처리
try ~ catch 처리
+를 사용하여 문자열을 연산하면 지저분해 보이기 쉬운데, 이 때 이 클래스를 사용하면 데이터를 변수처럼 사용해서 메시지 패턴에 적용 가능
결과