Back-end/Java

Java개념 - 후반부(접근 제어자, 인터페이스, 다형성, 예외, 참조)

HOONY_612 2021. 5. 19. 11:38
반응형

이제 Java의 후반부 개념에 대해서 설명하겠다.

이 부분은 내용이 어려워 매우 기본적인 부분을 내가 이해한만큼만 적어봤다.

 

● Classpath

일단 Class를 작성하고 컴파일을 하면 각각의 .class파일이 생성된다. 그리고 이것을 다른 package에서 가져다 사용하고 싶을 경우, 클래스 패스를 사용한다. 이것을 환경변수에 설정해놓으면 어디에서나 사용 할 수 있다.

 

EX> System.out.println(1)

--> 풀이 :  System이라는 class  포함 멤버 out이라는 객체(변수) 안에 println메소드 가지고있다.

 

 

● 접근 제어자

- 접근 제어자란? 다른 Class의 접근을 제한하거나 허용하기 위해 만든 것.

- 왜 사용할까? 클래스를 보호하기 위한 . 실제 내부적으로 계산이 일어나는 부분을 private설정.

 

- 대표적인 접근자

  1. Public : 외부 객체들이 자유롭게 사용할 있는 메소드나 변수.
  2. Private : 같은 메소드내에서만 사용 있다. 아래 예시를 참고.
package org.opentutorials.javatutorials.accessmodifier;
class A {
	public String y(){
		return "public void y()";
	}
	private String z(){
		return "public void z()";
	}
	public String x(){
		return z();
	}
}
public class AccessDemo1 {
	public static void main(String[] args) {
		A a = new A();
		System.out.println(a.y());
		// 아래 코드는 오류가 발생한다.
		//System.out.println(a.z());
		System.out.println(a.x());
		}
}

● Abstract

- Abstract 란?  Abstract 클래스나 메소드를 사용하기 위해서는 반드시 상속해서 사용하도록 강제하는 것.

 

<상위 클래스>
public abstract void sum(); 
public abstract void avg();

<하위 클래스>
public void sum(){
System.out.println("- sum :"+(this.left+this.right));
}
public void avg(){
System.out.println("- avg :"+(this.left+this.right)/2);
}

위와 같이 큰 프로젝트에서 상위 클래스에 선언해놓고 하위 클래스에서 오버라이딩을 통해서 사용한다.

 

● Final

Final 실행되는 과정에서 한번 값이 정해진 이후에는 변수 내의 값이 바뀌지 않도록하는 규제다.

상속도 금지. 오버라이딩하는 것을 방지.

 

● Interface

- 인터페이스란? 하위 클래스에 특정한 메소드가 강제로 존재하게 하는 .

- 왜 사용할까? 협업을 서로 소통하기위해서 사용한다.

 

interface I{
	public void z();
}

class A implements I{
	public void z(){}
}

기본적인 문법 예시이다.

근데 인터페이스는 특징이 여러가지가 있다.

 

첫 번째로 하나의  클래스가 여러가지 인터페이스를 가지는 것이 가능하다.

그래서 여러가지 멤버를 하나라도 구현하지 않으면 오류가 발생한다.

 

두 번째로 인터페이스도 상속이 가능하다. 예를 들면 interface i3 extends i4 이렇게 사용한다.

 

마지막으로 인터페이스의 멤버는 반드시 public해야한다.

 

● 다형성

package org.opentutorials.javatutorials.polymorphism;

class A{
    public String x(){return "A.x";}
}
class B extends A{
    public String x(){return "B.x";}
    public String y(){return "y";}
}
public class PolymorphismDemo1 {
    public static void main(String[] args) {
        A obj = new B();
        System.out.println(obj.x());
    }
}

위의 예시는 다형성을 한 번에 설명 할 수있는 예시이다.

오버로딩이랑 헷갈릴 수 있는데 오버로딩은 다형성의 특성 중 하나이다.

 

위의 객체 obj은 A데이터 타입에 B클래스로 만들어져있다.

결론적으로 A클래스 멤버만 이용가능하고 B클래스에서 오버라이딩을 적용할 수 있다.

 

이처럼 다형성이란 하나의 클래스가 다양한 동작을 할 수 있게 만들어 주는 기능이다.

아래의 실제 사용 예시를 보자.

package org.opentutorials.javatutorials.polymorphism;
 
interface father{}
interface mother{}
interface programmer{
    public void coding();
}
interface believer{}

class Steve implements father, programmer, believer{
    public void coding(){
        System.out.println("fast");
    }
}
class Rachel implements mother, programmer{
    public void coding(){
        System.out.println("elegance");
    }
}

public class Workspace{
    public static void main(String[] args){
        programmer employee1 = new Steve();
        programmer employee2 = new Rachel();
         
        employee1.coding();
        employee2.coding();
    }
}

위의 Steve와 Rachel은 다양한 인터페이스를 만족해야한다. 하지만 workplace에서는 두 명이 프로그래머다 라는 특성이 중요하므로 원하는 기능만을 구현하여 사용 할 수 있다. 그리고 그 안에 coding이라는 method를 통하여 프로그래머 특성을 알 수 있다. 이처럼 인터페이스데이터 타입으로 선언하면서 각 인터페이스가 가진 멤버들을 다양하게 구현 할 수 있는 특징이 있다.

 

● 예외

- 예외란? 비정상적인 부분을 통틀어서 말하는 것.

- 핵심 문법(try... catch...)

 

아래의 예시를 살펴보자.

위의 예시에서는 try내의 코드를 실행하다가 "계산결과는"까지 실행되고 catch를 찾아가서 매개변수로 받은 Exception이라는 데이터 타입의 클래스 객채인 e를 받아서 그 클래스 내의 getMessage라는 메소드를 실행시킨다.

추가적으로 e객체메소드에서 getMessage 간단한 에러, printStackTrace 구체적인 에러 출력.

 

이 부분은 다중 try..catch..문이다. 각 에러에 따라서 다른 에러 메세지를 출력하므로 더 가독성이 뛰어나다. 그러나 여기서 주의 할 점은 catch(Exception e){}모든 에러를 포함하므로 제일 밑에 적어줘야 위의 catch들이 다 실행되고 마지막에 실행된다.

 

- Finally

try catch문에 finally를 붙이면 예외발생과는 전혀 상관없이 무조건 마지막에 실행되는 로직.

 

- Throw

예외처리 부분을 계속 상위 클래스로 넘겨서 처리함.

내 생각에 장점은 각 클래스에서 일어 날 수 있는 예외상황들을 모두 한 곳에 모아 처리하기 때문에 가독성이 좋음.

 

package org.opentutorials.javatutorials.exception;
import java.io.*;
class B{
    void run() throws IOException, FileNotFoundException{
        BufferedReader bReader = null;
        String input = null;
        bReader = new BufferedReader(new FileReader("out.txt"));
        input = bReader.readLine();
        System.out.println(input);
    }
}
class C{
    void run() throws IOException, FileNotFoundException{
        B b = new B();
        b.run();
    }
}
public class ThrowExceptionDemo {
    public static void main(String[] args) {
         C c = new C();
         try {
            c.run();
        } catch (FileNotFoundException e) {
            System.out.println("out.txt 파일은 설정 파일 입니다. 이 파일이 프로잭트 루트 디렉토리에 존재해야 합니다.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }   
}

Throw = B -> C -> main

 

- 예외의 종류

 

위의 도식표는 주요 예외 클래스의 관계도이다.

 

1. Throwable

이 클래스는 Error와 Exception의 공통된 조상 class이다. 그러나 직접적으로 우리가 사용하진 않는다.

 

2. Error

이 클래스는 JVM에 문제가 있을 경우 발생하는 예외이다. 예를 들면 프로세싱 중 메모리 부족 등이 있다.

그래서 해결하기 위해서는 메모리를 효율적으로 사용할 수 있도록 변경하는 방법이다.

 

3. Exception

하위 2가지 경우로 나뉜다.

  • checked 예외 - RuntimeException을 제외한 Exception의 하위 클래스
  • unchekced 예외 - RuntimeException의 하위 클래스

두 가지의 차이점은 예외 처리 필수냐 아니냐이다. checked는 예외처리 필수. unchekced는 해도 되고 안해도 된다.

따라서 잘 구분해서 예외 처리를 해줘야한다.

반응형