반응형

모든 출처와 저작권은 프로그래머스에 있습니다. 자바 공부 시 필요한 강의 노트를 검색하기 쉽게 한 페이지에 모아두었습니다.

 

자바 입문

자바 입문 가장 널리 쓰이는 프로그래밍 언어 Java로 프로그래밍의 기초를 다져보세요. 이 강의의 내용을 책으로 만나고 싶으시면 여기를 눌러 책 정보를 확인하세요. 강의를 다 들었는데, 지금

programmers.co.kr

 

자바란?

자바의 탄생

  • 1995년에 썬 마이크로시스템즈에서 발표한 객체지향 언어
  • 현재 썬 마이크로시스템즈는 오라클에 인수가 된 상태

자바의 특징

  • 쉬운 언어이다.
    • C와 C++언어의 문법을 기본으로 차용하여 개발된 언어
    • C와 C++ 이 가진 어려운 문법인 포인터와 다중 상속 제거
    • C와 C++에 비해 쉬운 언어이다.
  • 플랫폼에 독립적이다.
    • 자바는 JVM() 만 있으면 윈도우, 리눅스, 맥등 어떤 플랫폼에서도 실행이 가능
  • 객체지향 언어이다.
  • 메모리 관리를 자동으로 해준다.(가비지 콜렉터)

자바 개발환경 구축

2019년 01월 25일 안내사항

모종의 이유로 자바 설치 및 환경 설정에 실패하시는 분께서는 Online Java Compiler 등 클라우드 서비스를 이용해보세요.


파일 다운로드 및 설치

Windows

  • JDK 다운 로드 및 설치
    • http://www.oracle.com/technetwork/java/index.html -> Java SE링크 클릭 -> JDK다운로드 링크 클릭 ->라이센스를 동의 한 후 운영체제에 맞는 JDK를 다운로드 (32비트 윈도우 운영체제-Windows x86을, 64비트 윈도우 운영체제- Windows x64)
    • 다운로드 후 설치
  • 환경변수 설정(윈도우 버전별 환경변수 메뉴 여는 방법 클릭)
    • JAVA_HOME
      • JDK가 설치된 경로 지정
    • Path
      • 윈도우의 기존 Path에 수정
    • CLASSPATH
      • 자바가 실행될 때는 모든 것들이 클래스 단위로 실행된다. 클래스를 찾는 위치라고 생각하면 된다.
  • 이클립스 다운로드 및 설치
    • http://www.eclipse.org 에서 운영체제에 맞는 버전을 다운로드 (현재 Neon이 최신버전입니다.)

OS X

OS X에는 java가 기본으로 설치되어 있기 때문에 이클립스만 설치합니다.

  • 이클립스 다운로드 및 설치
    • http://www.eclipse.org에서 운영체제에 맞는 버전을 다운로드 (현재 Neon이 최신버전입니다.)

사이드바에 응용프로그램이 보이지 않는 경우 : Finder환경설정 - 사이드바 - 즐겨찾기에 응용프로그램에 체크


자바 개발순서

2019년 06월 18일 안내사항

모종의 이유로 자바 설치 및 환경 설정에 실패하시는 분께서는 Online Java Compiler 등 클라우드 서비스를 이용해보세요.


자바 개발순서

  1. 소스 작성
  2. 작성한 소스 컴파일
  3. 컴파일한 소스를 JVM을 이용하여 실행

따라해 보기

  • 소스 작성
    • HelloWorld.java 파일을 c:\tmp 디렉토리에서 작성
    • 자바는 파일 이름 중요! 대소문자를 구별하니 잘 입력해 주어야 합니다.
public class HelloWorld{
	public static void main(String args[]){
    	System.out.println("Hello World"); 
	} 
}
  • 컴파일
    • 윈도 콘솔을 실행 ( 윈도우 버튼 -> 실행 -> cmd를 입력한 후 엔터를 입력)
    • cd c:\tmp 로 이동합니다.
    • javac HelloWorld.java 로 컴파일 합니다.
  • 실행
    • java HelloWorld 로 실행
    • 화면에 HelloWorld가 출력되는 것을 확인

이클립스를 이용하여 똑같이 실행해 보기

  • eclipse.exe를 실행
  • 사용자 홈디렉토리 아래에 workspace 폴더를 지정
    (이클립스를 처음 실행하면 워크스페이스 경로를 물어봅니다. 워크스페이스란 이클립스로 작성한 프로젝트가 저장되는 경로입니다. )
  • first 프로젝트 생성
  • 소스 작성
    • src폴더에서 HelloWorld.java파일 생성
    • 앞에서 만들었던 파일과 똑같은 파일을 HelloWorld.java파일로 작성
    • 워크스페이스 경로를 파일탐색기로 열어보면 src폴더에 HelloWorld.java파일 확인 가능
  • 컴파일
    • bin폴더를 열어보면 HelloWorld.class파일 생성되어있음 (이클립스는 소스파일에 문제가 없다면 자동으로 컴파일하여 bin폴더에 클래스를 만들게 됩니다.)
  • 실행
    • 클래스를 선택한 후 우측버튼을 클릭하고 자바 어플리케이션을 실행하는 메뉴를 선택

주석문

주석이란, 프로그램의 코드와 실행에는 영향을 주지 않는 문장

주석의 종류

  • 구현 주석
    • 행단위 주석 (// 를 해주면, 해당 행이 주석 처리됨 )
    • 블럭단위 주석 (/* 주석으로 사용할 내용 */ )
  • 문서화 주석
    • /** 문서에 포함할 내용을 작성함 */
    • 문서화 주석은 클래스, 인터페이스 그리고 멤버 당 하나씩 가질 수 있고, 선언 바로 전에 작성
    • 문서화 주석 예
import java.io.*;

/**
* <h1>Add Two Numbers!</h1>
* The AddNum program implements an application that
* simply adds two given integer numbers and Prints
* the output on the screen.
* <p>
* <b>Note:</b> Giving proper comments in your program makes it more
* user friendly and it is assumed as a high quality code.
*
* @author  Zara Ali
* @version 1.0
* @since   2014-03-31
*/
public class AddNum {
   /**
   * This method is used to add two integers. This is
   * a the simplest form of a class method, just to
   * show the usage of various javadoc Tags.
   * @param numA This is the first paramter to addNum method
   * @param numB  This is the second parameter to addNum method
   * @return int This returns sum of numA and numB.
   */
   public int addNum(int numA, int numB) {
      return numA + numB;
   }

   /**
   * This is the main method which makes use of addNum method.
   * @param args Unused.
   * @return Nothing.
   * @exception IOException On input error.
   * @see IOException
   */
   public static void main(String args[]) throws IOException
   {

      AddNum obj = new AddNum();
      int sum = obj.addNum(10, 20);

      System.out.println("Sum of 10 and 20 is :" + sum);
   }
}

변수

변수

변수란 값을 저장할 수 있는 메모리의 공간을 의미한다.

변수의 선언

  • 타입 변수이름;
    • int count; ( 정수 값을 담을 수 있는 count라는 이름의 변수를 선언)
    • double average; ( 실수 값을 담을 수 있는 average 라는 변수를 선언)
  • 명명규칙.
    • 변수의 이름을 정할 때 자바 언어에서 정해놓은 규칙
  • 식별자 (identifier)는 클래스, 메소드, 변수 등 다양한 대상에 대해 이름이 붙여지는 경우. 그 이름을 뜻 함

java 식별자 명명 규칙

  • 하나 이상의 글자로 이루어져야 함
  • 첫 번째 글자는 문자 이거나 '$', '_'이어야 함
  • 두번재 이후의 글자는 숫자, 문자, '$', '_'이어야 함
  • '$', '_' 이외의 특수문자 사용 불가능
  • 길이 제한이 없음
  • 키워드는 식별자로 사용할 수 없음
  • 상수 값을 표현하는 단어 true, false, null은 식별자로 사용할 수 없음

변수 명명 관례

  • 첫 번째 문자가 소문자인 명사로 정함
  • 여러 단어로 구성된 이름의 경우 두번째 단어부터 첫글자를 대문자로 함
  • '_'을 쓰지 않음
    • 규칙은 반드시 지켜야 한다. 지키지 않으면 컴파일시 에러가 발생함.
    • 관례는 지키지 않아도 컴파일에러가 발생하지는 않지만, 약속이기 때문에 지켜주는것이 좋다.

변수의 사용

  • 변수명 = 값;
    • count = 10; (count 라는 int형 변수에 정수값 10을 담습니다.)
    • count = 20; (count 라는 int형 변수에 정수값 20을 담습니다. 원래 담겨있던 10은 없어집니다. 변수는 값이 얼마든지 변할 수 있습니다.)
    • average = 11.1 (average라는 double형 변수에 실수 값 11.1 을 담습니다. )

상수

상수

상수(常數)란 수식에서 변하지 않는 값을 의미한다.

상수의 선언

  • final 상수타입 상수명;
    • final int J;

상수의 사용

  • 상수명 = 값;
    • J = 10; (J에는 값을 담을 수 있는 기회가 단 한 번만 허락됨)

상수 명명 관례

  • 대문자로만 구성된 명사로 정함
  • 여러 단어로 구성된 이름의 경우 단어 사이에 '_'을 써서 구분함.

상수를 사용해야 하는 경우

  • 값이 변하면 위험한 경우에 상수를 사용
  • 값만 봤을때 무엇을 의미하는지 쉽게 파악할 수 없는 값에도 값 자체를 사용하기 보다는 상수를 사용

기본형 타입

기본형

기본형 타입은 가장 기본이 되는 데이터 타입으로써 정수형, 실수형, 문자형, 불린형을 의미한다.

논리형

  • 논리형은 크기가 1byte이고 true와 false 중에 한 가지 값을 가질 수 있다.

문자형

  • 문자형은 char로 2byte크기를 가집니다. 문자는 작은따옴표를 이용하여 한 글자를 표현할 수 있다.

정수형

  • 정수형은 정수를 표현하는 데이터 타입인데 표현할 수 있는 정수의 범위에 따라서 다양하게 제공된다.
  • 정수형에서 가장 자주 사용하는 int는 4바이트이다.
  • long형은 8byte크기를 가진다. int 보다 더 큰 범위의 정수를 표현하고 싶을때 사용한다.

실수형

  • 실수형은 float과 double형이 있다.
  • float은 4바이트, double은 8바이트로 double은 float보다 더 큰 범위의 실수를 표현할 수 있다.

리터럴

  • 컴퓨터 과학 분야에서 리터럴이란, 소스 코드의 고정된 값을 대표하는 용어다.
  • 리터럴은 일종의 값이다. true, false, 10, 11.1, a 등 이런 값 자체를 리터럴이라고 한다.

기본형 타입의 사용 방법

  • boolean isFun = true;
  • char c ='f';
  • int x = 59;
  • long big = 3456789L; (값을 적을때는 뒤에 소문자 l이나 대문자 L을 적어야 합니다.)
  • float f = 32.5f (float에 값을 대입할 때는 실수 뒤에 소문자 f나 대문자 F를 붙여야 합니다.)
  • double d = 23.34;

기본형 타입

기본형

기본형 타입은 가장 기본이 되는 데이터 타입으로써 정수형, 실수형, 문자형, 불린형을 의미한다.

논리형

  • 논리형은 크기가 1byte이고 true와 false 중에 한 가지 값을 가질 수 있다.

문자형

  • 문자형은 char로 2byte크기를 가집니다. 문자는 작은따옴표를 이용하여 한 글자를 표현할 수 있다.

정수형

  • 정수형은 정수를 표현하는 데이터 타입인데 표현할 수 있는 정수의 범위에 따라서 다양하게 제공된다.
  • 정수형에서 가장 자주 사용하는 int는 4바이트이다.
  • long형은 8byte크기를 가진다. int 보다 더 큰 범위의 정수를 표현하고 싶을때 사용한다.

실수형

  • 실수형은 float과 double형이 있다.
  • float은 4바이트, double은 8바이트로 double은 float보다 더 큰 범위의 실수를 표현할 수 있다.

리터럴

  • 컴퓨터 과학 분야에서 리터럴이란, 소스 코드의 고정된 값을 대표하는 용어다.
  • 리터럴은 일종의 값이다. true, false, 10, 11.1, a 등 이런 값 자체를 리터럴이라고 한다.

기본형 타입의 사용 방법

  • boolean isFun = true;
  • char c ='f';
  • int x = 59;
  • long big = 3456789L; (값을 적을때는 뒤에 소문자 l이나 대문자 L을 적어야 합니다.)
  • float f = 32.5f (float에 값을 대입할 때는 실수 뒤에 소문자 f나 대문자 F를 붙여야 합니다.)
  • double d = 23.34;

기본형 타입변환

기본형 타입(형)변환

형변환이란, 변수 또는 리터럴의 타입을 다른 타입으로 변환하는 것이다.

묵시적 형변환

  • 크기가 작은 타입을 크기가 더 큰 타입으로 바꿀 때에는 묵시적으로 형을 바꾸어 준다.
  • int x = 50000;
    long y = x;
  • 이를 암묵적 형변환 이라고도 한다.

명시적 형변환

  • 크기가 더 큰 타입을 작은 타입으로 바꿀 때에는 명시적으로 변환 해주어야 한다.
  • long x = 50000;
    //int y = x; (이렇게 묵시적으로 수행하면 컴파일러는 오류를 발생 시킨다.)
    int y = (int) x; (반드시 (타입) 으로 명시적으로 형을 바꾸어 주어야 한다.)
  • 이를 강제 형변환 이라고도 한다.

산술연산자

부호(+,-), 증감(++,--), +,-,*,/,%

  • 연산식 ** x = y + z;**
    • y와 z를 더한 값을 x에 대입한다는 것을 의미
    • =과 + 는 연산자 = 은 대입연산자 이고, + 산술연산자 이다.
    • y와 z 는 피연산자 이다.
    • x = y+ z 는 연산식이다.
  • 부호를 결정하는 부호 연산자
  • 산술 연산을 할 수 있는 산술 연산자
  • 1씩 증가하거나 감소 시키는 증감연산자
  • 피 연산자가 1개인 연산자는 단항 연산자
    • 부호 연산자와, 증감연산자는 단항 연산자 이다.
 //부호 연산자 
    int i1 = -5;
    int i2 = +i1;
    int i3 = -i1;

    //증감 연산자 
    int i4 = ++i3;
    int i5 = i3++;
    int i6 = --i3;
    int i7 = i3--;
  • 피연 산자 하나로 연산할 수 없는 연산자 이항 연산자
	int i = 5;
    int j = 2;
  • 2개의 변수 이용한 산술 연산
    System.out.println(i +  j);
    System.out.println(i -  j);
    System.out.println(i *  j);
    System.out.println(i /  j);  
    System.out.println(i %  j);

비교연산자

== , != , < , > , <= , >=

  • 비교 연산자의 결과는 boolean이다.
    int i = 10; // = 대입연산자 
    int j = 10;    

    // i 와 j 가 같은지 비교 하는 비교 연산자           
    System.out.println(i == j ) 
    System.out.println(i == j ) 
    System.out.println(i != j );
    System.out.println(i < j);
    System.out.println( i <= j);
    System.out.println(i > j);
    System.out.println(i >= j);
  • 단순 대입 연산자
    • i = 10
    • 오른쪽에 있는 피연산자의 값을 왼쪽 피연산자의 변수에 저장
  • 복합 대입 연산자
    • 정해진 연산을 수행한 후에 결과를 대입
    i += 10; // i = i + 10;  과 같은 의미 

    System.out.println(i);  
    System.out.println(i -=5);
    System.out.println(i);

연산자우선순위

연산자 우선순위

  • 최우선연산자 ( ., [], () )
  • 단항연산자 ( ++,--,!,~,+/-   : 부정, bit변환>부호>증감)
  • 산술연산자 ( *,/,%,+,-,shift) < 시프트연산자 ( >>,<<,>>> ) >
  • 비교연산자 ( >,<,>=,<=,==,!= )
  • 비트연산자 ( &,|,,~ )
  • 논리연산자 (&& , || , !)
  • 삼항연산자 (조건식) ? :
  • 대입연산자 =,*=,/=,%=,+=,-=
    int a = 5;
    int b = 10;
    int c = 5
    System.out.println(  a - b * c );
    //결과는 -45가 나오게 됩니다
  • 곱셈이 우선순위가 높기 때문에 b와c를 먼저 곱한다. 그런 다음 a에서 b와 c를 곱한 값을 뺀다.
  • 비교연산자가 논리 연산자 보다 우선순위가 높다.
  • 단 증감 연산자일 경우에 전위 연산자인지 후위 연산자 인지에 따라서 우선 순위가 바뀔 수 있다.
            int a = 5; 
            System.out.println(++a - 5); 
            //결과는 1
  • 단항 연산자이면서, 전위 연산자인 ++ 가 먼저 연산된다. a가 6으로 바뀐 후 5 를 빼게 되므로 결과는 1
        int a = 5; 
        System.out.println(a++ - 5); 
        //결과는 0
        System.out.println(a); 
        //결과는 6
  • 단항 연산자이면서, 후위 연산자인 ++ 가 나중에 연산된다. a가 5인 상태에서 5를 뺀 후에 a++(a=a+1) 이 실행되므로 출력결과는 0

논리연산자 중 and 연산과 or 연산이 나왔을 경우 and 연산이 먼저 수행 됩니다.

 


if문

if 조건문

조건식의 연산 결과에 따라 블록 내부 문장의 실행 여부를 결정 할 수 있다.

  • if 문
    • 조건식이 true 일 경우에만 실행문이 실행된다.
    • if(조건식) 다음의 { } 를 생략할 수 있다. 하지만, 생략할 경우 if문에 포함되는 실행문은 단 한 줄만 포함된다.
        if(조건식){
            실행문;
            실행문;
        }
  • if - else 문
    • 조건식이 true일 경우 if 블록의 실행문이 실행되고, flase 일 경우 else 블록의 실행문이 실행된다.
        if(조건식){
            실행문;
            실행문;
        }else{
            실행문;
        }
  • if - else if - else문
    • 처음 if문의 조건식의 조건문이 true일 경우 처음 if문의 블록이 실행되고, false일 경우 다음 조건식의 결과에 따라 실행 블록이 달라진다.
    • else if 문의 수는 제한이 없다. 그러나 너무 많은 else if 문은 실행 속도를 느리게 한다.
    • 마지막 else 블록은 생략되도 상관없다.
        if(조건식){
            실행문;
            실행문;
        }else if(조건식){
            실행문;
        }else{
            실행문;
        }

논리연산자

논리 연산자

논리연산자는 논리곱(&&,&) 논리합(||,|), 배타적 논리합 () 논리부정(!) 연산을 수행한다. 논리 연산자의 피연산자는 블린 타입만 사용할 수 있다. 결과는 불린값이다.

    boolean b1 = true;
    boolean b2 = false;
    boolean b3 = true;
  • 논리곱 (&&, &) - 피연산자가 모두 true일 경우에만 연산 결과가 true 이다.
    • System.out.println(b1 && b2); -> b2가 false 이므로 결과는 false
    • System.out.println(b1 && b3); -> b1과 b2 모두 true 이므로 결과는 true
  • 논리합 (||,|) - 피연산자 중 하나만 true이면 연산 결과는 true 이다.
    • System.out.println(b1 || b2); -> b1 이 true이므로 결과는 true 이다.
  • 배타적 논리합 () -> 피연산자가 서로 다른 값일 경우만 연산 결과가 true 이다.
    • System.out.println(b1 ^ b2); -> b1은 true, b2는 false로 서로 다르므로 결과는 true 이다.
    • System.out.println(b1 ^ b3); -> b1, b3 모두 true로 서로 같다. 결과는false 이다
  • 논리 부정 (!) -> 피연산자의 논리값을 바꾼다. true는 false로 false는 true로 바꾼다.
    • System.out.println(!b1); -> b1 이 true 이므로 결과는 false 이다.
    • System.out.println(!b2); -> b1 이 false 이므로 결과는 true 이다.

삼항연산자

삼항 연산자

  • 조건식 ? 피연산자1 : 피연산자2
    • 조건식의 연산결과가 true 이면, 결과는 피연산자1이고, 조건식의 연산결과가 false 이면 결과는 피연산자2
        int b1 = (5>4) ? 50 : 40;
        //조건식이 true이므로 b1은 50이 된다.
  • 피연산자1, 피연산자2 에는 주로 값이 오지만, 경우에 따라 연산식이 올 수 있다.
  • 삼항 연산자가 익숙하지 않다면, if문으로 바꾸어 이용해도 좋다.
            int b2 = 0;
            if(5 > 4){
                b2 = 50;
            }else{
                b2 = 40;
            }

switch문

switch 문

switch문은 어떤 변수의 값에 따라서 문장을 실행할 수 있도록 하는 제어문이다.

  • switch문에서 사용하는 키워드는 switch, case, default, break 이다.
  • switch문
    switch(변수){
        case 값1 : 
            실행문; 
            break;
        case 값2 : 
            실행문; 
            break;  
        default;    
    }
	int value = 1;
    
    switch(value){
    	case 1:
        	System.out.println("1");
            break;
        case 2:
        	System.out.println("2");
            break;
        case 3:
        	System.out.println("3");
            break;
        default:
        	System.out.println("그 외의 숫자");
            break;
	}

value의 값이 1일 경우 1을 출력하고, 2일 경우는 2를 출력하고, 3일 경우는 3을 출력하고, 그 외에는 그 외의 숫자가 출력된다.

    case 1: 
        System.out.println("1");
    case 2:
        System.out.println("2");
    case 3 :
        System.out.println("3");
    default :
        System.out.println("그 외의 숫자");

break를 제거하면 value가 1일 경우 1이 출력되고 switch문장을 빠져나가는 것이 아니라
1,2,3, 그외의숫자가 연속해서 실행된다. break문장이 있을 경우와 없을 경우를 확실하게 구분할 수 있어야 합니다.

참고 하세요

JDK7이전에는 switch다음 괄호안에 정수타입의 변수만 올 수 있었습니다. 그런데 JDK7부터는 switch다음 괄호안에 문자열 타입의 변수도 올 수 있습니다.

    String str = "A";

    switch(str){
        case "A": 
            System.out.println("1");
        case "B":
            System.out.println("2");
        case "C" :
            System.out.println("3");
        default :
            System.out.println("그 외의 숫자");
    }

문자열의 값에 따라서 case블록의 내용이 출력되는 것을 알 수 있습니다.

 


while문

반복문

반복문은 실행문을 반복적으로 실행해야 할 때 사용 한다.

반복문의 종류는 while문, do-while문, for문 이 있다.

while문

  • 조건문의 실행 결과가 true일 동안 반복해서 실행한다.
    while(조건문){
        실행문; 
    }
  • 10번 반복하면서 0부터 9까지 출력하는 반복문
    int i = 0;  //while에서 사용할 변수를 선언

    while(i < 10){
        System.out.println(i);
        i++; //조건문을 원하는 만큼만 반복하고 빠져나가기 위한 부분 
    }
  • 1부터 100까지의 합을 while문을 이용하여 구현해 보도록 하겠습니다.
    public class WhileExam2 {
        public static void main(String[] args) {
            int total = 0; // i의 값을 누적할 변수를 선언합니다.
            int i = 1;
            while(i <= 100){
                total = total + i;
                i++;
            }
        }
    }

do while문

do-while문

  • while문의 경우 조건이 만족하지 않는다면 한번도 반복하지 않을 수 있다.하지만, do while문의 경우는 무조건 한번은 실행되는 반복문이다.
    do{
        실행문;
    }while(조건문);
  • do-while 실습
    import java.util.Scanner;

    public class DoWhileExam {

        public static void main(String[] args) {
            int value = 0;

            // Scanner는 java.util 패키지에 있는 클래스로써 키보드로 부터 값을 입력받는다던지 할 때 유용하게 사용할 수 있는 클래스입니다.
            Scanner scan = new Scanner(System.in);
            //위 처럼 작성하시면 키보드로부터 값을 입력받을 수 있는 Scanner객체가 생성됩니다. 

            do{
                value = scan.nextInt(); // Scanner클래스를 이용하여 키보드로 부터 숫자값을 입력받습니다.
                System.out.println("입력받은 수 : " + value);  
            }while(value != 10);  // 입력받은 값이 10이 아닐 경우에는 계속 반복합니다.

            System.out.println("반복문 종료");
        }
    }

for문

for 문

  • for반복문은 변수초기화, 조건식, 증감식이 한줄에 모두 있다.
    1. 초기화식은 최초 한 번만 수행합니다.
    2. 조건식을 수행해서 수행결과가 false라면 for 반복문을 빠져 나갑니다.
    3. 수행 결과가 true라면 실행문을 수행한다.
    4. 증감식을 수행한다.
    5. 2번부터 4번까지 반복적으로 수행한다.
    for(초기화식; 조건식; 증감식){
        실행문;
        실행문;
    }
  • for문을 이용하여 1부터 100까지의 합을 구하는 프로그램
    int total = 0; //1부터 100까지 합한 결과값을 담기위한 변수 선언 

    for(int i = 1; i <= 100; i++){ //1부터 100까지 반복하기 위한 for 반복문 

        total = total + i; // 1부터 100까지 반복해서 total 변수에 값을 누적  
    }
    System.out.println(total);  //결과값 출력
  • for문을 이용하여 1부터 100까지의 짝수의 합을 구하는 프로그램
    public class ForExam {

        public static void main(String[] args) {
            int total = 0;
            for(int i = 1; i <= 100; i++){
                if(i % 2 != 0){  // 2로 나눈 나머지가 0이 아니라는것은 홀수를 의미한다.  
                    continue; // 홀수일 경우 total = total + i; 문장이 실행되지 않으므로, 결과적으로 짝수만 더해준다. 
                }
                total = total + i;
            }
            System.out.println(total);
        }

    }

배열 만들기

1차원 배열

배열은 같은 데이터 타입을 가진 연속된 메모리 공간으로 이루어진 자료구조이다.

같은 데이터 타입을 가진 여러개의 변수가 필요할 때 사용한다.

  • 배열 생성 방법
    • 정수를 4개 저장 할 수 있는 배열을 생성 하는 방법
        int[] array1 = new int[4];
  • 배열에 값을 저장하는 방법
    array1[0] = 1;
    array1[1] = 2;
    array1[2] = 3;
    array1[3] = 4;
    //자바에서 배열의 인덱스는 0번 부터 사용한다. 4개짜리 배열은 0부터 3까지의 인덱스를 가지게 된다.
    //배열인덱스 0번부터 3번까지 차례로 1,2,3,4 값을 저장한다.
  • 배열에 저장된 값을 꺼내서 사용하는 방법
    int value = array1[2]; 
    //array1 이 참조하는 배열의 2번 인덱스에 해당하는 값 3을 꺼내서 int형 변수 value에 담는다. 
    System.out.println(array1[1]); 
    //array1 이 참조하는 배열의 1번 인덱스에 해당하는 값 2가 콘솔에 출력된다.
  • 선언과 동시에 초기화하는 방법
    int[] array2 = new int[]{1,2,3,4,5};
    //int 값을 5개저장 할 수 있는 배열이며, 해당 배열에는 1,2,3,4,5가 순서대로 저장되게 된다.

배열 사용하기

for 반복문을 이용해서 배열 사용하기

  • 배열에 접근할때에는 인덱스를 통해서 접근한다.
    int[] iarray = new int[100];
    iarray[0] = 1; 
    iarray[1] = 2;
  • 배열에 0번째 인덱스 부터 시작해서 1부터 100까지 넣기
    • 정수를100개 저장 할 수 있는 배열을 생성
    int [] iarray = new int[100];
  • 배열의 길이를 알아내는 방법
	irray.length
    // 배열을 참조하는 레퍼런스 변수 .length 하면 해당 배열의 길이를 리턴한다.
  • 배열에 1부터 100까지 값넣기
    //배열에 값을 반복적으로 넣어야 하므로, for 반복문을 이용한다. 
    for(int i = 0; i < iarray.length; i++){ 
    //배열의 인덱스는 0부터 시작하므로, 0부터 배열의 길이보다 하나 작을때까지 반복하면 배열의 크기만큼 반복할 수 있다. 
            iarray[i] = i + 1;  
    //배열의 인덱스는 0부터인데 넣고 싶은 값은 1부터 사용해야하므로, 인덱스에 1을 더해준 값을 넣어준다. 
    }
  • 배열에 저장된 값을 모두 더해주기
    int sum = 0; 
    //값을 누적하기위한 변수는 반복문 밖에서 선언한다. 

    for(int i = 0; i< iarray.length; i++){  
    // 배열의 크기만큼 반복한다.         

        sum = sum + iarray[i];
        //반복문 밖에서 선언한 변수에 반복적으로 값을 누적한다. 
    }

    System.out.println(sum);
    //배열에 들어있는 모든 값 누적한 변수를 출력한다.

 


2차원배열

2차원 배열

2차원 배열이란 배열의 배열이다.

  • 2차원 배열 생성 방법
    • 정수를 4개씩 담을 수 있는 배열이 3개 생성된다.
	int[][] array4 = new int[3][4];
  • 2차원 배열에 값을 저장하는 방법
    • 만약 array4[1] = 10 ; 이렇게 사용하면 오류!!
    • array4[1] 은 또 다른 1차원 배열을 가리킬 수 있는 참조형 변수이기 때문에 값을 담을수는 없다.
	array4[0][0] = 10;
  • 가변크기의 2차원 배열을 생성하는 방법
	int[][] array5 = new int[3][];
    // 위와 같이 선언하면 array5는 3개짜리 배열을 참조한다. 3개짜리 배열은 아직 참조하는 배열이 없다는 것을 의미
    
    array5[0] = new int[1]; //정수를 하나 담을 수 있는 배열을 생성해서 array5 의 0 번째 인덱스가 참조한다.  
    array5[1] = new int[2]; //정수를 두개 담을 수 있는 배열을 생성해서 array5 의 1 번째 인덱스가 참조한다.  
    array5[2] = new int[3]; //정수를 세개 담을 수 있는 배열을 생성해서 array5 의 2 번째 인덱스가 참조한다.
  • 선언과 동시에 초기화하는 방법
	int[][] array6 = {{1}, {2,3}, {4,5,6}};
    //위와 같이 선언할 경우 array6[0][0] 는 1이다. array6[1][0]은 2이다.

for each

자바 1.5 버전부터 추가된 foreach 구문

	int[] iarr = {10,20,30,40,50};
    
    for(int value:iarr){
    	System.out.println(value);
    }

클래스 선언

클래스

자바는 객체를 만들기 위해 반드시 클래스를 먼저 만들어야 한다. 클래스는 객체를 만들기 위한 일종의 틀이다.

  • 붕어빵이 객체라면, 붕어빵 틀은 클래스
  • 자동차 클래스 생성
	public class Car{
    
    }
  • Car.java란 파일을 만든다.
  • 저장을 하면 이클립스는 컴파일하여 디스크에 Car라는 클래스를 생성한다.
  • 자동차 클래스가 생성되었다고 해서 자동차가 만들어진 것은 아니다.

Car객체 생성하기 (자동차 만들기)

	public class CarExam{
    	public static void main(string args[]){
        	Car c1 = new Car();
            Car c2 = new Car();
        }
    }
  • new 연산자는 new 연산자 뒤에 나오는 생성자를 이용하여 메모리에 객체를 만들라는 명령.
  • 메모리에 만들어진 객체를 인스턴스(instance)라고도 한다.
  • 이렇게 만들어진 객체를 참조하는 변수가 c1 , c2 이다.
  • 위의 코드가 실행되면 Car라는 객체가 2개가 만들어지고 각각의 객체를 참조하는 c1과 c2변수가 선언됩니다.

참조타입

참조형 타입은 기본형 타입을 제외한 모든 타입입니다. 앞서 배웠던, 배열도 참조형이고, 클래스도 모두 참조 타입이다

  • 참조형 변수
    • String str = new String("hello");
      • str 변수 앞에 기본형 타입이 아닌 String클래스가 적혀있다.
      • 이퀄(=)뒤에는 new 다음에 생성자라는 것이 있다.
      • new 라는 키워드는 객체를 메모리에 올려준다. 이렇게 메모리에 올라간 객체를 인스턴스라고 말한다.
  • 메모리에 올라간 인스턴스를 가리키는 변수, 참조하는 변수, 레퍼런스 하는 변수가 str 이다. 참조한다. 레퍼런스 한다라는 것은 변수가 인스턴스를 가지고 있는게 아니라 말그대로 가리킨다는 의미이다.
  • str이라는 변수에는 메모리의 위치 값이 저장되는 것이다. 메모리의 위치값이 저장된다고 하더라도, 어떤 메모리에 저장되는지 그 정보를 알 수 있는 방법은 없다. 그렇기 때문에 str변수는 String 인스턴스를 참조한다라고만 아시면 된다.
  • 앞으로 배울 클래스들은 모두 참조형이다.

String클래스

String 클래스

문자열을 표현하는 자바에서 가장 많이 사용하는 클래스

자바 인스턴스 생성 방법

  1. new연산자를 이용하지 않고 인스턴스를 만드는 경우

String str1 = "hello";
String str2 = "hello";
  • "hello"라는 문자열이 메모리 중에서 상수가 저장되는 영역에 저장된다. 상수는 변하지 않는 값을 의미.
  • String str2 = "hello"; 이 문장이 실행될 때에 hello 라는 문자열 상수는 이미 만들어져 있으므로 str1이 참조하는 인스턴스를 str2도 참조한다.

  2 .new연산자를 이용해서 인스턴스를 만드는 경우

    String str3 = new String("hello");
    String str4 = new String("hello");
  • new연산자를 이용하여 인스턴스를 만들면 인스턴스는 무조건 새롭게 만들어진다.
  • String str4 = new String("hello"); 이 문장이 실행될때도 새롭게 만들게 되므로, str3 과 str4는 서로 다른 인스턴스를 참조한다.
    if(str1 == str2){  // 같은 인스턴스를 참조하므로 결과는 true 
        System.out.println("str1과 str2는 같은 레퍼런스입니다.");
    }

    if(str1 == str3){  // str1과 str3은 서로 다른 인스턴스를 참조하므로 결과는 false 
        System.out.println("str1과 str3는 같은 레퍼런스입니다.");
    }

    if(str3 == str4){  // str3과 str4는 서로 다른 인스턴스를 참조하므로 결과는 false 
        System.out.println("str3과 str4는 같은 레퍼런스입니다.");
  • 참조변수끼리 == 로 비교하면 서로 같은 것을 참조하는지 비교한다.
  • String은 다른 클래스와 다르게 new를 사용하지 않고 사용할 수 있다. 메모리를 아끼려면 String은 new를 사용하지 않고 사용하는 것이 좋다.
  • String은 불변 클래스이다. 불변이란 String이 인스턴스가 될때 가지고 있던 값을 나중에 수정할 수 없다.
  • String은 문자열과 관련된 다양한 메소드를 가지고 있다. 메소드를 호출한다 하더라도 String은 내부의 값이 변하지 않는다.
  • String이 가지고 있는 메소드중 String을 반환하는 메소드는 모두 새로운 String을 생성해서 반환한다.
    String str5 = "hello world";
    String str6 = str5.substring(3);
  • substring은 문자열을 자른 결과를 반환하는 메소드이다. 해당 코드가 실행되어도 str5는 변하지 않는다.
  • str6은 str5가 가지고 있는 문자열 중 3번째 위치부터 자른 결과 즉 새로운 String을 참조하게 된다.

필드(field)선언

자동차는 자동차 이름, 자동차 번호를 가지고 있고, 자동차는 달리고 멈추는 기능이 있다. 여기에서 가지고 있는 것을 속성이라고 한다. 자바에서는 이러한 속성을 필드(Field)라는 용어로 사용한다.

  • 이름과 번호를 필드로 가지고 있는 Car클래스 선언
	public class Car{
    String name;
    int number;
    }
  • Car 클래스를 인스턴스화 하기
    Car c1 = new Car();
    Car c2 = new Car();
    //Car라는 인스턴스가 메모리에 2개 만들어 진다. 객체별로 name과 number라는 속성을 가진다.
  • 속성 이용하기
    • 참조 변수 다음에 나오는 점(dot)은 참조변수가 참조하는 객체가 가지고 있는 것을 사용할 때 사용
    //c1.name은  c1이 참조하는 객체의 name 을 의미.

    c1.name = "소방차";  //c1이 참조하는 객체의 name을 소방차로 설정 
    c1.number = 1234;   // c1.number = 1234란 c1이 참조하는 객체의 number를 1234 로 설정 

    c2.name = "구급차"  //c2가 가리키는 객체의name을 구급차로 설정
    c2.number = 1004;  //c2가 가리키는 객체의 number를 1004로 설정


    System.out.println(c1.name);  //콘솔에 c1이 참조하는 객체의 name 을 출력합니다. 
    System.out.println(c1.number); //콘솔에 c1이 참조하는 객체의 number 를 출력합니다. 

    String name = c2.name;   //c2가 참조하는 객체의 name 을 String 타입 변수 name 도 참조하게 합니다.

메소드란?

메소드

필드가 물체의 상태라면, 물체의 행동에 해당하는게 메소드다. car에 이름과 번호가 있기도 하지만, car는 앞으로 전진할수도 있고 후진하는 행동도 할 수 있다.

  • 메소드는 입력값이 있고, 그 입력값을 받아서 무언가 한 다음 결과를 도출해 내는 수학의 함수와 비슷한 개념이다.
  • 이때 입력값을 매개변수라고 하고,결과값을 리턴값이라고 합니다.
    • 인자( Argument ) 는 어떤 함수를 호출시에 전달되는 값을 의미한다.
    • 매개 변수( Parameter ) 는 그 전달된 인자를 받아들이는 변수를 의미한다.
  • 메소드란 클래스가 가지고 있는 기능이다. 클래스 안에 선언됩니다.

메소드(Method) 선언

다양한 형태의 메소드

  • 매개변수도 없고 리턴하는 것도 없는 형태의 메소드
    • 리턴하는 것이 없을 경우 void라고 작성합니다.
    public class MyClass{
        public void method1(){
            System.out.println("method1이 실행됩니다.");
        }
    }
  • 정수를 받아들인 후, 리턴하지 않는 메소드
    • 받아들이는 값은 어떤 타입이라도 상관없다.
    • 받아 들이는 값의 수는 여러개 일 수 있다. 여러개을 경우 콤마(,)로 구분한다.
    • 이번엔 정수를 받아들인 후, 리턴하지 않는 메소드입니다. 이것을 클래스에서 작성하면 다음과 같습니다.
    public class MyClass{       
        public void method2(int x){
            System.out.println(x + " 를 이용하는 method2입니다.");
        }
    }
  • 아무것도 받아들이지 않고, 정수를 반환하는 메소드
    • 리턴하는 값 앞에 return 이라는 키워드를 사용한다.
    • 메소드 이름 앞에는 리턴하는 타입을 적어준다.
    • 리턴타입은 하나만 사용할 수 있다. 리턴하는 타입은 어떤 타입이라도 상관없다.
    public int method3(){
        System.out.println("method3이 실행됩니다.");

        return 10;
    }
    //위 메소드가 실행되면, 콘솔에 'method3이 실행됩니다.' 를 출력하고, 이 메소드를 호출한 쪽에 10을 리턴한다.
  • 정수를 2개 매개변수로 받고, 아무것도 반환하지 않는 메소드
    public void method4(int x, int y){
        System.out.println(x + "," + y + " 를 이용하는 method4입니다.");
    }
  • 정수를 한개 받아들인 후, 정수를 반환하는 메소드
public class MyClass{
    public void method(){
        System.out.println("method1이 실행됩니다.");
    }

    public void method2(int x){
        System.out.println(x + " 를 이용하는 method2입니다.");
    }

    public int method3(){
        System.out.println("method3이 실행됩니다.");

        return 10;
    }

    public void method4(int x, int y){
        System.out.println(x + "," + y + " 를 이용하는 method4입니다.");
    }

    public int method5(int y){
        System.out.println(y + " 를 이용하는 method5입니다.");
        return 5;
    }
}

메소드 사용해보기

메소드의 사용

MyClass

    public class MyClass{
        public void method(){
            System.out.println("method1이 실행됩니다.");
        }

        public void method2(int x){
            System.out.println(x + " 를 이용하는 method2입니다.");
        }

        public int method3(){
            System.out.println("method3이 실행됩니다.");
            return 10;
        }

        public void method4(int x, int y){
            System.out.println(x + "," + y + " 를 이용하는 method4입니다.");
        }

        public int method5(int y){
            System.out.println(y + " 를 이용하는 method5입니다.");
            return 5;
        }
    }
  • 메소드를 사용하기 위해서는 메소드가 정의된 클래스인 MyClass 가 생성되어야 한다
  • 객체를 생성할 때는 new 연산자를 이용한다.
  • 메소드 사용할때는 생성된 클래스를 참조하는 레퍼런스변수.메소드명() 으로 사용할 수 있다.
    public class MyClassExam{
        public static void main(String args[]){
            MyClass my1 = new MyClass(); //메소드가 정의된 클래스 생성 

            my1.method1();   //MyClass에서 정의해 놓은 메소드 method1() 를 호출한다.       

            my1.method2(10);

            int x = my1.method3();

            System.out.println("method3 이 리턴한 " + x + " 입니다.");

            my1.method4(10,100);

            int x2 = my1.method5(50);

            System.out.println("method5 가 리턴한 " + x2 + " 입니다.");

        }
    }

String클래스의 메소드

String Class가 제공하는 메소드 이용하기

  • 문자열 길이 구하기
    • str.length()는 str이 참조하는 문자열의 길이를 구해서 int 타입으로 리턴해주는 메소드 이다.
    System.out.println(str.length());  //str
  • 문자열 붙히기 (concat)
    • str.concat("world") 메소드는 str 이 참조하는 문자열 hello 에다가 메소드의 인자로 들어온 문자열 world 를 붙혀서 String 타입으로 리턴하는 메소드다.
    • String Class는 불변 클래스로, 메소드가 수행되면, 새로운 문자열을 만든다. 그러므로, 원래 클래스는 변하지 않는다.
    String str = new String("hello");

    System.out.println(str.concat(" world"));  //출력결과는 hello world 
    System.out.println(str);  //출력결과는 hello
  • 문자열 자르기 (subString)
    • str.subString(1,3) 은 str이 참조하는 문자열을 인덱스 1번부터 3번까지 자른 결과이다.
    • str.subString(2) 은 str이 참조하는 문자열을 2번 인덱스부터 마지막까지 자른 결과를 의미한다.
    • 문자열의 인덱스는 0번 부터 시작한다.
    System.out.println(str.substring(1, 3)); //출력결과  el
    System.out.println(str.substring(2));   //출력결과 llo world

변수의 scope와 static

변수의 스코프

프로그램상에서 사용되는 변수들은 사용 가능한 범위를 가진다. 그 범위를 변수의 스코프라고 한다.

변수가 선언된 블럭이 그 변수의 사용범위이다.

    public class ValableScopeExam{

        int globalScope = 10;   // 인스턴스 변수 

        public void scopeTest(int value){   
            int localScope = 10;
            System.out.println(globalScope);
            System.out.println(localScpe);
            System.out.println(value);
        }
    }
  • 클래스의 속성으로 선언된 변수 globalScope 의 사용 범위는 클래스 전체 이다.
  • 매개변수로 선언된 int value 는 블럭 바깥에 존재하기는 하지만, 메서드 선언부에 존재하므로 사용범위는 해당 메소드 블럭 내이다.
  • 메소드 블럭 내에서 선언된 localScope 변수의 사용범위는 메소드 블럭 내이다.

main메소드에서 사용하기

  • 같은 클래스 안에 있는데 globalScope 변수를 사용 할 수 없다.
  • main은 static한 메소드이다. static한 메서드에서는 static 하지 않은 필드를 사용 할 수 없다.
    public class VariableScopeExam {
        int globalScope = 10; 

        public void scopeTest(int value){
            int localScope = 20;            
            System.out.println(globalScope);
            System.out.println(localScope);
            System.out.println(value);
        }   
        public static void main(String[] args) {
            System.out.println(globalScope);  //오류
            System.out.println(localScope);   //오류
            System.out.println(value);        //오류  
        }   
    }

static

  • 같은 클래스 내에 있음에도 해당 변수들을 사용할 수 없다.
  • main 메소드는 static 이라는 키워드로 메소드가 정의되어 있다. 이런 메서드를 static 한 메소드 라고 한다.
  • static한 필드(필드 앞에 static 키워드를 붙힘)나, static한 메소드는 Class가 인스턴스화 되지 않아도 사용할 수 있다.
    public class VariableScopeExam {
        int globalScope = 10; 
        static int staticVal = 7;

        public void scopeTest(int value){
            int localScope = 20;        
        }

        public static void main(String[] args) {
            System.out.println(staticVal);      //사용가능 
        }

    }

static한 변수는 공유된다.

  • static하게 선언된 변수는 값을 저장할 수 있는 공간이 하나만 생성된다. 그러므로, 인스턴스가 여러개 생성되도 static한 변수는 하나다.
    ValableScopeExam v1 = new ValableScopeExam();
    ValableScopeExam v2 = new ValableScopeExam();
    v1.golbalScope = 20;
    v2.golbalScope = 30; 

    System.out.println(v1.golbalScope);  //20 이 출력된다. 
    System.out.println(v2.golbalScope);  //30이 출력된다. 

    v1.staticVal = 10;
    v2.staticVal = 20; 

    System.out.println(v1.statVal);  //20 이 출력된다. 
    System.out.println(v2.statVal);  //20 이 출력된다.
  • golbalScope같은 변수(필드)는 인스턴스가 생성될때 생성되기때문에 인스턴스 변수라고 한다.
  • staticVal같은 static한 필드를 클래스 변수라고 한다.
  • 클래스 변수는 레퍼런스.변수명 하고 사용하기 보다는 클래스명.변수명 으로 사용하는것이 더 바람직하다고 하다.
    • VariableScopeExam.staticVal

열거형(enum)

자바는 열거타입을 이용하여 변수를 선언할 때 변수타입으로 사용할 수 있다.

  • 열거형은 JDK5에서 추가되었다.
  • JDK5 이전에는 상수를 열거형 대신 사용
    • 상수를 이용하는 방법
    public class EnumExam {
        public static final String MALE = "MALE";
        public static final String FEMALE = "FEMALE";

        public static void main(String[] args) {
            String gender1;

            gender1 = EnumExam.MALE;
            gender1 = EnumExam.FEMALE;                  
        }
    }

상수를 사용했때의 문제점

  • String으로 선언된 gender1 에는 MALE, FEMALE 둘 중 한가지 값을 갖기 원하는데, gender1의 type이 String 이기 때문에 gender1 = "소년"; 이렇게 수행 되어도 전혀 문제가 되지 않는다.
  • 실행할때 원했던 값인 MALE,FEMALE 이 아닌 다른 값이 들어오게 되므로 문제를 발생시킬 수 있다.

해결 방법

  • 이런 문제를 발생시키지 않게 하기 위해서 열거형을 사용하시면 됩니다.
  • 열거형 정의 방법
    enum Gender{
        MALE, FEMALE;
    }
  • 열거형 사용 방법
    Gender gender2;

    gender2 = Gender.MALE;
    gender2 = Gender.FEMALE;

    //Gender타입의 변수에는 MALE이나 FEMALE만 대입이 가능. 다른 값은 저장할 수가 없다.

특정 값만 가져야 한다면 열거형을 사용하는 것이 좋다.


생성자

생성자

모든 클래스는 인스턴스화 될때 생성자를 사용한다.

생성자의 특징

  • 생성자는 리턴타입이 없다.
  • 생성자를 프로그래머가 만들지 않으면 매개변수가 없는 생성자가 컴파일할 때 자동으로 만들어진다.
  • 매개변수가 없는 생성자를 기본생성자라고 한다.
  • 생성자를 하나라도 프로그래머가 만들었다면 기본생성자는 자동으로 만들어지지 않는다.

생성자의 역할

  • 생성자가 하는 일은 객체가 될 때 필드를 초기화 하는 역할을 수행한다.
  • 자동차가 객체가 될때 반드시 이름을 가지도록 하려면,Car클래스를 다음과 같이 만들어야 한다.
    public class Car{
        String name;
        int number;

        public Car(String n){
            name = n;
        }
    }
  • 위의 Car 클래스를 이용하여 Car 인스턴스를 생성하는 방법
    public class CarExam2{
        public static void main(String args[]){

            Car c1 = new Car("소방차");
            Car c2 = new Car("구급차");
            //Car c3 = new Car(); // 컴파일 오류가 발생합니다.

            System.out.println(c1.name);

            System.out.println(c2.name);
        }
    }
  • Car클래스는 기본 생성자를 가지지 않는다. 그래서 기본생성자로 Car 객체를 생성할 수 없다.

this

this

this는 현재 객체, 자기 자신을 나타낸다.

this 의 사용

    public class Car{
        String name;
        int number;

        public Car(String n){
            name = n;
        }
    }
  • Car클래스의 생성자 매개변수의 이름이 n 이다. n 이라는 변수명은 무엇을 의미하는지 쉽기 알수 없다.
  • n 으로 쓰기 보다는 name 으로 사용하는 것이 좋다.
    public Car(String name){
        name = name;
    }
  • 'name=name' 이라고 코드를 바꾸면, 가깝게 선언된 변수를 우선 사용하기 때문에 'name=name'이라는 코드는 매개변수의 name의 값을 매개변수 name에 대입하라는 의미가 된다.
  • 즉, 필드는 바뀌지 않습니다. 이런 경우 필드라는 것을 컴파일러와 JVM에게 알려주기 위해서 this키워드를 사용해야 한다.
    public Car(String name){
        this.name = name;
    }
  • 앞의 this.name은 필드 name을 말하고 =(이퀄) 뒤의 name은 매개변수를 의미한다.
  • 즉 매개변수의 값을 필드에 대입하라는 의미가 된다.

클래스 안에서 자기 자신이 가지고 있는 메소드를 사용할 때도 this.메소드명()으로 호출할 수 있다.


메소드 오버로딩

메소드 오버로딩

매개변수의 유형과 개수가 다르게 하여 같은 이름의 메소드를 여러 개 가질 수 있게하는 기술

메소드 오버로딩

  • 이름은 같지만 매개변수가 다른 메소드
    class MyClass2{
        public int plus(int x, int y){
            return x+y;
        }

        public int plus(int x, int y, int z){
            return x + y + z;
        }

        public String plus(String x, String y){
            return x + y;
        }
    }
  • 메소드 오버로딩은 매개변수 부분이 달라야 한다.
    public int plus(int i, int f){
        return i+f;
    }
  • 위처럼 변수명은 다르지만, 매개변수의 타입과 개수가 동일한 메소드를 또 정의 할 수는 없다.

오버로딩된 메소드 이용하기

  • 메소드의 인자에 어떤 값이 쓰이느냐에 따라서 각기 다른 메소드가 호출된다.
    public MethodOverloadExam{
        public static void main(String args[]){
            MyClass2 m = new MyClass2();
            System.out.println(m.plus(5,10));
            System.out.println(m.plus(5,10,15));
            System.out.println(m.plus("hello" + " world"));
        }
    }

생성자 오버로딩과 this

생성자 오버로딩

생성자의 매개변수의 유형과 개수가 다르게 하여 같은 이름의 생성자를 여러 개 가질 수 있다.

  • 생성자도 메소드와 마찬가지로 여러개를 선언할 수 있다.
  • 매개변수의 수와 타입이 다르다면 여러개의 생성자를 선언할 수 있다.
    public class Car{
        String name;
        int number;

        public Car(){

        }

        public Car(String name){
            this.name = name;
        }

        public Car(String name, int number){
            this.name = name;
            this.number = number;
        }
    }

오버로딩된 생성자 이용하기

    public class CarExam4{
        public static void main(String args[]){
            Car c1 = new Car();
            Car c2 = new Car("소방차");
            Car c3 = new Car("구급차", 1234);
        }
    }

자기 생성자 호출하는 this()

  • 기본생성자를 호출하였을 때 name을 "이름없음" , 숫자를 0으로 초기화 하기
    public Car(){
        this.name = "이름없음";
        this.number = 0;
    }
  • 위처럼 작성했을 경우 코드의 중복이 일어난다.
  • 자신이 가지고 있는 다른 생성자를 이용할 수 있다.
    public Car(){
        this("이름없음", 0);
    }
  • this괄호 열고로 시작하면 자신의 생성자를 호출하는 것이다.
  • 자기 자신의 생성자를 호출함으로써 비슷한 코드가 중복되서 나오는 것을 방지할 수 있다.

패키지

패키지(package)란 서로 관련이 있는 클래스 또는 인터페이스들을 묶어 놓은 묶음이다. 패키지를 사용함으로써 클래스들이 필요할 때만 사용될 수 있도록 하고, 클래스를 패키지 이름과 함께 계층적인 형태로 사용함으로써 다른 그룹에 속한 클래스와 발생할 수 있는 클래스 이름간의 충돌을 막아줌으로 클래스의 관리를 편하게 해준다.

패키지 정의방법

  • package이름은 보통 도메인 이름을 거꾸로 적은 후, 그 뒤에 프로젝트 이름을 붙여서 만든다. 물론, 프로젝트 이름 뒤에 또 다른 이름이 나올 수도 있다.
  • package이름은 폴더명 점 폴더명 점 폴더명 과 같은 형식으로 만들어진다. 각각의 폴더명은 숫자로 시작할 수 없다.
  • 도메인 이름이 8cruz.com 이고 프로젝트 이름이 javastudy 라면 com.eightcruz.javastudy.Hello 로 패키지를 지정 할 수 있다.
    • 도메인이 숫자로 시작되는데 패키지명은 첫글자에 숫자를 사용할 수 없으므로 적절하게 수정한다.
    • 도메인으로 사용하는 이유는 패키지가 중복되는것을 방지하기 위함이므로, 반드시 존재하는 도메인이 아니라도 상관없다.

이클립스에서 패키지 생성하기

  1. 소스폴더를 선택한 후 우측버튼을 클릭하여 패키지 생성을 선택한다.
  2. 패키지 이름에 kr.co.helloWorld.javastudy를 입력한다.
  3. 해당 패키지를 선택하고 Hello클래스를 작성한다.
    • 작성된 클래스 파일의 첫줄에 package com.eightcruz.javastudy.Hello; 생성된것을 볼 수 있다.
    • 패키지를 생성하는 예약어는 package 다.

패키지에 생성된 클래스 사용하기

  • java.lang패키지를 제외하고는 다른 패키지에 있는 클래스를사용하려면 import라는 구문을 적어줘야 한다.
  • import com.eightcruz.javastudy.Hello;
  • 위의 코드는 com.eightcruz.javastudy패키지 아래의 Hello클래스를 사용하겠다는 것을 컴파일러와 JVM에게 알리는 것이다.
  • 클래스 이름대신에 * 를 적어도 된다. import com.eightcruz.javastudy.*;

import 하지 않고 사용하는 방법

  • 만약 import를 하기 싫다면, 혹은 각기 다른 패키지에 존재하는 같은 이름의 클래스 파일을 사용해야 한다면 아래와 같이 이용한다.
    • com.eightcruz.javastudy.Hello hello = new com.eightcruz.javastudy.Hello(); 이렇게 사용한다.

상속

상속이란? 부모가 가진것을 자식에게 물려주는것을 의미한다.

  • 노트북은 컴퓨터의 한 종류다.
  • 침대는 가구의 한 종류다. 혹은 침대는 가구다.
  • 소방차는 자동차다.

이렇게 말할 수 있는 관계를 is a 관계 혹은 kind of 관계라고 한다.

Car 를 상속받은 Bus 를 class로 표현하는 방법

    public class Car{

    }

    public class Bus extends Car{

    }
  • 자바는 클래스 이름 뒤에 extends 키워드를 적고 부모클래스 이름을 적게 되면 부모 클래스가 가지고 있는 것을 상속받을 수 있게 된다.
  • 상속이란 부모가 가지고 있는 것을 자식이 물려받는 것을 말한다. 즉, 부모가 가지고 있는 것을 자식이 사용할 수 있게 된다.

부모클래스에 메소드 추가하기

  • Car에 run()메소드를 추가
    public class Car{
        public void run(){
            System.out.println("달리다.");
        }
    }
  • Car를 상속받은 Bus 사용
    public class BusExam{
        public static void main(String args[]){
            Bus bus = new Bus();
            bus.run();  
            //Bus class 는 아무런 코드를 가지지 않는다. 그럼에도 run 이라는 메소드를 사용하는데 문제가 발생되지 않는다. 
        }   
    }
  • Bus에 메소드 추가
    public class Bus extends Car{
        public void ppangppang(){
            System.out.println("빵빵");
        }       
    }
  • Bus는 Car에서 물려받은 run메소드와 ppangppang메소드를 사용할 수 있게 된다.
  • 부모가 가지고 있는 메소드외에 추가로 메소드를 선언하는 것을 확장하였다고 표현한다.

접근제한자

접근 제한자란 클래스 내에서 멤버의 접근을 제한하는 역할을 한다.

접근제한자의 종류

  • public
    • 어떤 클래스든 접근할 수 있다는 것을 의미
  • protected
    • 자기 자신, 같은 패키지, 서로 다른 패키지다 하더라도 상속받은 자식 클래스에서는 접근할수 있다는 것을 의미
  • private
    • 자기 자신만 접근할 수 있다는 것을 의미
  • 접근제한자를 적지 않으면 default접근 지정자
    • 자기자신과 같은 패키지에서만 접근할 수 있다는 것을 의미
    public class AccessObj{
        private int i = 1;
        int k = 2; // default접근 제한자
        protected int p2 = 4;
        public int p = 3;
    }
  • AccessObj를 사용하는 AccessObjExam
    • AccessObj의 필드 i 의 접근 제한자는 private이므로 다른 클래스인 AccessObjExam에서 접근할 수 없다.
    public class AccessObjExam{
        public static void main(String args[]){
            AccessObj po = new AccessObj();

            System.out.println(po.i); // 컴파일 오류가 발생합니다.
            System.out.println(po.k);
            System.out.println(po.p);
            System.out.println(po.p2);
        }
    }
  • AccessObj 와 다른 패키지에서 사용해보기
    • 패키지가 달라졌기때문에 default 접근제한자로 지정된 필드 k 와 protected 접근제한자로 지정된 필드 p2 도 접근할 수 없다.
    public class AccessObjExam{
        public static void main(String args[]){
            AccessObj po = new AccessObj();

            System.out.println(po.i); // 컴파일 오류가 발생합니다.
            System.lout.println(po.k);// 컴파일 오류가 발생합니다.
            System.lout.println(po.p);
            System.lout.println(po.p2);// 컴파일 오류가 발생합니다.
        }
    }
  • AccessObjExam을 AccesObj로 부터 상속받도록 수정한 후 사용해 보기
    • 패키지는 다르지만 상속관계에 있으므로 protected 접근제한자로 지정된 필드 p2에 접근할 수 있다.
    public class AccessObjExam extends AccessObj{
        public static void main(String[] args) {
            AccessObjExam obj = new AccessObjExam();
            System.out.println(obj.p);
            System.out.println(obj.p2);
            System.out.println(obj.k);// 컴파일 오류가 발생합니다.
            System.out.println(obj.i);// 컴파일 오류가 발생합니다.
        }
    }

추상클래스

추상 클래스란 구체적이지 않은 클래스를 의미한다. 독수리, 타조는 구체적인 새를 지칭하는데 새, 포유류 같은 것은 구체적이지 않다.

이런 것을 구현한 클래스를 추상 클래스라고 한다.

추상 클래스 정의하기

  • 추상 클래스는 클래스 앞에 abstract 키워드를 이용해서 정의한다.
  • 추상 클래스는 미완성의 추상 메소드를 포함할 수 있다.
    • 추상 메소드란, 내용이 없는 메소드 이다. 즉 구현이 되지 않은 메소드이다.
    • 추상 메소드는 리턴 타입 앞에 abstract라는 키워드를 붙여야 한다.
  • 추상 클래스는 인스턴스를 생성할 수 없다.
    public abstract class Bird{
        public abstract void sing();

        public void fly(){
            System.out.println("날다.");
        }
    }

추상 클래스를 상속받는 클래스 생성하기

  • 추상 클래스를 상속받은 클래스는 추상 클래스가 갖고 있는 추상 메소드를 반드시 구현해야 한다.
  • 추상 클래스를 상속받고, 추상 클래스가 갖고 있는 추상 메소드를 구현하지 않으면 해당 클래스도 추상 클래스가 된다.
    public class Duck extends Bird{
        @Override
        public void sing() {
            System.out.println("꽥꽥!!");
        }
    }

사용하기

  • Bird는 추상 클래스 이므로 객체를 생성할 수 없다.
    public class DuckExam { 
        public static void main(String[] args) {
            Duck duck = new Duck();
            duck.sing();
            duck.fly();

            //Bird b = new Bird();
        }   
    }

super와 부모생성자

class가 인스턴스화될 때 생성자가 실행되면서 객체의 초기화를 한다. 그 때 자신의 생성자만 실행이 되는것이 아니고, 부모의 생성자부터 실행된다.

부모 생성자

    public class Car{
        public Car(){
            System.out.println("Car의 기본생성자입니다.");
        }
    }

    public class Bus extends Car{
        public Bus(){
            System.out.println("Bus의 기본생성자입니다.");
        }

    }
  • 생성자 테스트
    public class BusExam{
        public static void main(String args[]){
            Bus b = new Bus();
        }
    }
  • 결과

Car의 기본생성자입니다.
Bus의 기본생성자입니다.

  • new 연산자로 Bus객체를 생성하면, Bus객체가 메모리에 올라갈때 부모인 Car도 함께 메모리에 올라간다.
  • 생성자는 객체를 초기화 하는 일을한다.
  • 생성자가 호출될 때 자동으로 부모의 생성자가 호출되면서 부모객체를 초기화 하게된다.

super

  • 자신을 가리키는 키워드가 this 라면, 부모들 가리키는 키워드는 super
  • super() 는 부모의 생성자를 의미한다.
  • 부모의 생성자를 임의로 호출하지 않으면, 부모 class의 기본 생성자가 자동으로 호출된다.
  • 아래 예제처럼 호출해보면 위에서 super()를 호출하지 않을때와 결과가 같다.
    public Bus(){
        super();
        System.out.println("Bus의 기본생성자입니다.");
    }

부모의 기본생성자가 아닌 다른 생성자를 호출하는 방법

  • 클래스는 기본 생성자가 없는 경우도 존재한다.
    public class Car{
        public Car(String name){
            System.out.println(name + " 을 받아들이는 생성자입니다.");
        }
    }
  • Car class가 위 처럼 수정되면, Bus생성자에서 컴파일 오류가 발생한다.
  • 부모가 기본생성자가 없기 때문에 컴파일 오류가 발생하게 되는 것이다.
  • 이런 문제를 해결하려면 자식 클래스의 생성자에서 직접 부모의 생성자를 호출해야 합니다.
    public Bus(){
        super("소방차"); // 문자열을 매개변수로 받는 부모 생성자를 호출하였다.
        System.out.println("Bus의 기본생성자입니다.");
    }

super 키워드는 자식에서 부모의 메소드나 필드를 사용할 때도 사용합니다.


오버라이딩

오버라이딩이란 부모가 가지고 있는 메소드와 똑같은 모양의 메소드를 자식이 가지고 있는 것이다. 즉 오버라이딩이란 메소드를 재정의 하는 것이다.

메소드 오버라이딩

  • Car 클래스를 상속받은 Bus 클래스는 부모클래스가 가지고 있는 run() 메소드를 잘 사용한다.
    //run 메소드를 가지고 있는 Car클래스 
    public class Car{
        public void run(){
            System.out.println("Car의 run메소드");
        }
    }

    //Car 를 상속받는 Bus 클래스 
    public class Bus extends Car{

    }

    public class BusExam{
        public static void main(String args[]){
            Bus bus = new Bus();
            bus.run();  //Car의 run메소드가 실행된다. 
        }
    }
  • Bus클래스에 부모가 가지고 있는 메소드와 모양이 같은 메소드를 선언
    public class Bus extends Car{
        public void run(){
            System.out.println("Bus의 run메소드");
        }
    }

    public class BusExam{
        public static void main(String args[]){
            Bus bus = new Bus();
            bus.run();  //Bus run메소드가 실행된다. 
        }
    }
  • BusExam을 실행해 보도록 하겠습니다. "Bus의 run메소드"가 출력된다.
  • 메소드를 오버라이드 하면, 항상 자식클래스에서 정의된 메소드가 호출된다.
  • 오버라이딩 한다고 해서 부모의 메소드가 사라지는 것은 아니다.
    • super 키워드를 이용하면, 부모의 메소드를 호출할 수 있다.
    public class Bus extends Car{
        public void run(){
            **super.run();**  // 부모의  run()메소드를 호출 
            System.out.println("Bus의 run메소드");
        }

클래스 형변환

부모타입으로 자식객체를 참조하게 되면 부모가 가지고 있는 메소드만 사용할 수 있다. 자식객체가 가지고 있는 메소드나 속성을 사용하고 싶다면 형변환 해야 한다.

형변환

    public class Car{
        public void run(){
            System.out.println("Car의 run메소드");
        }
    }

    public class Bus extends Car{
        public void ppangppang(){
            System.out.println("빵빵.");
        }

상속관계란 is a 관계라고 말했었습니다. "Bus는 Car다." 라는 관계가 성립되는 것이죠.
현실에서도 우리는 버스를 가리키면서 차다. 라고 말하곤 합니다.

  • 부모타입으로 자식객체를 참조할 수 있다.
    • 부모타입으로 자식객체를 참조하게 되면 부모가 가지고 있는 메소드만 사용할 수 있다.
    public class BusExam{
        public static void main(String args[]){
            Car car = new Bus();
            car.run();
            car.ppangppang(); // 컴파일 오류 발생
        }
    }
  • ppangppang()메소드를 호출하고 싶다면 Bus타입의 참조변수로 참조해야 한다.
    public class BusExam{
        public static void main(String args[]){
            Car car = new Bus();
            car.run();
            //car.ppangppang(); // 컴파일 오류 발생

            Bus bus = (Bus)car;  //부모타입을 자식타입으로 형변환 
            bus.run();
            bus.ppangppang();
        }
    }
  • 객체들 끼리도 형변환이 가능하다. 단 상속관계에 있었을 때만 가능하다.
  • 부모타입으로 자식타입의 객체를 참조할 때는 묵시적으로 형변환이 일어난다.
  • 부모타입의 객체를 자식타입으로 참조하게 할때는 명시적으로 형변환 해주어 한다. 단 이렇게 형변환 할때에는 부모가 참조하는 인스턴스가 형변환 하려는 자식타입일 때만 가능하다.

인터페이스 만들기

인터페이스: 서로 관계가 없는 물체들이 상호 작용을 하기 위해서 사용하는 장치나 시스템

  • 인터페이스 정의하는 방법
    • 추상 메소드와 상수를 정의 할 수 있다.
    public interface TV{
        public int MAX_VOLUME = 100;
        public int MIN_VOLUME = 0;

        public void turnOn();
        public void turnOff();
        public void changeVolume(int volume);
        public void changeChannel(int channel);
    }

인터페이스에서 변수를 선언하면 컴파일시 자동으로 아래와 같이 바뀐다.

    public static final int MAX_VOLUME = 100;
    public static final int MIN_VOLUME = 0;

인터페이스에서 정의된 메소드는 모두 추상 메소드이다. 위에서 선언된 모든 메소드는 컴파일 시에 다음과 같이 자동으로 변경된다.

    public abstract void on();
    public abstract void off();
    public abstract void volume(int value);
    public abstract void channel(int number);

추상클래스와 인터페이스 차이

 

추상 클래스 대신에 Interface를 쓸때가 있을까요? 그리고 그 반대의 경우도 있을까요?

일반적인 OOP질문인데요. Interface랑 추상클래스의 기본적인 사용에대한 일반적인 비교를 하고싶어요. 인터페이스를 사용하고자할때랑 추상클래스를 사용하고자할때의 차이를 알고싶어요!

hashcode.co.kr

하지만 인터페이스의 메소드 앞에 default를 붙이면 메소드를 구현할 수 있다.

차이는 상수변수 final로 선언되는 것이다. 그리고 더 찾아봐야 할텐데...


인터페이스 사용하기

  • 인터페이스 사용하는 방법
    • 인터페이스는 사용할때 해당 인터페이스를 구현하는 클래스에서 implements 키워드를 이용한다.
    public class LedTV implements TV{
        public void on(){
            System.out.println("켜다");
        }
        public void off(){
            System.out.println("끄다");   
        }
        public void volume(int value){
            System.out.println(value + "로 볼륨조정하다.");  
        }
        public void channel(int number){
            System.out.println(number + "로 채널조정하다.");         
        }
    }
  • 인터페이스가 가지고 있는 메소드를 하나라도 구현하지 않는다면 해당 클래스는 추상클래스가 된다.(추상클래스는 인스턴스를 만들 수 없음)
    public class LedTVExam{
        public static void main(String args[]){
            TV tv = new LedTV();
            tv.on();
            tv.volume(50);
            tv.channel(6);
            tv.off();
        }
    }
  • 참조변수의 타입으로 인터페이스를 사용할 수 있다. 이 경우 인터페이스가 가지고 있는 메소드만 사용할 수 있다.
  • 만약 TV인터페이스를 구현하는 LcdTV를 만들었다면 위의 코드에서 new LedTV부분만 new LcdTV로 변경해도 똑같이 프로그램이 동작할 것다. 동일한 인터페이스를 구현한다는 것은 클래스 사용법이 같다는 것을 의미한다.
  • 클래스는 이러한 인터페이스를 여러개 구현할 수 있다.

인터페이스의 default method

인터페이스의 default 메소드

JAVA 8이 등장하면서 interface에 대한 정의가 몇 가지 변경되었다.

default메소드

  • 인터페이스가 default키워드로 선언되면 메소드가 구현될 수 있다. 또한 이를 구현하는 클래스는 default메소드를 오버라이딩 할 수 있다.
    public interface Calculator {
        public int plus(int i, int j);
        public int multiple(int i, int j);
        default int exec(int i, int j){      //default로 선언함으로 메소드를 구현할 수 있다.
            return i + j;
        }
    }

    //Calculator인터페이스를 구현한 MyCalculator클래스
    public class MyCalculator implements Calculator {

        @Override
        public int plus(int i, int j) {
            return i + j;
        }

        @Override
        public int multiple(int i, int j) {
            return i * j;
        }
    }

    public class MyCalculatorExam {
        public static void main(String[] args){
            Calculator cal = new MyCalculator();
            int value = cal.exec(5, 10);
            System.out.println(value);
        }
    }
  • 인터페이스가 변경이 되면, 인터페이스를 구현하는 모든 클래스들이 해당 메소드를 구현해야 하는 문제가 있다. 이런 문제를 해결하기 위하여 인터페이스에 메소드를 구현해 놓을 수 있도록 하였다.

static메소드

    public interface Calculator {
        public int plus(int i, int j);
        public int multiple(int i, int j);
        default int exec(int i, int j){
            return i + j;
        }
        public static int exec2(int i, int j){   //static 메소드 
            return i * j;
        }
    }

    //인터페이스에서 정의한 static메소드는 반드시 인터페이스명.메소드 형식으로 호출해야한다.  

    public class MyCalculatorExam {
        public static void main(String[] args){
            Calculator cal = new MyCalculator();
            int value = cal.exec(5, 10);
            System.out.println(value);

            int value2 = Calculator.exec2(5, 10);  //static메소드 호출 
            System.out.println(value2);
        }
  • 인터페이스에 static 메소드를 선언함으로써, 인터페이스를 이용하여 간단한 기능을 가지는 유틸리티성 인터페이스를 만들 수 있게 되었다.

내부클래스

내부 클래스란 클래스 안에 선언된 클래스

어느 위치에 선언하느냐에 따라서 4가지 형태가 있을 수 있다.

  • 첫번째는 클래스 안에 인스턴스 변수, 즉 필드를 선언하는 위치에 선언되는 경우. 보통 중첩클래스 혹은 인스턴스 클래스라고 한다.
    • 내부에 있는 Cal객체를 생성하기 위해서는, 밖에는 InnerExam1의 객체를 만든 후에 InnerExam1.Cal cal = t.new Cal();과 같은 방법으로 Cal객체를 생성한 후 사용한다.
    public class InnerExam1{
        class Cal{
            int value = 0;
            public void plus(){
                value++;
            }
        }

        public static void main(String args[]){
            InnerExam1 t = new InnerExam1();
            InnerExam1.Cal cal = t.new Cal();
            cal.plus();
            System.out.println(cal.value);

        }
  • 두번째는 내부 클래스가 static으로 정의된 경우, 정적 중첩 클래스 또는 static 클래스라고 한다.
    • 필드 선언할 때 스태틱한 필드로 선언한 것과 같다. 이 경우에는 InnerExam2객체를 생성할 필요없이 new InnerExam2.Cal() 로 객체를 생성할 수 있다.
    public class InnerExam2{
        static class Cal{
            int value = 0;
            public void plus(){
                value++;
            }
        }

        public static void main(String args[]){
            InnerExam2.Cal cal = new InnerExam2.Cal();
            cal.plus();
            System.out.println(cal.value);

        }
    }
  • 세번째로는 메소드 안에 클래스를 선언한 경우, 지역 중첩 클래스 또는 지역 클래스라고 한다.
    • 메소드 안에서 해당 클래스를 이용할 수 있다.
    public class InnerExam3{
        public void exec(){
            class Cal{
                int value = 0;
                public void plus(){
                    value++;
                }
            }
            Cal cal = new Cal();
            cal.plus();
            System.out.println(cal.value);
        }


        public static void main(String args[]){
            InnerExam3 t = new InnerExam3();
            t.exec();
        }
    }
  • 네번재로는 익명클래스가 있다.

익명클래스

익명 중첩 클래스는 익명 클래스라고 보통 말하며, 내부 클래스이기도 하다.

    //추상클래스 Action 
    public abstract class Action{
        public abstract void exec();
    }

    //추상클래스 Action을 상속받은 클래스 MyAction

    public class MyAction extends Action{
        public void exec(){
            System.out.println("exec");
        }
    }

    //MyAction을 사용하는 클래스 ActionExam 
    public class ActionExam{
        public static void main(String args[]){
            Action action = new MyAction();
            action.exec();
        }
    }

    //MyAction을 사용하지 않고 Action을 상속받는 익명 클래스를 만들어서 사용하도록 수정해 보도록 하겠습니다.
    public class ActionExam{
        public static void main(String args[]){
            Action action = new Action(){
                public void exec(){
                    System.out.println("exec");
                }
            };
            action.exec();
        }
    }
  • 생성자 다음에 중괄호 열고 닫고가 나오면, 해당 생성자 이름에 해당하는 클래스를 상속받는 이름없는 객체를 만든다는 것을 뜻한다.
  • 괄호 안에는 메소드를 구현하거나 메소드를 추가할 수 있다. 이렇게 생성된 이름 없는 객체를 action이라는 참조변수가 참조하도록 하고, exec()메소드를 호출.
  • 익명클래스를 만드는 이유는 Action을 상속받는 클래스를 만들 필요가 없을 경우이다.
  • Action을 상속받는 클래스가 해당 클래스에서만 사용되고 다른 클래스에서는 사용되지 않는 경우이다.

이너 클래스(내부, 중첩, 네스티드), 로컬 클래스(지역, 지역 중첩, 로컬 네스티드), 익명 클래스, 람다식 사용 관련 자바 튜토리얼

 

 

When to Use Nested Classes, Local Classes, Anonymous Classes, and Lambda Expressions (The Java™ Tutorials >

The Java Tutorials have been written for JDK 8. Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available. See Java Language Changes for a summary of updated

docs.oracle.com


Exception

Exception

프로그램실행중 예기치 못한 사건을 예외라고 한다. 예외 상황을 미리 예측하고 처리할 수 있는데, 이렇게 하는 것을 예외 처리라고 한다.

    public class ExceptionExam {
        public static void main(String[] args) {
            int i = 10;
            int j = 5;
            int k = i / j;
            System.out.println(k);
            System.out.println(main 종료!!);
        }
    }
  • 위 코드에서 j를 0으로 바꾸면 Excption 발생
    • j를 0으로 바꾸면 ArithmeticException이 발생하면서 프로그램이 종료된다.
    • Java는 정수를 정수로 나눌때 0으로 나누면 안된다.0으로 나누면 오류가 발생하는 것입니다.
  • 예외 처리
    • 프로그래머는 j라는 변수에 0이 들어올지도 모르는 예외 상황을 미리 예측하고 처리할 수 있다.
  • 예외처리하는 문법
    • 오류가 발생할 예상 부분을 try라는 블록으로 감싼 후, 발생할 오류와 관련된 Exception을 catch라는 블록에서 처리한다.
    • 오류가 발생했든 안했든 무조건 실행되는 finally라는 블록을 가질 수 있다.
    • finally블록은 생략가능하다.
    public class ExceptionExam {
        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            try{
                int k = i / j;
                System.out.println(k);
            }catch(ArithmeticException e){
                System.out.println("0으로 나눌 수 없습니다. : " + e.toString());
            }finally {
                System.out.println("오류가 발생하든 안하든 무조건 실행되는 블록입니다.");
            }
        }
    }
  • 실행결과
    0으로 나눌 수 없습니다. : java.lang.ArithmeticException: / by zero

    오류가 발생하든 안하든 무조건 실행되는 블록입니다.
  • Exception 처리하지 않았을때는 프로그램이 강제 종료되었는데 catch라는 블록으로 Exception을 처리하니 강제종료되지 않고 잘 실행되는 것을 알 수 있다.
  • try블록에서 여러종류의 Exception이 발생한다면 catch라는 블록을 여러개 둘 수 있다.
  • Exception클래스들은 모두 Exception클래스를 상속받으므로, 예외클래스에 Exception을 두게 되면 어떤 오류가 발생하든지 간에 하나의 catch블록에서 모든 오류를 처리할 수 있다.

Throws

throws

throws는 예외가 발생했을때 예외를 호출한 쪽에서 처리하도록 던져준다.

    public class ExceptionExam2 {   
        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            int k = divide(i, j);
            System.out.println(k);
        }

        public static int divide(int i, int j){
            int k = i / j;
            return k;
        }
    }

정수를 매개변수로 2개를 받아들인 후 나눗셈을 한 후 그 결과를 반환하는 divide메소드
main메소드에서는 divide메소드를 호출

다음과 같이 divide메소드를 수정

    public class ExceptionExam2 {

        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            int k = divide(i, j);
            System.out.println(k);
        }

        public static int divide(int i, int j) throws ArithmeticException{
            int k = i / j;
            return k;
        }
    }

메소드 선언 뒤에 throws ArithmeticException 이 적혀있는 것을 알 수 있습니다. 이렇게 적어놓으면 divide메소드는 ArithmeticException이 발생하니 divide메소드를 호출하는 쪽에서 오류를 처리하라는 뜻입니다.

    package javaStudy;
    public class ExceptionExam2 {

        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            try{
                int k = divide(i, j);
                System.out.println(k);
            } catch(ArithmeticException e){
                System.out.println("0으로 나눌수 없습니다.");
            }

        }

        public static int divide(int i, int j) throws ArithmeticException{
            int k = i / j;
            return k;
        }

    }

클래스 말고 예외를 발생시키는 메소드 뒤에 붙여줘야 한다.


Exception 발생시키기

강제로 오류를 발생시키는 throw

throw는 오류를 떠넘기는 throws와 보통 같이 사용됩니다.

    public class ExceptionExam3 {   
        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            int k = divide(i, j);
            System.out.println(k);

        }       
        public static int divide(int i, int j){
            int k = i / j;
            return k;
        }   
    }
  • divide메소드는 2번째 파라미터의 값이 0일 경우 나누기를 할 때 Exception이 발생한다.

위의 코드를 에러가 발생하지 않게 수정

    public class ExceptionExam3 {
        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            int k = divide(i, j);
            System.out.println(k);      
        }

        public static int divide(int i, int j){
            if(j == 0){
                System.out.println("2번째 매개변수는 0이면 안됩니다.");
                return 0;
            }
            int k = i / j;
            return k;
        }
    }
  • j가 0일 경우 안된다는 메시지가 출력되도록 수정하고 0을 리턴.
  • 이렇게 할 경우 main메소드의 k변수는 0값을 가지게 되고 0을 출력하게 된다.
  • 0으로 나눈 결과는 0이 아니다. 0으로 반환하면 더 큰 문제가 발생할수도 있다.

에러도 발생하지 않고, 올바르지 않은 결과를 리턴하지 않도록 수정

    public class ExceptionExam3 {
        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            int k = divide(i, j);
            System.out.println(k);

        }       
        public static int divide(int i, int j) throws IllegalArgumentException{
            if(j == 0){
                throw new IllegalArgumentException("0으로 나눌 수 없어요.");
            }
            int k = i / j;
            return k;
        }   
    }
  • j가 0일 경우에 new연산자를 통하여 IllegalArgumentException 객체가 만들어 진다.
  • new 앞에 throw 는 해당 라인에서 익셉션이 발생한다는 의미이다.
  • 즉 그 줄에서 오류가 발생했다는 것이다. 0으로 나눌수 없습니다. 라는 오류가 발생한것이다.
  • Exception클래스 이름을 보면 아규먼트가 잘못되었기 때문에 발생한 오류라는 것을 알 수 있다.

divide 메소드를 호출 한 쪽에서의 오류 처리

  • divide 메소드 뒤에 throws IllegalArgumentException 은 해당 오류는 divide를 호출한 쪽에서 처리를 해야한다는 것을 의미한다.
    public class ExceptionExam3 {   
        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            try{
                int k = divide(i, j);
                System.out.println(k);
            }catch(IllegalArgumentException e){
                System.out.println("0으로 나누면 안됩니다.");
            }           
        }

        public static int divide(int i, int j) throws IllegalArgumentException{
            if(j == 0){
                throw new IllegalArgumentException("0으로 나눌 수 없어요.");
            }
            int k = i / j;
            return k;
        }   
    }

사용자 정의 Exception

사용자 정의 Exception

  • Exception 클래스를 상속 받아 정의한 checked Exception
    • 반드시 오류를 처리 해야만 하는 Exception
    • 예외 처리하지 않으면 컴파일 오류를 발생 시킨다.
  • RuntimeException 클래스를 상속 받아 정의한 unChecked Exception
    • 예외 처리하지 않아도 컴파일 시에는 오류를 발생시키지 않는다.

RuntimeException을 상속받은 BizException객체

    public class BizException extends RuntimeException {
        public BizException(String msg){
            super(msg);
        }       
        public BizException(Exception ex){
            super(ex);
        }
    }

BizService클래스는 업무를 처리하는 메소드를 가지고 있다고 가정한다.

    public class BizService {
        public void bizMethod(int i)throws BizException{
            System.out.println("비지니스 로직이 시작합니다.");
            if(i < 0){
                throw new BizException("매개변수 i는 0이상이어야 합니다.");
            }
            System.out.println("비지니스 로직이 종료됩니다.");
        }
    }

앞에서 만든 BizService를 이용하는 BizExam클래스

  • 매개변수 값을 -1을 넘길때는 Exception이 발생하기 때문에 try catch블록으로 처리한다.
    public class BizExam {  
        public static void main(String[] args) {
            BizService biz = new BizService();
            biz.bizMethod(5);
            try{
                biz.bizMethod(-3);
            }catch(Exception ex){
                ex.printStackTrace();
            }
        }
    }

실행결과

비지니스 로직이 시작합니다.
비지니스 로직이 종료됩니다.
비지니스 로직이 시작합니다.
javaStudy.BizException: 매개변수 i는 0이상이어야 합니다.
at javaStudy.BizService.bizMethod(BizService.java:7)
at javaStudy.BizExam.main(BizExam.java:9)


반응형

+ Recent posts