17 . 클래스 변수와 클래스 메소드
public static void main(String[] args) {
}
Java
복사
public은 접근 제한자, void는 반환 유형, main은 함수이름, 괄호 안은 파라미터
그렇다면 ,, static은 ???
static 키워드
함수에도 사용할 수 있고 변수에도 사용할 수 있다.
static 변수
static 변수 = 정적 변수 = 클래스변수 = 공용변수의 이름 모두가 static 변수를 의미한다.
static 변수의 접근 방법
•
클래스 내부 접근
◦
static 변수가 선언된 클래스 내에서는 이름만으로 직접 접근 가능
•
클래스 외부 접근
◦
private으로 선언되지 않으면 클래스 외부에서도 접근 가능
◦
접근 수준 지시자가 허용하는 범위에서 접근 가능
◦
클래스 또는 인스턴스의 이름을 통해 접근
<static 변수 코드로 이해해보기>
•
예제 1
AccessWay.num++; 코드에서
클래스 외부에서 클래스 이름을 통한 static 변수 접근이 가능함을 보여준다.
•
static 변수가 클래스 변수라는 이름도 가질 수 있다는 것을 보여준다.
jvm이 클래스들을 체크를하면서 객체가 생성되기 전에 static이 붙은 것들을 먼저 메모리에 올리기때문에 객체 생성 없이도 클래스 이름을 통한 접근이 가능하다.
•
static 변수는 객체 생성 없이도 접근이 가능하다.
•
예제 2
class InstCnt {
static int instNum = 0;
//int instNum = 0;
public InstCnt() {
instNum++;
System.out.println("인스턴스 생성: "+ instNum);
}
}
public class ClassVar {
public static void main(String[] args) {
InstCnt cnt1 = new InstCnt();
InstCnt cnt2 = new InstCnt();
InstCnt cnt3 = new InstCnt();
}
}
Java
복사
출력 :
인스턴스 생성: 1
인스턴스 생성: 2
인스턴스 생성: 3
Java
복사
static int instNum 이 static 변수로 선언이 되고 InstCnt객체를 만들 때마다 instNum의 값이 +1 되면서 각 객체의 인스턴스 변수로 instNum을 선언되는 것이 아닌 하나의 instNum변수를 공유하고 있음을 확인할 수 있다. 그래서 위의 코드와 같이 몇 개의 객체가 생성되었는지 확인할 때 활용할 수 있다.
•
static 변수는 메모리에 한 번 먼저 올려 공유하는 변수이므로 공유 변수의 이름을 가질 수 있다.
•
static은 메모리에 한번 올려놓고 공유하기 때문에 객체가 만들어 질 때 인스턴스 변수로 만들어지지 않는다.
•
예제 3
게임에서의 카드는 모두 높이, 너비 길이가 같다. 만약 배열로 52개의 카드를 생성하게 되었을 때, width 와 height이 static 변수가 아니었다면 객체의 인스턴스 변수로 생성되며 메모리 낭비가 일어난다. 이럴 때 width 와 height를 static 변수로 사용해서 값을 공유하면 메모리를 아낄 수 있다.
static의 활용 정리
•
Math.PI
public final class Math {
public static final double PI = 3.14159265358979323846;
}
Java
복사
우리가 사용하는 Math.PI에서 Math는 클래스고 PI 는 public static fianl double 변수이다.
3.14159265358979323846 값을 얻기 위해 Math(클래스명) .(dot) PI(변수명)으로 접근할 수 있는것으로 보아 PI는 static 변수임을 알 수 있다. 그리고 외부에서 자유롭게 접근이 가능하도록 public 이다.
•
System.out.println();
public static final PrintStream out = null;
Java
복사
System 크래스에 선언된 out이라는 변수도 static 변수다. System(클래스명) .(dot) println() (메소드명)으로 클래스 이름을 외부에서 바로 접근했으며, 또 외부에서 자유롭게 접근할 수 있도록 public 이다.
static 메소드
•
static 메소드 안에 인스턴스 변수는 올 수 없다.
•
static 함수를 사용하려면 static 변수가 있어야 사용할 수 있다.
위의 코드에서처럼 static 메소드 안에 인스턴스 변수가 있으면 컴파일 오류가 난다.
static 메소드는 프로그램 실행 시 메모리에 올라가는데, 인스턴스 변수는 객체가 생성이 될 때 할당 된다. 그러므로 static 메소드가 메모리에 올라가는 시점에 인스턴스 변수가 메모리에 존재하지 않기 때문에 사용할 수 없다.
static 키워드 총정리
1.
static은 변수, 메소드를 객체보다 먼저 메모리에 올려서 공유할 수 있도록 한다.
2.
static 메소드 안에는 인스턴스 변수가 올 수 없다.
15 . 예외처리
예외
예외처리
•
프로그램을 종료시킨다.
•
문제가 발생한 지점에 대한 정보를 전달한다.
•
문제가 발생한 에러의 내용을 전달한다.
a를 b로 나누는 과정에서 1을 0으로 나누게 되는 문제가 발생했다.
위의 console의 내용을 보면
ArithmeticException 문제가 발생했으며
/ by zero로 0으로 나눴다는 상세한 문제 사항을 전달한다.
TryCatchTest.java 파일에서 20 Line이라는 문제가 발생한 지점에 대한 정보도 전달한다.
(ArithmeticException은 예외의 내용을 담은 기본 클래스이다.)
예외 처리 방법 1
•
try 안에 에러가 발생할 수 있는 코드를 넣는다.
•
catch 안에 에러가 발생했을 시 수행해야 하는 코드를 넣는다.
•
finally 안에 무조건 수행해야 하는 코드를 넣는다.
< try - catch 구문 코드 진행 과정>
<try - catch 코드로 이해해보기>
public class TryCatchTest {
public static void main(String[] args) {
int a = 1;
int b = 0;
try {
b = a / b;
System.out.println("try 안 a = " + a);
} catch (Exception e) {
e.printStackTrace();
System.out.println("catch 안 a = " + a);
System.out.println("catch 안 b = " + b);
}
System.out.println("try catch 외부");
}
}
Java
복사
출력 :
java.lang.ArithmeticException: / by zero
catch 안 a = 1
catch 안 b = 0
at java_0928.TryCatchTest.main(TryCatchTest.java:10)
try catch 외부
Java
복사
- try 구문 : 안에서 a(1)을 b(0)으로 나누는 에러가 발생했고, System.out.println("try 안 a = " + a);코드가 실행되지 않고 바로 catch 구문으로 넘어갔다.
- catch 구문 : catch (Exception e) catch 괄호 뒤의 Exception이라는 클래스의 e 객체를 만들었는데, Exception 클래스는 모든 예외의 조상 클래스이다. 그리고 그 객체의 e를 만들어서 e의 메소드들로 예외를 처리할 것이라는 의미이다.
printStackTrace();메소드는 실행시켰을 때 try 구문에서 발생하는 에러의 내용을 뿌려주는 메소드이다. catch 구문 안에 넣어줌으로써 어떤 에러의 내용인지 확인할 수 있다.
JVM 내부적으로 나누는 수에 0이 들어오면 뿌리는 클래스가 ArithmeticException이다 .
e를 new()로 객체 생성을 안 했지만 JVM이 기본적으로 객체를 만들어 준다.
⇒ 다형성 때문이다. (Exception은 모든 예외처리 클래스의 조상)
예외 처리 방법 2
•
예외가 발생했을 때, 예외처리를 호출한 함수한테 맡기겠다는 뜻
위의 상황에서 에러가 났을 때 , throws로 예외처리를 main에게 넘기려 한다면,
main 함수 뒤에 throws 키워드와 발생할 수 있는 오류의 예외에 대한 클래스를 적어준다.
⇒ 오류가 생겼을 때, IOException을 호출한 main에서 예외처리를 하도록 떠넘기게 된다.
위처럼 main이 처리를 떠맡게 되었을 때는 JVM한테 IOException예외를 던지게 된다.
왜냐하면 main함수가 JVM을 호출하기 때문이다.
•
throws 예제
•
try 구문 안에서 md1 함수를 호출한다.
•
md1 함수는 IOException을 넘기겠다고 thows 키워드를 통해 명시했으며
md2를 호출한다.
•
md2 함수도 IOException을 넘기겠다고 thows 키워드를 통해 명시했으며
문제가 발생할 수 있는 내용의 코드가 적혀있다.
md1은 자신을 호출한 try로 예외를 넘기게 된다.
try 구문에서 발생한 오류는 catch 구문에서 처리하기 때문에 catch 구문의 코드가 실행된다.
catch 안에 e.printStackTrace()로 오류 내용이 console에 출력하면서 예외처리 구문이 작동한다.
예외 클래스 구분
•
Checked Exception – 반드시 개발자가 처리해야할 예외
•
Unchecked Exception – 반드시 개발자가 예외처리를 하지 않아도 되는 예외
(ArithmeticException 종류의 객체가 띄워주는 런타임 중에 나타나는 예외)
•
Error - 시스템 적인 에러라서 개발자가 처리할 수 없는 문제
RuntimeException 하위의 예외들은 Unchecked Exception이다.
•
Checked Exception 예시
IOException 발생 가능한 상황이라면
Checked Expetion이라서 강제적으로 예외처리를 해야 한다.
IOException(파일 입출력에 대한 예외)처리가 writer.close()와
writer = Files.newBufferedWritter(file) 에서도 예외처리가 강제적으로 필요함을 알 수 있다.