Java (18)

 

문제

 

문자열을  입력받아 문자열을 구성하는 각 문자를 key로 갖는 hashMap을 리턴하는 메소드 만들기

 

 

해결

 

public HashMap<Character, Integer> countAllCharacter(String str) {
        // 문자열이 비어있을 경우 null 리턴
        if (str.isEmpty()) {
            return null;
        }
        
        // 반환할 hashMap 생성
        HashMap<Character, Integer> result = new HashMap<>();
        // 매개변수의 문자열을 char형 배열로 변환
        char[] charArray = str.toCharArray();
        // Arrays.sort()를 이용하여 char 배열을 알파벳 순으로 정렬
        Arrays.sort(charArray);
        
        // char형 배열의 요소를 하나씩 꺼내기
        // 향상된 for문 이용
        for (char c : charArray) {
        	// 중복될 경우 해당 key의 value 값에 +1
            if (result.containsKey(c)) {
                result.put(c, result.get(c) + 1);
            } else {
            	// 중복되지 않을 경우 key와 value 1을 hashMap에 추가
                result.put(c, 1);
            }
        }
        return result;
}

 

 

 

해결하기 전까지의 과정

 

처음에는 String을 char형 배열로 만든 다음 배열 내에서 중복을 체크하고

중복되면 value에 +1 해준 후 배열의 해당 중복된 문자 하나를 지운 후 한 칸씩 왼쪽으로 이동해주는 코드를 작성했다.

하지만 오류가 많고 문제가 배열의 길이를 축소할 방법이 없었다.

 

그 다음에 생각한 방법이 char형 배열을 ArrayList<Character> 형으로 만드는 방법이었다.

중복된 문자를 ArrayList의 메소드인 remove()를 이용해서 하나 제거하고 value에 +1 해주는 방법으로 했다.

이렇게 해도 함수에서 반환받은 hashMap이 index 초과 오류가 발생했다.

 

전부 지우고 빈 화면에서 곰곰히 생각하다가 겨우 생각났다. 😔

char형 배열로 옮긴 다음에

문자를 하나씩

hashMap의 containsKey() 메소드를 이용해서 hashMap안에 중복되 있는지 확인하고

중복되면 해당 문자 key에 value 값을 +1 하고

중복되지 않으면 map안에 없는 것이니까 새로 맵에 붙여 주면 된다.

고민하고 헤맨 것에 비해 너무 간단하고 한순간에 해결됐다.. 

계속 방법이 생각이 안나다가 머리속에 벼락맞은 것처럼 한순간에 생각났다. ㅋㅋㅋ

 

 

 

 

 

 

 

 

❑ 제네릭(Generic)

 

 

➤ 제네릭이 무엇인가?

 

  • Generic 은 “일반적인”이란 뜻
  • 클래스 내부에 사용할 타입을 외부에서 파라미터 형태로 지정
  • 데이터 타입을 일반화 ( ▶️ 범용적으로 사용할 수 있게함)
  • 자바 5부터 제네릭 추가됨

 

 

 

➤ 제네릭 프로그래밍

 

어떤 변수가 하나의 참조 자료형이 아닌 여러 참조 자료형을 사용할 수 있도록 프로그래밍하는 것

 

여러 참조 자료형이 쓰일 수 있을 때 미리 특정한 자료형을 지정하지 않고 제네릭으로 선언해서 클래스나 메소드가 사용되는 시점에 어떤 자료형 사용할지 지정

 

 

 제네릭 클래스 정의하기

 

클래스명 <T> {

}

 

ex) 

class GenericDeclaration <T> {
    private T variable;

    public T getVariable() {
        return variable;
    }

    public void setVariable(T variable) {
        this.variable = variable;
    }
}

 

여러 자료형으로 바꾸어 사용할 부분에 자료형 대신 T 작성

<> : 다이아몬드 연산자

T를 자료형 매개변수(Type parameter, 타입 매개변수)

T : 대입된 자료형

GenericDeclaration <T> : 제네릭 자료형, 매개변수화된 자료형

 

 

ArrayList<Integer> array = new ArrayList<>();

선언하는 부분의 <>에 자료형을 작성했기 때문에 생성부분의 <> 안은 생략 가능

컴파일러가 유추 가능하기 때문

 

주로 <>안에 T를 많이 사용 (Type)

E (Element), K (Keyt), N (Number), V (Value), R (Result) 등 있음

위의 예시 뿐만 아니라 A, B, C 등 사용자가 정의해서 사용해도 된다.

 

 

 

⤵️아래는 저의 견해입니다.

 

타입 매개변수는 수학의 변수 x라고 생각해주면 코드를 작성하고 읽기가 용이하다.

수학에서 변수 x는 어떤 수든 대입할 수 있다.

하지만 식에서 x에 특정 수를 대입하는 순간 식 안의 모든 x는 그 수로 정해져서 계산된다.

예를 들어서 x+1-2x 라는 식이 있다고 가정해보자.

이때 x에 1을 대입하려고 하면 x, -2x 모두 x=1을 대입하고 계산해야 한다.

x에는 x=1 을 대입하고 -2x에는 x=2를 대입하는 식으로 계산해선 안된다.

변수 x는 같은 수를 의미하므로 모든 x엔 같은 수로 대입해줘야 한다.

프로그래밍에서 제네릭을 컴파일하는 과정에서도 마찬가지이다.

컴파일러는 같은 알파벳의 타입 매개변수는 모두 같은 변수라고 생각한다.

따라서 타입 매개변수 T는 인스턴스가 만들어질 때 같은 타입이 대입된다.

 

 

 

➤ static 변수와 타입 매개변수

 

static 변수, static 메소드 내에서는 타입 매개변수 사용할 수 없음

 

🔎  이유는?

제네릭의 타입이 정해지는 것은 인스턴스가 생성되는 순간이다.

하지만 static은 클래스 생성 시 클래스 정보와 함께 메모리에 올라가는데 타입을 지정해주지 않으면 메모리를 할당할 수 없다.

따라서 타입 매개변수의 자료형이 결정되는 시점보다 static 변수나 메소드가 생성되는 시점이 더 빠르기 때문에 문제가 발생하게 된다.

 

 

 

 

➤ 왜 제네릭이 직접 형 변환하는 것보다 안정적일까?

 

Object 등의 상위 클래스 타입으로 정의하고 직접 형변환 해주면 제네릭보다 불안정함

제네릭 클래스는 컴파일러가 일단 대입된 자료형이 잘 쓰였는지 확인하고

class 파일을 생성할 때 타입 매개변수를 사용한 곳에 지정한 자료형에 따라 컴파일함

 

 

 

➤ 제네릭 메소드(Generic Method)

 

클래스 전체가 아닌 클래스 내부의 특정 메소드만 제네릭으로 선언

매개변수나 메소드 시그니처에 타입 매개변수 T를 사용한 메소드

메소드가 호출되는 시점에 제네릭 타입이 결정됨

정의되는 시점에는 어떤 타입이 입력되는지 알 수 없음

-> length()와 같은 클래스내 메소드는 정의하는 시점에 사용 불가

-> 최상위 클래스 Object의 메소드는 사용 가능

일반 메소드, static 메소드에서 모두 활용 가능

 

 

 

➤ 제네릭의 장점

 

- 여러 참조 자료형마다 코드를 작성하지 않아도 되서 코드가 간결하고 직관적

- 매번 형 변환을 할 필요가 없기 때문에 오류의 확률 줄어듬 -> 안정성

- 새로운 자료형을 사용할 땐 그 자료형만 생성하고 사용할때 <> 안에 자료형 넣기만 하면됨

 

 

 

☑️ 참고) 제네릭으로 자료형 추론하기

자바10 부터는 지역변수에 한해서 자료형을 추론 가능(var형 사용 가능)

➡️ 지역 변수 자료형 추론(local variable type inference)

var local = new ArrayList<String>();

➡️ 컴파일러가 자료형 추론 가능

 

 

 

➤ 와일드카드(wild card)

 

제한을 두지 않는 기호를 의미

제네릭에서는 ? 기호를 사용하여 와일드 카드 사용

 

  • <?> : 타입 매개변수에 모든 타입 사용
  • <? extends T> : T 타입과 T타입의 하위 클래스만 사용
  • <? super T> : T 타입과 T 타입의 상위 클래스만 사용

 

 

 

추가로 공부할 부분

 

왜 Object가 아닌 Generic을 사용하는가?

 

 

Object의 메소드

https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html

 

Object (Java Platform SE 7 )

Called by the garbage collector on an object when garbage collection determines that there are no more references to the object. A subclass overrides the finalize method to dispose of system resources or to perform other cleanup. The general contract of fi

docs.oracle.com

 

 

읽어주셔서 감사합니다 😊  도움이 되셨길 바랍니다.

오개념에 대한 지적은 언제나 환영입니다.

 

 

 

< 다형성(Polymorphism) >

 

 

❏ 다형성이 무엇인가?

 

polymorphism은 poly(여러개) 와 morphism(형태)의 합성어이다.

말그대로 여러개의 형태를 의미한다.

객체지향에서 하위 클래스는 상위클래스로 형변환(업캐스팅)이 가능하다.

 

 

예를 들어서 동물이라는 클래스를 개, 고양이, 도마뱀이라는 클래스가 상속하고 있다.

 

class Animal {
    void info(){
        System.out.println("나는 동물 입니다.");
    }
}

class Dog extends Animal{
    @Override
    void info() {
        System.out.println("나는 개입니다.🐕");
    }
    void woof() {
        System.out.println("멍멍멍멍");
    }
}

class Cat extends Animal {
    @Override
    void info() {
        System.out.println("나는 고양이입니다.🐱");
    }
    void meow() {
        System.out.println("야옹~야옹~");
    }
}

class Lizard extends Animal {
    String sexuality;
    @Override
    void info() {
        System.out.println("나는 도마뱀입니다.🦎");
    }
    
}

 

Animal의 info클래스를 각각의 하위 클래스에서 이름에 맞게 재정의를 해줬다.

 

public class AnimalTest {
    public static void main(String args[]) {
        // 다형성을 이용하여 같은 참조변수로 선언하기
        Animal dog = new Dog();
        Animal cat = new Cat();
        Animal lizard = new Lizard();

        // 재정의한 메소드 실행
        dog.info();
        cat.info();
        lizard.info();
    }
}

 

<출력결과>

나는 개입니다.🐕
나는 고양이입니다.🐱
나는 도마뱀입니다.🦎

 

상위 클래스인 Animal로 타입을 지정하고 new로 만든 인스턴스는 각각 하위 클래스로 지정해줄 수 있다.

이렇게 하위 클래스로 만들고 상위 클래스로 타입을 바꾸는 것을 '업캐스팅'이라고 한다.

상속 계층도에서 위로 올라가서 업캐스팅이라고 생각하자. (반대는 아래로 가니까 다운캐스팅)

 

 

업캐스팅, 다운캐스팅

 

자바에서는 업캐스팅은 별다른 키워드 없이 암묵적으로 가능하다.

이것을 '묵시적 형변환' 이라고도 한다.

하지만 반대로 암묵적으로 다운캐스팅(상위클래스 ➡️ 하위클래스)은 불가하다!!

 

다운 캐스팅 오류

상위 클래스로 인스턴스를 만든 후에 하위 클래스로 다운 캐스팅하게 되면 사진처럼 빨간 줄이 그어지고 오류가 난다.

 

 

 

 

❏ 왜 업캐스팅은 묵시적으로 되지만 다운캐스팅은 안될까?

 

하위 클래스들은 상위 클래스보다 구체적이고 메소드나 멤버변수가 같거나 많다.

하지만 상위 클래스는 더 일반적으로 만들어서 메소드나 멤버변수가 같거나 적다.

 

그래서 상위 클래스로 만든 인스턴스를 하위 클래스 타입의 메모리 공간에 집어넣으면

일부 메소드와 멤버변수를 사용할 수 없는 일이 발생한다.

실제로 클래스 내에 정의된 멤버변수와 메소드를 쓸 수 없어서 에러가 발생한다.

 

반대로 하위 클래스로 만든 인스턴스를 상위 클래스 타입의 메모리에 넣는건

인스턴스 만들 떄 있던 일부 기능이나 속성을 사용하지는 못하더라도 상위 클래스에 정의된 모든 메소드나 멤버변수는 사용할 수 있다.

내용물은 하위 클래스더라도 참조 타입은 상위 클래스이기 때문에 문제될 것은 없는 것이다.

 

참고) 상위 클래스 위의 상위 클래스들도 묵시적으로 형변환이 가능할까?

상속 계층이 여러 층일 때 여러 층 위의 상위 클래스로의 형변환도 묵시적으로 이루어진다.

 

 

 

❏ instanceof 를 통한 다운 캐스팅

 

상위 클래스로 형변환 했던 하위 클래스를 다시 원래 자료형으로 돌려놓을 수는 없을까?

하위 클래스로 직접적으로 형변환 할 수는 없지만 instanceof라는 키워드를 사용하면 원래 형태가 하위 클래스인지 확인할 수는 있다.

 

instanceof 예약어는 왼쪽에 있는 변수의 원래 인스턴스 형이 오른쪽 클래스 자료형인지 확인해준다.

➡️ 원래 자료형이 맞으면 true / 틀리면 false 를 반환한다.

주로 if 문과 함께 사용한다.

 

하위 클래스를 업 캐스팅하면 상위 클래스에 없는 해당 클래스의 고유한 메소드나 필드는 사용할 수 없게 된다.

위에 작성한 예시 코드에서 Dog와 Cat 클래스에는 상위 클래스에서 재정의한 메소드가 아닌 woof()와 meow()메소드가 있다.

그리고 Lizard에는 스트링 타입의 성별 멤버 변수가 선언되있다.

상위 클래스에서 정의 하지 않은 woof()와 meow(), sexuality를 업캐스팅한 변수에서 접근해보았다.

 

public static void main(String args[]) {
        // 다형성을 이용하여 같은 참조변수로 선언하기
        Animal dog = new Dog();
        Animal cat = new Cat();
        Animal lizard = new Lizard();
        Lizard example = new Animal();

        // 하위클래스에만 있는 메소드 실행
        dog.woof(); // cannot find symbol 오류
        cat.meow(); // cannot find symbol 오류
        // 하위 클래스에만 있는 필드 실행
        lizard.sexuality = "female";    // cannot find symbol 오류
        
}

 

실행하게 되면 'cannot find symbol' 에러가 뜨게 된다.

상위 클래스로 형변환하면서 하위 클래스에만 있던 메소드와 필드는 메모리 할당이 되지 않아 사용할 수 없게 된 것이다.

 

이럴 때 instanceof 를 사용해서 원래 자료형을 확인하고 맞으면 원래 인스턴스형강제로 다운캐스팅 해주면 된다.

원래 인스턴스형으로 변환할 때는 괄호안에 원래 자료형을 반드시 명시해야한다.

상위 클래스로 형변환 했던 객체를 다시 원래 자료형으로 형변환하는 것을 '다운캐스팅'이라고 부르기도 한다.

 

public static void main(String[] args) {
   // 상위 클래스로 형변환
   Animal dog = new Dog();
   Animal cat = new Cat();
   Animal lizard = new Lizard();

   // instanceof를 이용한 다운캐스팅
   if (dog instanceof Dog) {
       Dog dog1 = (Dog)dog;
       dog1.woof();
   }
   if (cat instanceof Cat) {
       Cat cat1 = (Cat)cat;
       cat1.meow();;
   }
   if (lizard instanceof Lizard) {
       Lizard lizard1 = (Lizard)lizard;
       lizard1.sexuality = "female";
       System.out.println(lizard1.sexuality);
   }
}

 

<출력결과>

멍멍멍멍
야옹~야옹~
female

 

 

 

 

 

 

업캐스팅과 다운캐스팅에 대한 레퍼런스

https://www.geeksforgeeks.org/upcasting-vs-downcasting-in-java/

 

Upcasting Vs Downcasting in Java - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org

 

 

 

읽어주셔서 감사합니다. 도움이 되셨길 바랍니다. 🫶

오개념에 대한 지적은 언제나 환영입니다.

 

 

 

 

 

 

< 상속 >

 

 

❑ 상속이란?

 

상속은 OOP에서 아주아주 중요한 개념이다.

자바에서 상속은 말 그대로 부모 클래스가 자식 클래스에게 가지고 있는것을 물려주는 것을 말한다.

부모-자식 / 조상-자손 / parent class-child class 라고 표현하기도 한다.

하지만 상속의 의미를 생각했을 때 상위 클래스-하위 클래스라고 표현하는 것이 올바르다.

 

하위 클래스는 상위 클래스에서 속성과 기능을 모두 물려받아서 하위 클래스는 상위 클래스의 필드(field)와 메소드(method)를 쓸 수 있다.

 

 

🔎 그렇다면 상속은 언제 써야할까?

 

상속에서 상위 클래스는 하위 클래스를 포괄하는 일반적인 개념이고

하위 클래스는 상위 클래스보다 구체적인 개념이다.

상속은 이미 정의해놓은 클래스에 속성이나 기능을 추가해서 새로운 클래스를 만들려고 할 때 유용할 것이다.

이미 만들어놓은 클래스에 추가할 것만 새로 작성하면 되서 완전히 새로 작성하는 것보다 에너지가 적게 들 것이다.

그리고 상위 클래스를 통해서 아래에 여러 하위 클래스를 관리할 수 있기 때문에 유지보수하기 편할 것이다.

 

 

🌱 상속 개념 예시

포유류와 사람으로 예를 들어서 표현해보았다.

포유류는 사람, 고양이, 개보다 포괄적인 개념이고 사람, 고양이, 개는 포유류에 포함된다.

따라서 포유류가 상위 클래스이고 사람/고양이/개는 하위 클래스가 될 수 있다.

 

※ 상속을 표현할 때 화살표는 항상 하위 클래스에서 상위 클래스 쪽으로 향하게 그린다.

 

상속 예시1

 

여기서 또 사람은 프로그래머/요리사/화가보다 일반적인 개념이다.

따라서 사람 클래스는 이번엔 프로그래머, 요리사, 화가 클래스의 상위 클래스가 될 수 있다.

 

 

상속 예시2

 

이렇게 상속은 누군가의 하위 클래스이면서 동시에 누군가의 상위 클래스가 될 수 있다.

 

자바에서 상속을 구현할 때는 extends라는 예약어를 사용한다.

 

class child extends parent {
}

 

하위 클래스의 이름 옆에 'extends 상위클래스' 를 작성하면 상위-하위 클래스 관계가 된다.

 

 

🔔 참고) 다중 상속

다중 상속은 한 클래스가 여러 클래스에서 상속받는 것이다.

객체지향 언어인 C++에서는 다중 상속이 가능하지만 자바에서는 지원하지 않는다.

자바에서는 하위 클래스는 단 하나의 상위 클래스만 가질 수 있다. (extends 뒤엔 하나의 클래스만 올수 있다.)

여러 클래스에서 상속받으면 다양한 기능을 상속받을 수 있지만 모호성의 문제가 있다.

객체 지향에서 다중상속으로 인한 대표적인 문제가 다이아몬드 문제이다.

C++에서는 문법적으로 이를 해결했지만 자바는 모호함을 없애고 다중 상속을 사용하지 않는 것을 택한 것이다.

하지만 자바에서도 다형성이나 인터페이스라는 개념들로 다중 상속과 비슷한 효과를 낼 수 있다.

 

 

 

❑ 포함 관계

 

자바의 클래스들은 서로 관계적이다.

그렇다면 모든 관계가 상속일까? ❌

 

클래스간의 관계에는 상속도 있지만 '포함' 관계도 있다.

포함은 클래스 내에서 사용하기 위해서 정의한 클래스 관계이다.

public class Student {
	Subject math = new subject("math");
}

public class Subject {
	String name;
    
    Subject(String name) {
    	this.name = name;    
    }
}

 

예를 들어서 학생 클래스와 과목 클래스가 있을 때 과목 객체들은 모두 학생 클래스에 속하게 된다.

이럴 때 상속으로 만들면 어떻게 될까?

학생 클래스의 속성과 메소드는 과목 클래스에서 재사용하기 어렵다.

하지만 학생 클래스에서 과목 클래스를 만들어서 사용한다.

이럴 때는 상속보다는 포함 관계로 만드는 것이 좋다.

 

 

※ 상속은 '일반적인 개념-구체적인 개념' 다시말해

'IS-A 관계' (is a relationship) 에서 사용하는 것이 좋다.

'~(하위클래스)는 ~(상위클래스)이다' 로 표현했을 때 어색하지 않다면 상속으로 쓰면 된다.

 

- 예시 -

학생은 사람이다.

강아지는 동물이다.

카카오톡은 앱이다.

 

 

※ 포함은 'HAS-A 관계(has a relationship)' 에서 사용하는게 좋다.

'~는 ~를 가지고 있다.' 로 표현했을 때 어색하지 않다면 포함으로 쓰면 된다.

 

- 예시 -

컴퓨터는 모니터를 가지고 있다.

플레이어는 레벨을 가지고 있다.

 

 

 

❑ 메소드 오버라이딩 ( Method Overriding)

 

메서드 오버라이딩이란?

상위 클래스에서 정의된 메소드를 하위 클래스에서 재정의 하는 것이다.

상위 클래스에서 정의한 메소드를 하위 클래스마다 다르게 사용할 때가 있다.

오버라이딩 된 메소드라는 것을 컴파일러에 알려주기 위해서 재정의할 메소드 위에 '@Override'를 작성해준다.

public class Person {
	void walk() {
    	System.out.println("걷습니다.");
	}
}

class Dancer extends Person {
	@Override
	void walk() {
    	System.out.println("춤추면서 걷습니다.");
    }
}

 

 

⚠️ 오버라이딩 조건

✅ 반환형, 메소드 이름, 매개변수 개수, 매개변수 자료형이 반드시 같아야함

  접근 제어자의 범위가 상위 클래스의 메소드보다 같거나 넓어야 함

  예외는 상위 클래스의 메소드보다 많이 선언할 수 없음

➤ 조건을 지키지 않으면 자바 컴파일러가 재정의한 메소드를 기존의 메소드와 다른 메소드로 인식!

 

 

 

❑ super

 

상속에서 쓰는 super의 역할은 this 와 비슷하다.

super는 하위클래스에서 상위 클래스를 부르는 예약어다.

super 와 super()는 this처럼 역할이 다르다.

 

super

하위클래스에서 상위클래스를 부를 때 사용한다.

 

super()

하위클래스의 생성자에서 상위클래스의 생성자를 부를 때 사용한다.

생성자의 첫번째 줄에 작성해야 한다.

하위클래스 생성자에 작성하지 않아도 자동으로 호출한다.

 

 

 

❑ 최상위 클래스 Object

 

자바에서는 'Object'라는 말은 객체라는 의미이기도 하지만 최상위 클래스를 의미한다.

모든 클래스는 Object 밑에 하위 계층에 존재한다.

만약에 어떤 클래스를 만들었는데 extends를 작성하지 않으면 컴파일러가 자동으로 'extends Object'를 작성한다.

따라서 모든 클래스는 Object에 정의된 메소드들을 사용할 수 있다.

Object의 대표적인 메소드

메소드 설명
toString() 객체를 문자열로 표현하여 반환, 재정의하여 객체에 대한 설명이나 특정 멤버 변수 값을 반환함
boolean equals(Object obj) 두 인스턴스가 동일한지 여부를 반환, 재정의하여 논리적으로 동일한 인스턴스임을 정의할 수 있음
in hashCode() 객체의 해시코드 값을 반환(위치정보)
Object clone() 객체를 복제하여 동일한 멤버 변수 값을 가진 새로운 인스턴스를 생성함
Class getClass() 현재 객체가 참조하고 있는 클래스를 반환함
void finalize() 인스턴스가 힙 메모리에서 제거될 때 가비지 컬렉터에 의해 호출되는 메소드, 네트워크 연결 해제, 열려 있는 파일 스트림 해제 등을 구현
void wait() 멀티스레드 프로그램에서 사용하는 메소드, 스레드를 '기다리는 상태'로 만듦
void notify() wait() 메소드에 의해 기다리고 있는 스레드를 실행 가능한 상태로 가져옴

 

 

 

 

 

 

 

생성자 (Constructor)

 

 

“ 인스턴스가 생성될 때 인스턴스를 초기화 하는 메소드 “

 

 

클래스 구성요소 중 하나로 클래스를 생성하는 역할

생성자가 인스턴스를 만드는 명령어는 아님

new 키워드가 클래스의 인스턴스를 만들때 사용됨

 

클래스 이름(){

}

 

 

🌟 생성자도 오버로딩이 가능함

 

 

메소드와 다른점

 

1. 리턴을 하지 않는다

2. 생성자 이름은 반드시 클래스 이름과 동일해야 한다

     ➡️ 클래스명과 다르면 일반 메소드가 된다

 

 

 

생성자가 왜 필요한가?

 

➡️ 클래스를 처음 만들 때 멤버 변수나 상수를 초기화해서 여러개의 객체를 생성할 때 시간을 단축!

 

 

 

 

기본 생성자 / 매개변수가 있는 생성자

 

 

기본 생성자(default constructor)

 

➤ 모든 클래스 내부에는 생성자가 반드시 1개 이상 있어야 함

➤ 생성자가 없는 클래스는 프로그램 실행할 때 컴파일러가 자동으로 기본 생성자 생성

         → 생성자를 작성한 경우에는 디폴트 생성자 제공하지 않음

➤ 기본 생성자 직접 작성해도됨 ‘클래스() {}’

➤ 매개변수와 구현코드가 없음

 

 

매개변수가 있는 생성자

 

➤ 매개변수를 통해서 생성과 동시에 속성 값을 같이 넣어줄 수 있다.

➤ 기본 생성자로 만들고 ‘객체이름.변수’로 속성값 하나하나 지정해주는 것 보다 훨씬 편리함

 

 

 

 


 

 

 

this

 

▶️ this는 생성된 인스턴스 스스로를 가르키는 예약어

▶️ this는 쓰임새가 총 3가지 있음

 

 

1. 자신의 인스턴스 변수를 가르키는 this

 

인스턴스 변수와 지역변수 이름을 같게 하면 혼동됨

 

휴대폰을 예시로 들어서  클래스를 작성해보았다.

 

public class Phone {
	// 필드
	private String company;
   	private static int serialNum = 10000;
  	private String modelName;
   	private int modelNum;
	
	// 생성자
	Phone(String company, String modelName){
		// 잘못된 예시
		company = company;	
		modelName = modelName;
		modelNum = Phone.serialNum;
		Phone.serialNum += 1000;
	}
    
	// 메소드
	public String getCompany() {
        return company;
	}
	public String getModelName() {
        return modelName;
	}
	public int getModelNum() {
        return modelNum;
	}
}

 

Phone의 생성자를 보면 지역 변수와 인스턴스 변수 이름이 같다.

이런식으로 작성하면 컴파일러는 양쪽 다 지역변수로 생각한다.

 

main 클래스를 만들고 출력해보자

 

public class PhoneTest {
    public static void main(String[] args) {
        Phone iPhone11Max = new Phone("Apple", "iPhone11Max");

        System.out.println(iPhone11Max.getModelName() + "의 정보");
        System.out.println("제조사 : " + iPhone11Max.getCompany());
        System.out.println("모델넘버 : " + iPhone11Max.getModelNum());    }
}

 

<실행 결과>

null의 정보
제조사 : null
모델넘버 : 10000

 

실행 결과를 보면 지역 변수명과 인스턴스 변수명이 같은 변수는 인스턴스의 변수에 제대로 값이 저장이 안되서 null로 뜨는 것을 확인할 수 있다.

자바에서는 일반적으로 인스턴스 변수와 생성자의 지역변수 명을 똑같이 작성하는데

이럴때 인스턴스 변수와 지역변수를 컴파일러가 구분할 수 있게 'this.변수명' 을 사용한다.

이때 사용하는 this는 자신의 인스턴스를 가르킨다.

지역 변수가 아닌 인스턴스 내에 있는 해당 변수를 사용하는 것이다.

 

클래스의 생성자 부분을 이렇게 고치고 실행해보자

Phone(String company, String modelName) {
	this.company = company;
	this.modelName = modelName;
	this.modelNum = Phone.serialNum;
	Phone.serialNum += 1000;
}

 

<실행 결과>

iPhone11Max의 정보
제조사 : Apple
모델넘버 : 10000

this를 사용해서 구분해주면 지역변수가 인스턴스 변수에 올바르게 대입된 것을 확인할 수 있다.

 

 

 

2. 생성자에서 다른 생성자를 호출하는 this()

 

this()는 객체 내부에서 같은 객체 내부의 생성자를 호출하는 메소드이다.

반드시 생성자 내부에만 사용하고 생성자의 첫 줄에 위치해야한다.

생성자가 여러개 있으면 원하는 생성자의 매개변수에 맞춰서 괄호()안에 넣어주면 된다.

 

예시)

public class ThisExample {
    int num;
    String name;
    public ThisExample() {
        this(1, "None");
    }
    public ThisExample(int num, String name) {
        this.num = num;
        this.name = name;

    }
}

this(1, "None") 은 ThisExample(int num, String name) 생성자를 호출

num 변수에 1을, name변수에 "None"을 대입시킨다.

 

public class ThisTest {
    public static void main(String[] args) {
        ThisExample example1 = new ThisExample();
        ThisExample example2 = new ThisExample(10, "김철수");

        System.out.println(example1.name + ", " + example1.num);
        System.out.println(example2.name + ", " + example2.num);
    }
}

 

<실행 결과>

None, 1
김철수, 10

 

 

 

3. 자신의 주소를 가르키는 this

 

객체 내부에서 this 는 인스턴스의 주소를 가르키는 역할도 한다.

주소를 리턴하는 경우는 잘 사용하지 않는다.

 

 

ThisExample 클래스에 주소를 리턴하는 메소드를 작성해 보았다.

ThisExample address() {
   return this;
}

 

 

public static void main(String[] args) {
        ThisExample example3 = new ThisExample();
        System.out.println(example3.address());
        System.out.println(example3);
}

객체를 그대로 출력해도 주소값을 얻을 수 있다.

 

<실행결과>

constructor.ThisExample@6ad5c04e
constructor.ThisExample@6ad5c04e

실행해보면 인스턴스가 저장된 주소가 출력된다.

주소 앞에 constructor은 패키지 이름이고 ThisExample은 클래스 이름이다.

 

 

읽어주셔서 감사합니다 ❤️

 

 

 

 

 

 

객체지향 프로그래밍

 

OOP (Object Oriented Programming)

 

객체지향 프로그래밍 = 자바 ? (❌)

자바는 OOP의 하나일 뿐 자바 자체가 객체지향 프로그래밍은 아니다.

 

 

객체란?

 

눈에 보이는 모든 사물, 세상에 존재하는 모든 것

 

➤ 객체와 인스턴스의 차이는 무엇일까?

Object 와 instance는 같은 때 사용하는데 차이가 있을까?

여러 글들에서 객체와 인스턴스의 차이를 두지 않고 있는데 용어의 사용에서 차이가 있다고 해서 궁금해졌다.

이 부분은 정확하진 않지만 많은 글들을 참고해봤다.

객체는 객체를 선언하고 아직 메모리를 차지하기 전의 상태를 얘기하고

인스턴스는 실제로 메모리가 할당된 상태를 말한다고 한다. (인스턴스화 한다고 한다)

객체는 청사진을 토대로 이런 물건을 만들어야겠다 라고 생각하고 아직 실물은 없는 거고

인스턴스는 실제로 물건을 만들어서 실물로 만든 상태인 것이다...

왜 이 두가지에 차이를 두는지 아직은 잘 모르겠다. 🤔

공부하다보면 언젠가 깨닫게 되지 않을까..

 

※ instantiate (인스턴스화) : 클래스로부터 객체를 만드는 과정, 컴파일러가 클래스 정보를 토대로 힙 메모리에 객체를 만들 공간을 지정하고 클래스 정보를 옮겨서 인스턴스를 만드는 일련의 과정을 의미합니다. 쉽게 말해 청사진을 토대로 만드는 과정

 

 

Class

 

- 클래스명은 일반적으로 대문자로 시작

- 객체를 여러개 만들어낼 수 있는 틀, 설계도, 청사진

- 필드(속성), 메소드(기능), 생성자로 구성됨

 

 

field (멤버변수)

 

클래스 내의 속성을 나타냄

 

 

자바의 변수의 종류

 

1. 클래스 변수 (=static 변수 =정적변수)

 

static int serialNum = 1001;

 

  • 클래스가 생성될 때 함께 생성됨
  • 인스턴스 변수와 같은 위치에서 선언하지만 static이 앞에 붙음
  • 선언된 클래스에 존재
  • 인스턴스로 클래스 변수에 접근가능 ☞ 인스턴스명.변수명
  • 클래스명으로도 접근 가능 ☞ 클래스명.변수명
  • 어떻게 접근하든 같은 클래스 변수로 도착함
  • 보통 하나의 변수를 여러 객체에서 공통으로 사용할 때 클래스 변수로 만듬

 

 

2. 인스턴스 변수

 

int inst = 100;

 

  • 인스턴스가 생성될 때마다 생기는 변수
  • 인스턴스마다 다른 힙 메모리에 저장됨
  • 반드시 인스턴스를 생성해야만 접근 가능

 

 

3. 지역변수

 

  • 메소드에 선언된 변수
  • 메소드가 끝나면 스택 메모리에서 사라짐

 

 

static

 

  • 클래스의 멤버에 사용가능
  • static이 붙은 멤버는 정적멤버 (static member)
  • static이 붙은 변수(클래스 변수)는 인스턴스를 생성할 때마다 양산되지 않음
  • 클래스명과 포인터로도 접근 가능
  • 프로그램이 실행될 때 딱 한번만 스택 메모리 공간에 공간 할당됨

 

 

method

 

  •  클래스 내의 기능을 담당
  •  함수
  •  메소드는 클래스변수와 같은 공간에 저장됨(메소드 영역)  같은 클래스로 만든 인스턴스는 모두 하나의 메소드를 공유함
  •  method signature와 method body 로 나뉨

 

접근제어자 반환타입 메서드명(매개 변수) { // method signature

메소드 내용 // method body

}

 

  • 반환타입이 없으면 void ☞ return 안써줘도됨
  • 반환타입이 있으면 return 뒤에 반드시 같은 반환타입을 넣어줘야함
  • 반환타입은 기본 변수뿐 아니라 참조 변수도 가능
  • 포인트(.)를 이용해서 인스턴스 내부의 메소드 호출
  • 메소드 호출 시 괄호() 안에 넣어주는 값을 인자(argument)라고 부름

 

 

method Overloading

 

  • 클래스 안에 같은 이름의 메소드를 여러개 정의하는 것
  • overload는 사전적으로 과적하다, 부담을 지우다 라는 의미
  • 같은 이름의 메소드를 여러개 가지면서 매개변수의 유형과 개수가 다르게하는 기술
  • 자주사용하는 오버로딩으로는 println() 메소드가 있음
  • 안에 넣어주는 인자에 따라 다른 println()메소드 호출됨

 

 

 

 

조건문

 

조건이 참이면 실행

 

if 문

 

if (조건식) {

     실행문;

}

 

  • 참이나 거짓으로 판별할 수 있는 식을 ‘조건식’ 안에 넣어주고
  • 참이면 중괄호 안의 코드를 실행
  • 블록(block) : 중괄호를 이용해 문장을 하나의 단위로 묶은 것

 

if else

  • else 는 말 그대로 그렇지 아니면...
  • if 문의 조건식이 false라서 실행문을 실행하지 않았을 때 밑에 else if / else 로 이어서 작성할 수 있음

 

 

 

Switch문

 

변수가 어떤 값을 갖느냐에 따라 실행문이 선택됨

변수의 값에 따라 실행문 다르게 할 때 if문 보다 코드 간결

 

 

switch (변수) {
	case 1:
		실행문;
		break;
	case 2:
		실행문;
		break;
	...

}

 

동일한 값을 갖는 case로 가서 실행

동일한 값이 없으면 default로 가서 실행(default는 생략 가능)

case 마다 break문을 작성하지 않으면 모든 case에 있는 실행문을 실행 (fall through)

해당 실행문만 실행시키려면 실행문 끝에 break문을 써줘야함

switch의 변수에는 int, char 뿐 아니라 java 7부터 String 타입도 가능

 

 

참고) 향상된 switch문

  • java 14부터 향상된 switch문(enhanced switch문) 생김
  • 여러 조건에 따라 , 로 구분하여 한번에 묶을수 있음
  • ' : ' 대신에 ' -> ' 사용(람다 스타일), break문 생략
  • ' -> ' 사용하고 실행문이 2개 이상이면 중괄호{}로 묶음
switch (day) {
	case Monday, Tuesday -> System.out.println("피곤");
    case Wednesday, Thursday -> System.out.println("🐶 피곤");
    case Friday -> {System.out.println("🔥 금");
    				nextDay = sat;
                    }                
}

 

 

 

 

반복문

 

반복횟수를 알고 있을 떄는 for문, 조건에 따라 반복할 때는 while문 주로 사용

 

for문

조건식이 참인 동안 반복

 

for(초기화; 조건식; 증감식) {

반복문;

}

초기화 변수는 주로 i(iterator, 반복계수)를 많이 사용

 

향상된 for문(enhanced for)

배열이나 객체에서 항목 개수만큼 반복할 때 주로 사용

for(변수 : 배열){

반복문;

}

 

 

while문

조건식이 true인 동안 계속 반복

 

while (조건식) {

반복문;

}

 

for문의 증감식이 필요하면 반복문 밑에 넣어주면 됨

또는 조건문

 

 

do-while문

 

do {

실행문

}
while(조건식);

실행문을 조건식을 확인하기 전에 한번 실행

 

 

 

break문

break문은 제어문에서 흐름을 나갈 떄 사용

주로 반복문 내에 if 문 넣어서 사용

break만 있을 경우 제일 가까운 반복문만 종료, 바깥쪽 반복문은 이어서 진행

빠져나가고 싶은 반복문이 있으면 해당 문법 앞에 라벨 붙이면됨

ex) Outer : for()

 

 

 

continue문

반복문의 조건식으로 이동하여 진행

주로 반복문 내에 if문 넣어서 사용

 

 

※ 그 외

 

String.format()은 반환형이 String 타입이기 때문에 String형 변수에 바로 대입해줄 수 있음

 

IntelliJ 단축키

debug : Ctrl + Alt + D

자동 줄정렬 : Cmd + Alt + L

 

랜덤 함수

Math.random()

double형으로 0.0이상 1.0 미만 사이의 값을 반환하는 함수

난수를 만들고 싶을 때 자주 사용

 

두 수 중 큰 수/작은 수를 찾는 함수

Math.max(int a, int b)

Math.min(int a, int b)

double, float, long형도 가능

 

 

'TIL(Today I Learned)' 카테고리의 다른 글

5/10 (화) 객체지향 프로그래밍 기초  (0) 2022.05.11
5/9 (월) 자바 배열 / 계산기 만들기  (0) 2022.05.09
5/4 (수) JAVA 기초  (0) 2022.05.05
5/3 (화) Git 기초  (0) 2022.05.04
5/2 (월) Linux 기초2  (0) 2022.05.03

 

JAVA란?

 

1996년에 나온 객체 지향 프로그래밍 언어(Object Oriented Programming, OOP)

운영체제에 독립적으로 실행 가능 → 다양한 운영체제가 공존하는 웹 환경에 적합한 언어로 지금도 전세계적으로 많이 쓰이는 언어

‘Write Once, Run Anywhere’ 슬로건으로 빠르게 많은 사용자 확보함

 

 

자바의 특징

 

운영체제에 독립적

객체지향언어 (OOP)

함수형 프로그래밍 지원

자동 메모리 관리(Garbage Collection)

 

 

 

JVM과 JDK

 

JVM (Java Virtual Machine)

 

  • 자바 프로그램을 실행시키는 도구
  • JRE(Java Runtime Environment, 자바 실행 환경)이나 JDK(Java Development kit, 자바 개발 키트)를 설치하면 자동으로 설치
  • 자바가 운영체제에 독립적인 건 JVM 때문에 가능
  • 자바 코드로 작성한 프로그램을 해석해 실행하는 별도의 프로그램
  • JVM을 거치기 때문에 자바는 C/C++ 보다는 속도가 느린 편 이지만 JVM 내부의 최적화된 JIT(just-in-time) 컴파일러를 통해 속도를 크게 개선

 

참고) JIT(Just-int-tim) 컴파일 이란?

동적 번역(dynamic translation)이라고도 함

프로그램을 실제 실행하는 시점에 기계어로 번역하는 컴파일 기법

컴퓨터 프로그램을 만드는 방법은 크게 두가지 (인터프리트 방식과 정적 컴파일 방식)

인터프리트 방식은 실행 중 프로그래밍 언어를 읽어가면서 해당 기능에 대응하는 기계어 코드를 실행

정적 컴파일은 실행하기 전에 프로그램 코드를 기계어로 번역

JIT 컴파일러는 두가지 방식을 혼합한 방식, 실행 시점에 인터프리트 방식으로 기계어 코드를 생성하면서 그 코드를 캐싱하여 같은 함수가 여러번 불릴 때 매번 기계어 코드를 생성하는 것을 방지

 

 

JDK (Java Development Kit)

 

JRE : JVM + 표준 클래스 라이브러리

JDK : JRE + 개발에 필요한 도구

JDK는 OracleJDK와 OpenJDK 가 있음

 

 

 

클래스(class)

 

자바는 객체 지향 언어이기 때문에 모든 코드는 클래스 내에 작성

클래스는 쉽게 말하면 객체를 찍어낼 수 있는 툴

 

 

main 메서드

 

메서드란? 클래스 내부에 정의된 함수

자바로 만든 프로그램은 실행 시 main 메소드를 가장 먼저 실행

public static void main(String[] args){
	//코드
}

 

 

 

자바의 접근 제어자(Access Modifier)

 

public > protected > default > private

 

public : 모든 접근 허용

protected : 같은 패키지(폴더)에 있는 객체와 상속 관계의 객체들만 접근 가능

default : 같은 패키지(폴더)에 있는 객체들만 접근 가능

private : 같은 클래스 내에서만 접근 가능

 

 

static

 

메소드가 객체마다 속한 것이 아닌 클래스 자체에 속한 것임을 지정하는 키워드

 

 

return과 void

 

자바의 메소드는 리턴 값의 타입을 명시해줘야함

return 값이 없을 경우 return을 생략하거나 return만 쓰거나 아무것도 없다는 의미에서 return void 키워드 사용

 

 

 

자바의 타입(Type)

 

기본 타입(primitive type)

 

  • 데이터의 실제 값을 의미함
  • 정수 타입, 실수 타입, 문자 타입, 논리 타입

 

 

참조 타입(reference type)

 

  • 데이터가 저장된 주소값을 담고있음
  • 기본형을 제외한 나머지 타입

 

 

정수 타입 (Integer Type)

 

맨 앞은 부호 비트이고 나머지 비트에 숫자를 이진수로 표현함

ex) 1byte에 맨 앞을 제외한 7bit 를 이용해서 나타낼 수 있는 숫자는 2^7 (256) 개

      양수와 음수를 모두 표현해야 하므로 양수 0~127(128개) + 음수 -1 ~ -128(128개) 까지 표현 가능

 

타입 메모리 범위 기타
byte 1byte -128(-2^7) ~ 127(2^7 - 1) 1byte = 8bit
short 2byte -32,768(-2^15) ~ 32,767(2^15 - 1)  
int 4byte -2,147,483,648(-2 ^31) ~
2,147,483,647(2^
31 - 1)
integer(정수)의 약자
기본적으로 정수는 int형을 사용
long 8byte -9,223,372,036,854,775,808(-2^63) ~
9,223,372,036,854,775,807(2^
63 - 1)
변수에 값 할당할 때 long 형이라고 컴퓨터에 알려주기 위해서 값 뒤에 L이나 l을 붙여야함(안 붙이면 오류!)

 

 

 

실수 타입

 

float와 double

 

  • float : 4byte
  • double : 8byte

 

실수형 값 뒤에 float 형이면 F 또는 f , double 형이면 d를 붙여야 하지만 double은 실수 기본형이기 때문에 d 생략 가능

자바는 실수형을 저장할 때 부동소수점 표현방식 사용 → 소수점을 더 정밀하게 표현할 수록 오차 줄어듬

 

 

논리 타입

 

boolean형

true 또는 false 값만 가질 수 있음

JVM이 다룰 수 있는 데이터 최소 단위가 1byte 이기 때문에 boolean 형은 1byte 차지

 

 

 

문자 타입

 

char형(character)

단 하나의 문자만을 저장할 수 있음

자바는 유니코드에 기반하여 문자를 표현하기 때문에 하나의 유니코드를 저장 (2byte)

문자를 변수에 저장하면 문자에 해당하는 유니코드 값이 저장됨

변수 값은 유니코드 값으로 저장해도 되고 'A' 처럼 작은 따옴표 안에 문자 직접 넣어서 저장할 수도 있음

 

 

※ char형 정수형으로 변환하기

// char형의 숫자를 int형으로 변환하는 방법
char ch1 = '9';
int temp = ch1 - '0'; // 57 - 48 = 9

 

int형을 char로 변환할 때는 반대로 + '0' 해주면 됨

 

 

 

String

 

String은 문자열을 저장할 수 있는 클래스

참조 타입

String = " "

큰따옴표 안에 저장할 문자열 입력

 

 

String 타입을 선언하고 저장하는 여러가지 방법

 

String str1;
str1 = "문자열";	// 문자열 리터럴을 대입하는 방식

String str2 = "문자열";	// 문자열 초기화

String str3 = new String("문자열");	// new 연산자를 사용해서 객체를 생성 후 대입

System.out.println(str1 == str2);	// true
System.out.println(str2 == str3);	// false

 

 

str1과 str2은 같은 리터럴이기 떄문에 같다고 나오지만 str3은 새로운 String 객체를 만들어서 저장했기 때문에 주소값이 다르므로 false

 

 

대표적인 String 메소드

 

메소드 설명
char charAt(int index) 해당 문자열의 특정 인덱스에 해당하는 문자를 반환함
int compareTo(String str) 해당 문자열을 인수로 전달된 문자열과 사전편찬 순으로 비교함(전달된 문자열보다 작으면 음수, 크면 양수, 같으면 0)
int compareToIgnoreCase(String str) 해당 문자열을 인수로 전달된 문자열과 대소문자 구분없이 사전편찬 순으로 비교함
String concat(String str) 해당 문자열의 뒤에 인수로 전달된 문자열을 추가한 새로운 문자열을 반환함
int indexOf(int ch) / int indexOf(String str) /
int indexOf(char ch, int fromIndex) /
int indexOf(String str, int fromIndex)
해당 문자열에서 특정 문자나 문자열이 전달된 인덱스 이후에 처음으로 등장하는 위치의 인덱스를 반환함 (찾을 수 없으면 -1)
int lastindexOf(char ch) /
int lastIndexOf(char ch, int fromIndex)
해당 문자열에서 특정 문자가 전달된 인덱스 이후에 마지막으로 등장하는 위치의 인덱스를 반환함
String[] split(String regex) 해당 문자열을 전달된 정규 표현식에 따라 나눠서 반환함
String substring(int begin) /
String substring(int begin, int end)
해당 문자열을 전달된 인덱스 만큼 잘라서 새로운 문자열을 반환함
String toLowerCase() /
String toUpperCase()
Lower은 모든 문자열을 소문자로 변환 /
Upper은 모든 문자열을 대문자로 변환
String trim() 해당 문자열의 맨 앞과 맨 뒤에 포함된 모든 공백문자를 제거
length() 해당 문자열의 길이를 반환함
isEmpty() 해당 문자열의 길이가 0이면 true 반환 / 아니면 false 반환

 

 

 

StringTokenizer

 

문자열을 지정한 구분자로 쪼개주는 클래스

쪼개진 문자열을 토큰(Token)이라고 부름

실행하기 위해서는 java.util.StringTokenizer를 import 해야함

 

import java.util.StringTokenizer;

public class StringMethod {
    public static void main(String[] args) {
        // StringTokenizer 클래스 연습
        String str = "This is a string example using StringTokenizer";
        StringTokenizer tokenizer = new StringTokenizer(str);
        System.out.println(str);
        
        // int countTokens() : 남아있는 token의 개수를 반환
        System.out.println("total tokens:" + tokenizer.countTokens());
        
        // boolean hasMoreElements(), boolean hasMoreTokens() :
        // 현재 위치 뒤에 있는 문자열에서 하나 이상의 토큰을 사용할 수 있는 경우 true 반환
        // 그렇지 않을 경우 false 반환
        // StringTokenizer 내부적으로 어떤 위치의 토큰을 사용하였는지 기억
        while (tokenizer.hasMoreTokens()) {
            // Object nexElement(), String nextToken() : 다음의  토큰을 반환, 반환형이 다름
            System.out.println(tokenizer.nextToken());
        }
        System.out.println("total tockens: " + tokenizer.countTokens());
    }
}

 

<실행결과>

This is a string example using StringTokenizer

total tokens:7
This
is
a
string
example
using
StringTokenizer
total tockens: 0

 

 

 

StringBuilder

 

한번 생성된 String 클래스의 인스턴스는 문자열을 더할 때마다 새로운 인스턴스를 생성해야함

문자열을 더할 때 편리한 클래스

 

public class StringMethod {
    public static void main(String[] args) {
    
    	// StringBuilder 클래스 : 문자열을 쉽게 연결
        StringBuilder stringBuilder = new StringBuilder();
        
        // append(String str) method로 문자열 연결
        stringBuilder.append("문자열 ").append("연결");
        
        // 변수에 넣거나 출력시 toString() method 사용
        String example = stringBuilder.toString();
        System.out.println(stringBuilder);
        System.out.println(example);
   }
}

 

<실행결과>

문자열 연결
문자열 연결

 

 

 

StringBuffer

 

String 클래스는 인스턴스의 값을 읽기만 할 수 있고, 변경할 수는 없음

인스턴스의 값을 변경, 추가할 때 편리한 클래스

 

1. append() 메소드

 

인수로 전달받은 값을 문자열로 변환 후 해당 문자열의 마지막에 추가함

String 클래스의 concat() 메소드와 같은 결과지만 처리 속도가 훨씬 빠름

public class StringMethod {
    public static void main(String[] args) {
        StringBuffer buff = new StringBuffer("Java");
        System.out.println("문자열 : " + buff);
 
        System.out.println(buff.append(" programming"));
        System.out.println("append() 메서드 호출 후 문자열 : " + buff);
    }
}

<실행결과>

문자열 : Java
Java programming
append() 메서드 호출 후 문자열 : Java programming

 

 

 

2. capacity() 메소드

 

StringBuffer 인스턴스의 현재 버퍼 크기를 변환함

기본적으로 생성되는 여유 버퍼 크기인 16에 문자 개수 더한 총 값을 반환

StringBuffer str01 = new StringBuffer();
StringBuffer str02 = new StringBuffer("java");
System.out.println(str01.capacity());
System.out.println(str02.capacity());

<실행결과>

16
20

 

 

3. delete() 메소드

 

전달된 인덱스에 해당하는 부분 문자열을 해당 문자열에서 제거

deleteCharAt()메소드를 사용하면 특정 위치의 문자 한 개만을 제거할 수도 있음

StringBuffer temp = new StringBuffer("Java Oracle");
System.out.println("문자열 : " + temp);
System.out.println(temp.delete(4,8));
System.out.println(temp.deleteCharAt(1));
System.out.println("deleteCharAt() 메소드 호출 후 문자열 : " + temp);

<실행결과>

문자열 : Java Oracle
Javacle
Jvacle
deleteCharAt() 메소드 호출 후 문자열 : Jvacle

 

 

 

4. insert() 메소드

 

인수로 전달된 값을 문자로 변환 후 해당 문자열의 지정된 인덱스 위치에 추가

StringBuffer temp2 = new StringBuffer("Java Programming");
System.out.println("문자열 : " + temp2);
System.out.println(temp2.insert(4, "Script"));
System.out.println("insert() 메서드 호출 후 문자열 : " + temp2);

<실행결과>

문자열 : Java Programming
JavaScript Programming
insert() 메서드 호출 후 문자열 : JavaScript Programming

 

 


변수(variable)

 

타입이 데이터 종류

변수는 데이터의 저장공간을 의미

변수를 사용하는 이유?

  • 메모리에 데이터의 저장 공간을 확보
  • 다른 개발자와 협업 시 변수명을 붙여 소통
  • 데이터를 재사용

 

변수명 짓기

 

  • 영문자(대소문자), 숫자, _ 사용 가능
  • 카멜 케이스(camelCase)를 사용 🐫
  • 사용할 수 없는 변수명
    • 숫자로 시작하는 변수명
    • 자바에서 이미 사용 중인 예약어(reserved word)

 

 

상수(constant)

 

상수란? 프로그램에서 변하면 안되는 수

자바에서 final 예약어 사용해서 상수임을 알려줌

final double CALCULATOR_PI  = 3.14;

 

상수명은 일반적으로 대문자에 언더바(_)를 넣어 구분 (SCREAMING_SNAKE_CASE)

 

상수를 사용하는 이유?

  • 오타로 인한 에러를 방지
  • 변경하면 안되는 값을 보존
  • 데이터를 재사용

 

 

리터럴(literal)

 

리터럴이란? 프로그램에서 사용하는 모든 숫자, 문자, 논리값을 일컫는 말

변수나 상수에 넣어준 문자나 숫자를 리터럴, 혹은 리터럴 상수 라고 함

프로그램이 시작할 때 시스템에 같이 로딩되어 상수 풀(constant pool)에 놓임

 

 

 

 

타입 변환

 

boolean을 제외한 기본 타입 7개는 서로 타입을 변환 할 수 있음

 

자동 타입 변환

 

  1. 바이트 크기가 작은 타입에서 큰 타입으로 변환
  2. 덜 정밀한 타입에서 더 정밀한 타입으로 변환할 때
byte(1) -> short(2)/char(2) -> int(4) -> long(8) -> float(4) -> double(8)

 

 

수동 타입 변환

 

메모리가 더 큰 타입에서 작은 타입으로 변환 할 때는 자동으로 타입이 변환되지 않음

더 큰 데이터 타입을 작은 데이터 타입의 변수에 저장할 때 캐스팅(casting)함

캐스팅 연산자()를 사용, 괄호 안에 변환하고자 하는 타입 적어주면 됨

int intValue = 30;
byte byteValue = (byte)intValue;

타입을 변환하고자 하는 메모리 내에 담을 수 없는 숫자일 경우 전혀 다른 값이 나올 수 있음

 

 


 

산술 연산자

 

+ : 두 항을 더함

- : 앞의 항에서 뒤의 항을 뺌

* : 두 항을 곱함

/ : 앞의 항에서 뒤의 항을 나눈 몫을 구함

% : 앞의 항에서 뒤의 항을 나눈 나머지를 구함

 

 

비교 연산자

 

boolean을 제외한 나머지 기본 타입에 모두 사용 가능

 

대소 비교 연산자

>

<

>=

<=

 

 

등가 비교 연산자

 

== : 양쪽 항이 같으면 true, 다르면 false

!= : 양쪽 항이 다르면 true, 같으면 false

 

조건 연산자

 

조건식 ? 참일 때의 결과 : 거짓일 때의 결과;

 

 

연산자 우선순위

 

괄호/대괄호 > 부정/증감 연산자 > 곱셈/나눗셈 연산자 > 대소 비교 연산자 > AND 연산자 > OR 연산자 > 조건 연산자

> 대입/할당 연산자

 

 

콘솔 입출력(I/O)

 

콘솔 출력

 

System 클래스는 자바 표준 입출력 스트림

System.out.println() : 출력하고 줄바꿈

System.out.print()

System.out.printf() : 형식대로 출력하기

 

 

콘솔 입력

 

Scanner 클래스를 import 해와야함

import java.util.Scanner;

Scanner scanner = new Scanner(System.in);
String inputValue = scanner.nextLine();

System.out.println(inputValue);

 

입력한 값이 콘솔에 출력됨

 

 

 

그외 메소드

 

Math.abs(int/long/double/float) : 절대값 구하는 메소드

String.format( ) : 문자열 형식을 지정하는 메소드 (C언어의 printf 함수처럼 사용 가능)

  • %s / %S : 문자열
  • %b / %B : boolean
  • %d : 정수형
  • %f : float 형
  • %% : 퍼센트(%) 출력

 

 

 

'TIL(Today I Learned)' 카테고리의 다른 글

5/9 (월) 자바 배열 / 계산기 만들기  (0) 2022.05.09
5/6 (금) 자바 제어문  (0) 2022.05.07
5/3 (화) Git 기초  (0) 2022.05.04
5/2 (월) Linux 기초2  (0) 2022.05.03
5/2 (월) Linux 기초  (0) 2022.05.02
1 2