ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바 프로그래밍 언어 기본과 자료형
    자바/Java 공부 2018. 1. 16. 10:55

    -기본



    객체지향 언어:

    자바는 객체지향(Object Oriented Program)언어로 개발과 유지보수를 효율적으로 진행 할 수 있다.


    키워드:

    자바 언어 중 특별한 의미가 부여되어있는 명령어


    식별자:

    개발자가 자바 프로그래밍중 이름 붙인 것들(클래스, 변수, 메서드, 상수 등)


    리터럴:

    변수와 상수의 값

    ex) 1, "abc", 2.1 등




    컴파일:

    프로그래머가 만든 코드를 컴퓨터가 이해할 수 있는 기계어로 바꾸는 작업.

    자바.java -> 자바.class (컴파일 된 파일은 확장자가 class로 바뀐다.)


    메모리 관리:

    자바는 개발자가 사용된 메모리 관리를 직접 할 필요가 없다.

    (if not 메모리 누수, 심하면 프로세스가 중단 될 수 있다.)



    바이너리 파일: 

    2진법 데이터 또는 실행관련 파일



    Java JDK(Java Development Kit): 

    개발자용, 자바 프로그램 생성툴


    JRE(Java Runtime Environment):

    단순히 자바 프로그램 사용을 위한 툴


    API(Application Program Interface):

    프로그램 개발을 위한 subroutine definition, protocol, tool이 포함 된 것.


    Java VM(Virtual Machine):

    자바가 각 운영체제(윈도우, 리눅스, 맥os)에서 동작하게 하고 컴파일, 메모리 관리(garbage collection)의 기능을 한다.



    이클립스:

    IDE(Intergrated Development Environment), 가장 널리 사용되는 자바 프로그램 작성을 도와주는 도구


    자바 프로그램의 실행 단계:

    프로그래머가 작성한 코드(확장자 .java)가 컴파일러에 의해 확장자가 (.class)로 바뀐다. 그리고 그 파일을 Java VM이 바이너리 파일로 인식한다. 프로그램이 실행된다.


    C, C++언어와 자바의 차이점:

    C언어는 컴파일 된 프로그램을 바로 실행할 수 있지만 운영체제 별로 프로그램을 호환 가능하게 만들어야 한다.

    하지만 자바는 JVM과 같은 중간 단계가 있어서 하나의 프로그램이 모든 운영체제에서 실행된다. 단점은 C언어보다 속도가 느리다.


    변수:

    변수 선언과 함께 메모리 공간이 주어지고 이름을 붙인다. 그리고 공간의 용도(자료형)가 결정된다. 


    -변수 선언 후 값을 저장하는 경우

    int num1;

    num1 = 10;


    -변수 선언과 값을 동시에 저장

    int num2 = 20;

    int num3 = num1 + num2


    자료형(Datatype):

    변수의 값을 저장하고 참조하는 방식을 결정하는 것

    정수, 실수, 문자, 문자열 등은 데이터 표현 범위에 따라서 필요 저장공간(byte)이 각자 다르다.


    사칙연산은 자료형 int로 실행해야한다. (short 형으로 사칙연산을 실행하면 데이터 손실 에러발생)

    사칙연산의 처리속도를 높이기 위해서 int형을 기본으로 한다.



    기본자료형(primitive data type):

    이미 존재하고 있는 데이터 타입(int, double, boolean, char 등)

    자료형에 맞는 크기로 메모리에 직접 할당된다.


    객체자료형(reference data type):

    다수의 데이터가 모여있는 데이터로 크기가 더 크다(자바API, 클래스 객체)대문자로 시작한다.

    메모리의 데이터의 주소값이 별도로 저장된다.


    상수(constant):

    int a =1;

    변수 a는 대입 연산자에 의해서 1이 되었고

    1 = 3;

    위 예제는 컴파일 되지 않는다. 1은 3이 될 수 없기 때문이다. 1은 1이고, 3은 3이다. 고유한 값을 가지고 있고, 그 값을 변경 할 수 없는 데이터 타입을 상수라고 한다. (문자형, 논리형, 숫자형 등 대부분의 데이터 타입이 해당


    초기화?

    final 선언이 붙어있는 변수


    final 상수 선언시에는 상수의 이름은 모두 대문자로, 둘 이상의 단어는 언더바로 연결하는 것이 관례


    ex) int JAVA = 20;



    형변환(Conversion):

    정수 200과 실수 200.0의 bit 값이 완전히 다른 것을 알 수 있다. 이렇게 형식이 다른 데이터들을 더하려면 한쪽의 데이터 타입을 다른 쪽의 데이터 타입으로 전환(Conversion)해야 한다. 자바는 이러한 형 변환을 자동으로 처리해주는데 이러한 전환작업을 자동(암시적) 형 변환(implicit Conversion)이라고 부른다.


    -자동 형변환(프로모션): 

    범위가 좁은 데이터 타입 -> 범위가 넓은 데이터 타입으로 변환이 허용되는 것


    -명시적 형변환(디모션):

    아래와 같이 괄호 안에 데이터 타입을 지정해서 값 앞에 위치시키는 것을 명시적인 형 변환이라고 부른다.(데이터 손실을 감안해야 한다)


    float a = (float)100.0;
    int b = (int)100.0F;



    이스케이프 :

    \를 " 앞에 위치시키면 " 를 문자열의 시작과 끝을 구분하는 구분자가 아니라 단순히 문자로 해석하도록 강제할 수 있다. 이러한 기법을 escape(이스케이프)라고 한다.


    System.out.println("A의 \"값\"은:"+e);






    -자료형(데이터 타입)

    • 정수

    자료형표현범위(byte, short등도 있지만 거의 사용하지 않는다. 대용량의 데이터를 저장할때 간혹 사용한다.)


    int- 2147483648 ~ 2147483647

    long- 9223372036854775808 ~ 9223372036854775807


    int age = 10; long countOfStar = 8764827384923849L;


    • 실수

    실수형은 디폴트가 double이므로 위의 예에서 보듯이 float 변수에 값을 대입할 때에는 3.14F 와 같이 F접미사(또는 소문자 f)를 꼭 붙여 주어야 한다.


    double(8byte)과 float(4byte)의 자료형 선택 기준은 정밀도.


    double - 소수점 이하 15자리까지 오차없음

    float -소수점 이하 6자리까지 오차없음


    ※연산이 누적되면 오차범위가 늘어나므로 주의해야 한다.


    float pi = 3.14F; double morePi = 3.14159265358979323846;

    • 8진수와 16진수

    8진수와 16진수는 int 자료형을 사용하여 표기할 수 있다.

    0(숫자 '0')으로 시작하면 8진수, 0x(숫자 '0' + 알파벳 'x')로 시작하면 16진수가 된다.

    다음과 같이 사용된다.

    int octal = 023;    // 십진수: 19
    int hex = 0xC;     // 십진수: 12


    • 숫자연산

    자바의 사칙연산은 실 생활에서 사용되는 사칙연산과 다를 바가 없다.

    +, -, *, / 기호를 이용하여 두 숫자간 사칙연산을 수행한다.


    • 증감연산 (++, --)

    int i = 0; int j= 10; i++; j--; System.out.println(i); System.out.println(j);

    1 9

    ++는 값을 1만큼 증가시키고 --는 값을 1만큼 감소시킨다는 것을 확인 할 수 있었다.

    여기서 잠깐 실수하기 쉬운 것이 있다. 그것은 바로 ++, -- 등의 연산자의 위치이다.

    int i = 0;
    System.out.println(i++);
    System.out.println(i);
    

    실행결과는 다음과 같다.

    0
    1


    • 논리 자료형(boolean)

    참 또는 거짓의 값을 갖는 자료형을 부울 자료형이라고 한다. 자료형의 명침은 boolean(불린 또는 불리언이라고 부른다)이다.

    boolean isSuccess = true; boolean isTest = false;


    int base = 180; int height = 185; boolean isTall = height > base; if (isTall) { System.out.println("키가 큽니다."); }


    int i = 3;
    boolean isOdd = i % 2 == 1;
    

    i % 2 == 1은 i를 2로 나누었을 때 나머지가 1인지를 묻는 조건문이다. i는 3이므로 3을 2로 나눈 나머지는 1이 되어 참이 된다. 따라서 isOdd 는 true 값을 갖게 될것이다.


    • 문자(char)

    컴퓨터는 문자를 인식하지 못한다. 문자 -> 숫자, 숫자 ->문자로 변환하는 과정이 필요하고 가장 보편적인 기준이 유니코드이다. (JVM이 유니코드를 가지고 있고 문자 변환을 해준다.) 
    char a1 = 'a';
    

    주의할 점은 위와같이 문자값을 '(단일 인용부호)로 감싸주어야 한다는 점이다. ' '안에 문자에 해당하는 유니코드를 자바 컴파일러가 찾아서 그 값을 저장한다. 문자형 출력 시에는 위의 반대로 진행된다.


    • 문자열(string)

    자바에서 문자열에 해당하는 자료형은 String 이다.

    즉 위 문자열을 자바에서 표현하려면 다음과 같이 사용해야 한다.

    String a = "Happy Java";
    String b = "a";
    String c = "123";
    

    위의 예제는 다음과 같이 표현해도 된다. 1

    String a = new String("Happy Java");
    String b = new String("a");
    String c = new String("123");


    primitive(원시) 자료형

    이전에 살펴보았던 int, long, double, float, boolean, char 등을 자바는 primitive 자료형 이라고 부른다. 이런 primitive 자료형은 new 키워드로 생성할 수 없다.

    primitive 자료형은 다음과 같이 리터럴(literal)로 값을 세팅할 수 있다. (※ 리터럴은 계산식 없이 소스코드에 표기하는 상수 값을 의미한다.)

    boolean result = true;
    char capitalC = 'C';
    int i = 100000;
    

    여기서 잠깐, String 은 "Happy Java"와 같이 리터럴로 표기가 가능하지만 primitive 자료형은 아니다. (String은 리터럴 표현식을 사용할 수 있도록 자바에서 특별 대우 해 주는 자료형이다.)

    StringBuffer

    StringBuffer는 문자열을 추가하거나 변경 할 때 주로 사용하는 자료형이다.

    append


    public class Test { public static void main(String[] args) { StringBuffer sb = new StringBuffer(); sb.append("hello"); sb.append(" "); sb.append("jump to java"); System.out.println(sb.toString());


    hello jump to java


    예제와 같이 toString() 메소드를 이용하면 String 자료형으로 변경할 수 있다.


     String 자료형은 immutable하다. trim, toUpperCase는 다른 string 객체를 생선해서 리턴하는 것이다.

    반대로 StringBuffer는 값을 변경할 수 있지만 String 자료형 보다 무거운 편에 속한다.

    그러므로 용도에 따라서 선택 사용한다.


    insert

    insert 메소드는 특정 위치에 원하는 문자열을 삽입할 수 있다.

    public class Test {
        public static void main(String[] args) {
            StringBuffer sb = new StringBuffer();
            sb.append("jump to java");
            sb.insert(0, "hello ");
            System.out.println(sb.toString());
        }
    }

    hello jump to java


    substring

    substring 메소드는 String 자료형의 substring 메소드와 사용법이 동일하다.

    public class Test {
        public static void main(String[] args) {
            StringBuffer sb = new StringBuffer();
            sb.append("Hello jump to java");
            System.out.println(sb.substring(0, 4));
        }
    }
    

    결과값은 다음과 같다.

    Hell




    -배열 (array)

    배열은 자료형 타입 바로 옆에 [] 기호를 사용하여 표현한다. 위 예제와 같이 int 자료형의 배열은 int[] 로 표현되었다.

    요일의 집합은 다음과 같이 String 배열로 표현 할 수 있다.


    int[] odds = {1, 3, 5, 7, 9};

    String[] weeks = {"월", "화", "수", "목", "금", "토", "일"};

    ※ 위에서 알아본 배열은 모두 1차원 배열이다. 2차원, 3차원등의 다차원 배열도 가능한데 사실 2차원 이상의 배열은 프로그래밍 시 잘 사용되지 않는다.

    배열의 길이는 고정되어 있다

    위에서 살펴본 요일의 집합 예제는 다음과 같이 고쳐 쓸 수 있다.

    String[] weeks = new String[7];
    weeks[0] = "월";
    weeks[1] = "화";
    weeks[2] = "수";
    weeks[3] = "목";
    weeks[4] = "금";
    weeks[5] = "토";
    weeks[6] = "일";

    String[] weeks = new String[]; // 길이값이 없으므로 컴파일 오류가 발생한다.

    배열의 값은 어떻게 접근할 수 있을까?

    위에서 만든 요일의 배열중 "목"에 해당되는 값만 얻으려면 다음과 같이 인덱싱을 이용하면 된다.

    String[] weeks = {"월", "화", "수", "목", "금", "토", "일"};
    System.out.println(weeks[3]);

    배열의 길이

    배열의 길이만큼 for 문을 돌리는 것이 중요한데 이 배열의 길이는 다음과 같이 length를 이용하여 구한다.

    String[] weeks = {"월", "화", "수", "목", "금", "토", "일"};
    for (int i=0; i<weeks.length; i++) {
        System.out.println(weeks[i]);
    }

    빈번한 배열의 오류

    ArrayOutOfBoundsExcepiton

    다음의 예처럼 요일 배열의 길이는 총 7개인데 만약 8번째 값을 얻으려고 시도하면 위와 같은 오류가 발생할 것이다.

    System.out.println(weeks[7]);  // 8번째 배열값이 없으므로 ArrayOutOfBoundsException 오류가 발생한다.



    -리스트


    동적으로 자료형의 갯수가 가변하는 상황이라면 List를 사용하는 것이 유리하다.

    List 자료형 중 가장 간단한 형태의 자료형인 ArrayList에 대해서 알아보자.

    List 자료형에는 ArrayList, LinkedList 등의 List 인터페이스를 구현한 자료형이 있다. 여기서 말하는 List 자료형은 인터페이스인데 인터페이스에 대해서는 뒤에서 자세히 다루도록 한다.


    add

    박찬호 선수가 총 3번의 투구를 138, 129, 142(km) 의 속도록 던졌다면 다음과 같이 코드를 작성할 수 있다.

    ArrayList pitches = new ArrayList();
    pitches.add("138");
    pitches.add("129");
    pitches.add("142");

    만약 첫번째 위치에 "133"이라는 투구 스피드를 삽입하고 싶다면 아래와 같이 코딩하면 된다.

    pitches.add(0, "133");    // 첫번째 위치에 133 삽입.
    

    만약 2번 째 위치에 133을 삽일 할 경우에는 다음과 같이 코딩하면 된다.

    pitches.add(1, "133");
    

    ※ 자바는 J2SE 5.0 버전 이후부터 ArrayList<String> pitches = new ArrayList<String>(); 이런식으로 객체를 포함하는 자료형도 어떤 객체를 포함하는지에 대해서 명확하게 표현하는것을 권고하고 있다. 이클립스에서 위와 같이 코딩하면 명확한 타입을 명시하라는 warning이 표시될 것이다. 이 부분에 대한 자세한 내용은 다음 장인 제네릭스에서 자세하게 설명한다.

    get

    박찬호 선수의 2번째 투구 스피드를 알고 싶다면 다음과 같이 하면 된다.

    System.out.println(pitches.get(1));

    size

    size 메소드는 ArrayList의 갯수를 리턴한다.

    System.out.println(pitches.size());

    contains

    contains 메소드는 리스트 안에 항목값이 있는지를 판별하여 그 결과를 boolean으로 리턴한다.

    System.out.println(pitches.contains("142"));



    -제네릭스 (generics)


    다음과 같은 것이 제네릭스이다.

    ArrayList<String> aList = new ArrayList<String>();
    

    제네릭스가 도입되기 전인 J2SE 1.4 까지는 위의 코드를 다음과 같이 사용했다.

    ArrayList aList = new ArrayList();
    

    두 개 코드의 차이점은 ArrayList 라는 자료형 타입 바로 옆에 <String> 과 같은 문구가 있느냐 없느냐의 차이이다.

    위에서 사용한 첫번째 코드의 <String> 이라는 제네릭스 표현식은 "ArrayList 안에 담을 수 있는 자료형은 String 타입 뿐이다" 라는 것을 의미한다.

    ※ 여기서는 제네릭스의 타입으로 String 자료형만을 예로 들었지만 <Integer><Animal><Dog> 등 어떤 자료형도 사용할 수 있다.

    ArrayList 객체인 aList에 값을 넣을 때는 문제가 안되지만 값을 가져올 경우에는 항상 Object 자료형에서 String 자료형으로 다음과 같이 형변환(casting)을 해 주어야만 한다.

    String hello = (String) aList.get(0); // Object 를 String 으로 캐스팅한다. (String)
    

    또 한가지 aList 안에는 String 객체 이외의 객체도 넣을 수 있기 때문에 형 변환 과정에서 잘못된 형변환으로 인한 오류가 발생할 소지가 있다.

    바로 이러한 점이 제네릭스의 탄생 이유이기도 하다.

    위 코드를 제네릭스를 이용하여 변경하면 다음과 같이 된다.

    ArrayList<String> aList = new ArrayList<String>();
    aList.add("hello");
    aList.add("java");
    
    String hello = aList.get(0);
    String java = aList.get(1);
    

    제네릭스로 자료형을 선언하기만 하면 그 이후로는 자료형에 대한 형변환 과정이 필요없다. 이미 컴파일러가 aList 에는 반드시 String 자료형만 추가 되어야 함을 알기 때문이다. 이렇게 제네릭스를 이용하면 형변환에 의한 불필요한 코딩, 잘못된 형변환에 의한 런타임 오류등에서 벗어날 수 있게 된다.


    -맵 (map)

    ‘사람’을 예로 들면 누구든지 "이름" = "홍길동", "생일" = "몇 월 몇 일" 등으로 구분할 수 있다. 자바의 맵(Map)은 이러한 대응관계를 쉽게 표현할 수 있게 해 주는 자료형이다. 이것은 요즘 나오는 대부분의 언어들도 갖고 있는 자료형으로 Associative array, Hash라고도 불린다.

    맵(Map)은 사전(dictionary)과 비슷하다. 즉, people 이란 단어에 "사람", baseball 이라는 단어에 "야구"라는 뜻이 부합되듯이 Map은 Key와 Value라는 것을 한 쌍으로 갖는 자료형이다.

    keyvalue
    people사람
    baseball야구

    Map은 리스트나 배열처럼 순차적으로(sequential) 해당 요소 값을 구하지 않고 key를 통해 value를 얻는다.


    HashMap<String, String> map = new HashMap<String, String>();
    map.put("people", "사람");
    map.put("baseball", "야구");
    

    key와 value가 String 형태인 HashMap을 만들고 위에서 보았던 예제의 항목값들을 입력해 보았다. key와 value는 위 예제에서 보듯이 put메소드를 이용하여 입력한다.

    ※ HashMap 역시 제네릭스를 이용한다. 위의 HashMap 의 제네릭스는 Key, Value 모두 String 타입이다.

    get

    key에 해당되는 값을 얻기 위해서는 다음과 같이 한다.

    System.out.println(map.get("people"));
    

    위와같이 get 메소드를 이용하면 value값을 얻을 수 있다. 

    containsKey

    containsKey 메소드는 맵(Map)에 해당 키(key)가 있는지를 조사하여 그 결과값을 리턴한다.

    System.out.println(map.containsKey("people"));
    

    "people"이라는 키는 존재하므로 true가 출력될 것이다.

    remove

    remove 메소드는 맵(Map)의 항목을 삭제하는 메소드로 key값에 해당되는 아이템(key, value)을 삭제한 후 그 value 값을 리턴한다.

    System.out.println(map.remove("people"));
    

    "people"에 해당되는 아이템(people:사람)이 삭제된 후 "사람"이 출력될 것이다.

    size

    size 메소드는 Map의 갯수를 리턴한다.

    System.out.println(map.size());

    LinkedHashMap과 TreeMap

    Map의 가장 큰 특징은 순서에 의존하지 않고 key로 value를 가져오는데 있다. 하지만 가끔은 Map에 입력된 순서대로 데이터를 가져오고 싶은 경우도 있고 때로는 입력된 key에 의해 소트된 데이터를 가져오고 싶을 수도 있을 것이다. 이런경우에는 LinkedHashMap과 TreeMap을 사용하는 것이 유리하다.

    • LinkedHashMap은 입력된 순서대로 데이터가 출력되는 특징을 가지고 있다.
    • TreeMap은 입력된 key의 소트순으로 데이터가 출력되는 특징을 가지고 있다.