StudyServer
web, server, java, spring 등.. 공부한 것을 기록하는 장소 입니다. 공부하면서 정리하였기 때문에 틀린 내용이 있을 수 있습니다. 이야기 해주시면 수정하겠습니다.

reference,abstract 정리

2018-11-11 00:00:00 +0000

기본데이터(PrimitiveType)

  • 변수에 데이터가 저장됨
  • 부동소수점 타입(float, double)
  • 정수 타입(char, long, int, short, byte)

레퍼런스 타입(ReferenceType)

  • 변수가 객체를 가르킴
  • 열거 타입(enum), 배열 타입(array), 인터페이스 타입(Interface), 클래스 타입(class)

참조값과 데이터

  • 레퍼런스 변수를 또 다른 레퍼런스 변수에 대입할 때 일어나는 일
  • obj2이 가르키는 주소를 obj1도 가르키게 했다
  • obj1 = obj2;
  • obj가 obj1에게 참조 주소를 준다(call by reference)
Object obj
Func(obj);
void Func(Object obj1){}

null 참조값

  • 아무것도 가지고 있지 않음, 초기화가 되지 않은 것과는 다르다

부모, 자식 간 형변환

  • 자식 클래스를 부모 클래스로 형변환 하고 나선 오버라이딩 된 함수만 호출 가능하다
Account obj = new SpecielAccount("name", 2);
obj.addSpecielPoint() > 에러

Account obj = new SpecielAccount("name", 2);
SpecielAccount ob2 = obj; // 에러
SpecielAccount ob2 = (SpecielAccount)obj; // 성공
  • 부모클래스는 자식클래스로 변환되지 않는다
Account obj = new Account("name", 2);
SpecielAccount = (SpecielAccount) obj; // 에러

instanceof 연산자

  • 캐스트 연산 가능성을 검사하는 연산자. 자바 키워드
  • obj instanceof CheckingAccount
  • obj가 CheckingAccount 형으로 형변환으로 변경할 수 있는지 체크
  • 자식클래스 객체 of instanceof 자식클래스 => 성공
  • 자식클래스 객체 of instanceof 부모클래스 => 성공
  • 다만 if문으로 클래스 체크를 해서 다른 동작을 하도록 하는 것은 객체지향에 어긋남

열거타입

  • 상수체크 시 유용하게 사용
enum Season{
    SPRING, SUMMER, FALL, WINTER
}

클래스의 상속

  • 인스턴스화를 금지하는 abstract 키워드
  • 자식클래스에게 반드시 오버라이딩 하도록 강제시킨다
  • 추상메소드를 가지고 있다
  • abstract class Account

추상메소드

  • 메소드의 본체가 없는 함수
abstract void sendMessage();
  • 추상클래스는 인스턴스화 못시킨다. 오로지 상속으로만 사용 가능하다
  • 추상클래스, 인터페이스 쓰는 이유 => 코드의 독립성

추상클래스 예시

Person class는 현재 Work class를 멤버로 가지고 있다
그리고 role.doit() 함수 실행 시 ‘work 역활’이 출력된다.
이 때 Driver라는 클래스도 추가해서 doit 함수 실행 시 ‘Driver 역활’ 이라고 출력하고 싶다고 가정한다
Work에서 Driver로 수정하려면 많은 수정이 필요하다(생성자, return 값을 전부 Work에서 Driver로 바꿔야 한다)
하지만 Work와 Driver가 Role이라는 추상클래스를 상속하고 Person의 Work를 Role로 수정하면 코드 수정없이 Work에서 Driver로 수정할 수 있다
추상클래스로 만들어야 하는 이유는 doIt메소드를 만드기를 강제시키기 때문이다.
(기본클래스는 doit함수를 만든다는 보장이 없다)

수정전

public class Person {
     private String name;
     private Work role;
     
     public Person(){
           
     }
     public Person(String name, Work role) {
           super();
           this.name = name;
           this.role = role;
     }
     public Work getRole() {
           return role;
     }
     public void setRole(Work role) {
           this.role = role;
     }
}

public class Work{
     public void doIt() {
           System.out.println("work 역활");
}

수정후

  • Work가 Role을 상속하고, Person이 Work 대신 Role가상클래스를 멤버변수로 가짐
  • Role을 상속하는 Driver class를 추가해도 Person 소스코드 수정이 필요없다
public class Person{
     private String name;
     private Role role;
     
     public Person(){
           
     }
     public Person(String name, Role role) {
           super();
           this.name = name;
           this.role = role;
     }
     public Role getRole() {
           return role;
     }
     public void setRole(Role role) {
           this.role = role;
     }
}

public class Work extends Role{
     public void doIt() {
           System.out.println("work 역활");
}

FileNotFoundException Solve

2018-11-11 00:00:00 +0000

상황

txt파일을 읽기위해 소스코드와 같은 위치에 txt파일을 넣은 후
FileReader 객체로 파일읽기를 하니 java.io.FileNotFoundException 런타임 에러가 났다

해결

txt파일을 소스코드와 같은 위치가 아니라 해당 프로젝트 최상단에 넣어야 한다
예를들어 프로젝트 이름이 JavaEx라면 JavaEx 폴더에 넣어야 한다
.classpath,.project, src폴더, bin폴더가 있는 곳이 최상단 폴더이다

static

2018-11-08 00:00:00 +0000

클래스의 정적 구성 요소

  • static 키워드 사용
  • 객체를 생성하지 않고도 사용 가능
  • 객체 재생성해도 한번만 만들어짐
  • 클래스가 로딩될 때 메모리에 올라간다
  • static 함수 호출 시 class이름.static함수이름() 으로 호출한다

상수 필드

  • final 키워드 사용

정적 초기화 블록

  • static 키워드가 붙은 블록
  • 클래스가 사용되기 전에 자바 가상 기계에 의해 단 한 번 호출됨
  • 정적 필드의 초기값 설정에 주로 사용됨
  • 멤버변수는 정적 초기화 블록에서 초기화 못함. 메모리에 못 올라갔기 때문.
class HunderNumbers{
    static int arr[];
    static{
    err = new int[10];
    for(int cnt = 0; cnt < 100; ++cnt)
        arr[cnt] = cnt;
	}
}

Thread Synchronization(스레드동기화,원자성)

2018-11-07 00:00:00 +0000

스레드 동기화, 원자성 이란

Atomic Operation 원자성이란 소스코드가 한번에 실행된다는 걸 보장해주는 것이다.
스레드끼리는 stack(지역변수, 매개변수..)을 제외한 code, heap, static 데이터를 공유한다.
그렇기 때문에 여러 쓰레드가 공용 변수(code, heap, static 데이터)에 접근해서 값을 바꾼다면
제대로 연산이 되지 않는 문제가 발생한다.
예를들어 다음 class 멤버 함수가 있다.(memberId는 class 멤버 변수이다)

public void Func()
{
    int temp = memberId + 1;
    memberId = temp;
}

2개의 쓰레드가 Func() 함수에 접근하고 있다면
다음과 같은 상황이 벌어질 수 있다
(memberid가 0이라고 가정한다)

int temp = memberid + 1 실행 ( 1번째 쓰레드 접근 )
컨텍스트 스위칭 발생
int temp = memberid + 1 실행 ( 2번째 쓰레드 접근 )
컨텍스트 스위칭 발생
memberid(0) = 1; ( 1번째 쓰레드 접근 )
컨텍스트 스위치 발생
memberid(1) = 1; ( 2번째 쓰레드 접근, memberid에 1번째 쓰레드가 1을 넣어줬으므로 1이다)

만약 순서대로 실행되었다면 2가되었을 텐데 서로 접근하다 보니 temp 에 각 쓰레드마다 1을 넣어줘서 값을 뒤집어씌우게 되었다.
그렇다면 다음과 같이 바꾸면 원자성이 보장될까?

public void Func()
{
    ++memberId;
}

public void Func()
{
    memberId+=1;
}

이 소스도 원자성이 보장되지 않는다.
한줄이어서 한번에 처리된다고 생각하기 쉽지만
c++ 에서는 한줄코드가 여러개의 어셈블리어로 변환되기 때문에 연산 도중 컨텍스트 스위칭이 일어날 수 있다.
(자바도 비슷한 이유가 있을거라 생각된다.)

또 멀티 쓰레드 테스트 시 주의할 사항이 있다.
바로 println을 쓰면 안된다는 것이다.
println이 콘솔창에 찍는 처리를 하면서 다른 동작들을 자주 멈추게 하고 성능에 영향을 준다.
그래서 실행 후 결과를 보면 원자성이 보존된 결과가 나와서 착각하기 쉽다.

public void Func()
{
    println("before threadID:"+id+"meberid:"+memberId);
    memberId+=2;
    println("after threadID:"+id+"meberid:"+memberId);
}

원자성을 보장하기 위해선 어떻게 해야할까?
synchronized 키워드 : 자동 동기화 블록. 함수에 사용한다. 이 키워드를 사용하면 쓰레드가 함수 사용중일 때 다른 쓰레드는 대기하고, 처리완료 후 함수를 나갔을 때 다른 쓰레드가 들어가게 된다.
volatile 키워드 : 이것은 원자성은 보장하지 않는다. 이 키워드는 메인 메모리에 저장된 값과 동기화 되도록 한다. 그런데 다른 쓰레드에서 메인 메모리에 값을 쓰기 전에 컨텍스트 스위칭이 일어날 수 있으므로 동기화 할 수 없다.

volatile 설명 url : http://tutorials.jenkov.com/java-concurrency/volatile.html

Java Exception(예외처리)

2018-11-07 00:00:00 +0000

Java Exception(예외처리)

try-catch문

  • 컴파일 익셉션 : 컴파일 과정에서 에러
  • 런타임 익셉션 : 실행프로그램 구동 중 에러
  • try-catch문은 런타임 익셉션 발생
  • 아래 예제는 Exception in thread “main” java.lang.ArithmeticException: / by zero 익셉션 발생
public static void main(String[] args) {
    int a = 3, b = 0;
    int result;
    result = a / b;
    System.out.println(result);
    System.out.println("Done.");
} 

try-cath문 사용 방법

  • 익셉션이 발생할 것 같은 구문을 try catch 문으로 감싼다
  • try는 소스코드를 실행했을 때 에러가 발생할 것 같은 부분을 넣는다
  • catch는 에러가 났을 때 처리를 하는 부분이다(여러번 쓸 수 있다)
  • finaly는 예외가 일어나든 안 일어나든 실행한다.(생략가능)
  • 에러 출력 방법 e.printStackTrace(), e.getMessage()
public class C{
     public static void main(String[] args) {
           int a = 3, b = 0;
           int result;
           
           try{
                result = a / b;
                System.out.println(result);
           
           }catch(Exception e){
           
                System.out.println("잘못된 연산입니다");           
           }
           
           System.out.println("Done.");
     }    
}

try-catch문 순서

  • try문에서 예외가 발생하면 아래 소스코드는 실행하지 않는다.그러므로 2번을 제외하고 전부 출력된다
  • 만약 10/1이라면 예외가 발생하지 않는다. 그래서 3번빼고 전부 출력된다
public static void main(String[] args) {
           int a = 3, b = 0;
           int result;
           try{
                System.out.println("1");
                int a = 10/0;
                System.out.println("2");
           }catch(Exception e){
                System.out.println("3");
           }finally{
                System.out.println("4");              
           }
           
           System.out.println("5");
}

throws

  • throws는 예외발생 처리를 함수 호출한 부분으로 넘긴다
returnvalue functionname() throws Exception
{
}

throws 사용방법

  • 예외를 넘길 함수의 인자 옆에 throws Exception 을 추가한다
  • 아래 예제에선 main함수에서 add함수를 호출하는데 인자1과 인자2의 더한 값이 0보다 작다면
  • throws 발생 시키고 있다.
  • add함수가 throws를 발생시키고 있으므로 호출할 때 try-catch 블록안에 넣어야 한다. try문으로 감싸지 않으면 에러가 뜬다
public class Ex{
     static void add(int a, int b) throws Exception
     {
           int sum = a + b;
           if(sum < 0){
                throw new Exception("음수는 싫어");
           }
     }
     
     public static void main(String[] args) {
           
           try {
                add(10, -20);
           } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
           }
	}
}

throw

  • 함수에 throws 키워드를 안쓰고 그냥 예외를 발생시킬 수 있다
  • 아래 예제처럼 그냥 사용하면 에러난다
  • throw를 사용하면 사용한 구문을 try-catch 문으로 감싸줘야 한다.
public static void main(String[] args) {
    throw new Exception();
}

Exception extends

  • Exception을 상속받아 예외 class를 만들어 try-catch문을 강제할 수 있다
  • 예외처리할 class를 만들고 Exception클래스를 상속 받는다
  • 함수에 throws 예외를 발생시키는데 new Exception 대신 우리가 만든 클래스로 new ExceptionEx 한다
  • 예외가 발생할 때 ExceptionEx 생성자가 호출된다
class ExceptionEx extends Exception
{
     public ExceptionEx()
     {
           System.out.println("errorFunc");
           
     }    
}

public class C{
     
     static void func() throws ExceptionEx
     {
           throw new ExceptionEx();
     }
     
     
     public static void main(String[] args) {
           
           try {
                func();
           } catch (Exception e) {
           }
}

Posts

subscribe via RSS