[Java] What is Java Programming?

원알렉스·2020년 5월 28일
0

Java

목록 보기
1/7
post-thumbnail

Java 언어의 장단점

장점

  • 운영체제에 독립적이다.
    • JVM에서 동작하기 때문에, 특정 운영체제에 종속되지 않는다.
  • 객체지향 언어이다.
    • 객체지향적으로 프로그래밍 하기 위해 여러 언어적 지원을 하고 있다.(캡슐화, 상속, 추상화, 다형성 등)
    • 객체지향 패러다임의 특성상 비교적 이해하고 배우기 쉽다.
  • 자동으로 메모리 관리를 해준다.
    • JVM에서 Garbage Collector라고 불리는 데몬 스레드에 의해 GC(Garbage Collection)가 일어난다. GC로 인해 별도의 메모리 관리가 필요 없으며 비즈니스 로직에 집중할 수 있다.
  • 오픈소스이다.
    • 정확히 말하면 OpenJDK가 오픈소스이다.
    • 많은 Java 개발자가 존재하고 생태계가 잘 구축되어 있다. 덕분에 오픈소스 라이브러리가 풍부하며 잘 활용한다면 짧은 개발 시간 내에 안정적인 어플리케이션을 쉽게 구현할 수 있다.
  • 멀티 스레드를 쉽게 구현할 수 있다.
    • Java는 스레드 생성 및 제어와 관련된 라이브러리 API를 제공하고 있기 때문에 실행되는 운영체제에 상관없이 머리 스레드를 쉽게 구현할 수 있다.
  • 동적 로딩(Dynamic Loading)을 지원한다.
    • 어플리케이션이 실행될 때 모든 객체가 생성되지 않고, 각 객체가 필요한 시점에 클래스를 동적 로딩해서 생성한다. 또한 유지보수 시 해당 클래스만 수정하면 되기 때문에 전체 어플리케이션을 다시 컴파일할 필요가 없다. 따라서 유지보수가 쉽고 빠르다.

단점

  • 비교적 속도가 느리다.
    • Java는 한번의 컴파일링으로 실행 가능한 기계어가 만들어지지 않고 JVM에 의해 기계어로 번역되고 실행하는 과정을 거치기 때문에 C나 C++의 컴파일 단계에서 만들어지는 완전한 기계어보다는 속도가 느리다. 그러나 하드웨어의 성능 향상과 바이트 코드를 기계어로 변환해주는 JIT 컴파일러 같은 기술 적용으로 JVM의 기능이 향상되어 속도의 격차가 많이 줄어들었다.
  • 예외처리가 불편하다.
    • 프로그래머 검사가 필요한 예외가 등장한다면 무조건 프로그래머가 선언을 해줘야 한다.

Java의 접근 제어자의 종류와 특징

  • public
    • 표시: +
    • 특징: 어떤 클래스의 객체에서든 접근 가능
  • private
    • 표시: -
    • 특징: 이 클래스에서 생성된 객체들만 접근 가능
  • protected
    • 표시: #
    • 특징: 이 클래스와 동일 패키지에 있거나 상속 관계에 있는 하위 클래스의 객체들만 접근 가능
  • package
    • 표시: ~
    • 특징: 동일 패키지에 있는 클래스의 객체들만 접근 가능

Java의 데이터 타입

기본 데이터 타입(Primitive Data Type)

  • 정수형: byte, short, int, long
  • 실수형: float, double
  • 논리형: boolean(true/false)
  • 문자형: char
  • 기본 타입의 크기가 작고 고정적이기 때문에 메모리의 Stack 영역에 저장된다.

참조 타입(Reference Data Type)

  • 참조 타입의 종류는 class, array, interface, Enumeration이 있다.
    • 기본형을 제외하고는 모두 참조형이다.
    • new 키워드를 이용하여 객체를 생성하여 데이터가 생성된 주소를 참조하는 타입이다.
    • String, StringBuffer, List, 개인이 만든 클래스 등
    • String과 배열은 참조 타입과 달리 new 키워드 없이 생성이 가능하지만 기본 타입이 아닌 참조 타입이다.
  • 참조 타입의 데이터의 크기가 가변적, 동적이기 때문에 동적으로 관리되는 Heap 영역에 저장된다.
  • 더 이상 참조하는 변수가 없을 때 Garbage Collection에 의해 파괴된다.
  • 참조 타입은 값이 저장된 곳의 주소를 저장하는 공간으로 객체의 주소를 저장한다.(Call-By-Value)

OOP의 4가지 특징

[OOP 참고]

  1. 추상화(Abstraction)
    • 구체적인 사물들의 공통적인 특징을 파악해서 이를 하나의 개념(집합)으로 다루는 것.
  2. 캡슐화(Encapsulation)
    • 정보 은닉(Information Hiding): 필요가 없는 정보는 외부에서 접근하지 못하도록 제한하는 것.
  3. 일반화 관계(Inheritance, 상속)
    • 여러 개체들이 가진 공통된 특성을 부각시켜 하나의 개념이나 법칙으로 성립시키는 과정.
  4. 다형성(Polymorphism)
    • 서로 다른 클래스의 객체가 같은 메시지를 받았을 때 각자의 방식으로 동작하는 능력.

객체지향과 절차지향 프로그래밍의 차이

절차지향 프로그래밍

  • 실행하고자 하는 절차를 정하고, 이 절차대로 프로그래밍하는 방법이다.
  • 목적을 달성하기 위한 일의 흐름에 중점을 둔다.

객체지향 프로그래밍

  • 실제 세상의 물체를 객체로 표현하고, 이들 사이의 관계, 상호 작용을 프로그램으로 나타낸다.
  • 객체를 추출하고 객체들의 관계를 결정하고 이들의 상호작용에 필요한 함수와 변수를 설계 및 구현한다.
  • 객체 지향의 핵심은 연관되어 있는 변수와 메소드를 하나의 그룹으로 묶어서 그룹핑하는 것이다.
  • 사람의 사고와 가장 비슷하게 프로그래밍을 하기 위해서 생성된 기법
  • 하나의 클래스를 바탕으로 서로 다른 상태를 가진 인스턴스를 만들면 서로 다른 행동을 하게 된다. 즉, 하나의 클래스가 여러 개의 인스턴스가 될 수 있다는 점이 객체 지향이 제공하는 가장 기본적인 재활용성이라고 할 수 있다.

Java의 non-static 멤버와 static 멤버의 차이

non-static 멤버

  • 공간적 특성: 멤버는 객체마다 별도로 존재한다.
    • 인스턴스 멤버라고 부른다.
  • 시간적 특성: 객체 생성 시에 멤버가 생성된다.
    • 객체가 생길 때 멤버도 생성된다.
    • 객체 생성 후 멤버 사용이 가능하다.
    • 객체가 사라지면 멤버도 사라진다.
  • 공유의 특성: 공유되지 않는다.
    • 멤버는 객체 내에 각각의 공간을 유지한다.

static 멤버

  • 공간적 특성: 멤버는 클래스당 하나가 생성된다.
    • 멤버는 객체 내부가 아닌 별도의 공간에 생성된다.
    • 클래스 멤버라고 부른다.
  • 시간적 특성: 클래스 로딩 시에 멤버가 생성된다.
    • 객체가 생기기 전에 이미 생성된다.
    • 객체가 생기기 전에도 사용이 가능하다.(즉, 객체를 생성하지 않고도 사용할 수 있다.)
    • 객체가 사라져도 멤버는 사라지지 않는다.
    • 멤버는 프로그램이 종료될 때 사라진다.
  • 공유의 특성: 동일한 클래스의 모든 객체들에 의해 공유된다.

Java의 main 메소드가 static인 이유

static 키워드

  • static 멤버는 클래스 로딩(프로그램 시작) 시 메모리에 로드되어 인스턴스를 생성하지 않아도 호출이 가능하다.

main 메소드가 static인 이유

  • public static void main(String[] args){...}
  • 위와 같은 형식은 Java에서의 main() 관례이다. 위와 같은 시그니처를 가진 메소드가 없으면 실행되지 않는다.
  • JVM은 인스턴스가 없는 클래스의 main()을 호출해야하기 때문에 static이어야 한다.

JVM과 static

  • 코드를 실행하면 컴파일러가 .java 코드를 .class(byte code)로 변환한다.
  • 클래스 로더가 .class 파일을 메모리 영역(Runtime Data Area)에 로드한다.
  • Runtime Data Area 중 Method Area(=Class Area =Static Area)라고 불리는 영역에 Class Variable이 저장되는데, static 변수 또한 여기에 포함된다.
  • JVM은 Method Area에 로드된 main()을 실행한다.

Java의 final 키워드

final 키워드

  • 개념: 변수나 메소드 또는 클래스가 변경 불가능하도록 만든다.
  • 원시(Primitive) 변수에 적용 시
    • 해당 변수의 값은 변경이 불가능하다.
  • 참조(Reference) 변수에 적용 시
    • 참조 변수가 힙(Heap) 내의 다른 객체를 가리키도록 변경할 수 없다.
  • 메소드에 적용 시
    • 해당 메소드를 오버라이딩을 할 수 없다.
  • 클래스에 적용 시
    • 해당 클래스의 하위 클래스를 정의할 수 없다.

클래스, 객체, 인스턴스의 차이

클래스(Class)

  • 객체를 만들어 내기 위한 설계도 혹은 틀
  • 연관되어 있는 변수와 메소드의 집합

객체(Object)

  • 소프트웨어 세계에 구현할 대상
  • 클래스에 선언된 모양 그대로 생성된 실체
  • 클래스의 인스턴스라고도 부른다.
  • 객체는 모든 인스턴스를 대표하는 포괄적인 의미를 갖는다.
  • OOP의 관점에서 클래스의 타입으로 선언되었을 때 객체라고 부른다.

인스턴스(Instance)

  • 설계도를 바탕으로 소프트웨어 세계에 구현된 구체적인 실체
    • 즉, 객체를 소프트웨어에 실체화 하면 그것을 "인스턴스"라고 부른다.
    • 실체화된 인스턴스는 메모리에 할당된다.
  • 인스턴스는 객체에 포함된다고 볼 수 있다.
  • OOP의 관점에서 객체가 메모리에 할당되어 실제 사용될 때 "인스턴스"라고 부른다.
  • 추상적인 개념과 구체적인 객체 사이의 관계에 초점을 맞출 경우에 사용한다.
    • "~의 인스턴스" 의 형태로 사용된다.
    • 객체는 클래스의 인스턴스이다.
  • 즉, 인스턴스라는 용어는 반드시 클래스와 객체 사이의 관계로 한정 지어서 사용할 필요는 없다.
  • 인스턴스는 어떤 원본으로부터 "생성된 복제본"을 의미한다.
// 클래스
public class Animal {
	...
}
public class Main {
    public static void main(String[] args) {
    	Animal cat, dog;  // 객체
        
        // 인스턴스화
        cat = new Animal();  // cat은 Animal 클래스의 "인스턴스"
        dog = new Animal();  // dog는 Animal 클래스의 "인스턴스"
    }
}

오버로딩과 오버라이딩의 차이

오버로딩(Overloading)

  • 두 메소드가 같은 이름을 갖고 있으나 인자의 수나 자료형이 다른 경우

오버라이딩(Overriding)

  • 상위 클래스의 메소드와 이름과 이름과 용례(signature)가 같은 함수를 하위 클래스에 재정의하는 것
  • 상속 관계에 있는 클래스 간에 같은 이름의 메소드를 정의

Call by Value와 Call by Reference의 차이

Call by Value (값에 의한 호출)

  • 함수가 호출될 때, 메모리 공간 안에서 함수를 위한 별도의 임시 공간이 생성된다.
  • 함수 호출시 인자로 전달되는 변수의 값을 복사하여 함수의 인자로 전달한다.
  • 복사된 인자는 함수 안에서 지역적으로 사용되는 local value의 특성을 가진다.
  • 따라서 함수 안에서 인자의 값이 변경되어도, 외부의 변수의 값은 변경되지 않는다.

Call by Reference (참조에 의한 호출)

  • 함수가 호출될 때, 메모리 공간 안에서 함수를 위한 별도의 임시 공간이 생성된다.
  • 함수 호출시 인자로 전달되는 변수의 Reference를 전달한다.(해당 변수를 가리키는 주소값)
  • 따라서 함수 안에서 인자의 값이 변경되면, 인자로 전달된 변수의 값도 함께 변경된다.

Java는 항상 Call by Value이다.

  • 여기서 value란?
    • 기본 자료형의 값 또는 객체에 대한 Reference
  • 기본 자료형의 경우 해당하는 변수의 값을 복사해서 전달한다.
  • 참조 자료형의 경우 해당하는 변수가 가지는 값이 Reference이므로 인자로 넘길 때 Call by Value에 의해 변수가 가지고 있는 Reference가 복사되어 전달된다.
class Person {
    private String name;
    public Person(String name) {
    	this.name = name;
    }
    public setName(String name) {
    	this.name = name;
    }
    @Override
    public String toString() {
    	return "name is " + this.name;
    }
}
public class FunctionCallTest {
    public static void assignNewPerson(Person p) {
    	p = new Person("park");
    }
    public static void changeName(Person p) {
    	p.setName("park");
    }
    public static void main(String[] args) {
    	Person p = new Person("kim");
        
        assignNewPerson(p);
        System.out.println(p);  // name is kim
        
        changeName(p);
        System.out.println(p);  // name is park
    }
}
public class FunctionCallTest2 {
    // 참조변수 array 자체의 Reference가 아닌 array가 "저장하고 있는 주소값(Value)
    public static void changeContent(int[] array) {
    	// main()에 있는 array 변경
    	array[0] = 10;
        array[1] = 11;
    }
    public static void changeRef(int[] array) {
    	// main()에 있는 array 변경 안함
    	array = new int[2];
        array[0] = 20;
        array[1] = 21;
    }
    public static void main(String[] args) {
    	int[] array = new int[2];
        array[0] = 0;
        array[1] = 1;
        
        changeContent(array);
        for(int item: array) {
        	System.out.print(item + " ");  // 10 11
        }
        
        changeRef(array);
        for(int item: array) {
        	System.out.print(item + " ");  // 10 11
        }
    }
}

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

추상 메소드 (Abstract Method)

  • abstract 키워드와 함께 원형만 선언되고, 코드는 작성되지 않은 메소드
public abstract String getName();  // 추상 메소드
public abstract String fail() { return "Fail"; }  // 추상 메소드 x

추상 클래스 (Abstract Class)

  • abstract 키워드로 선언된 클래스
    • 추상 메소드를 최소 한개 이상 가지고 abstract로 선언된 클래스
      • 최소 한개의 추상 메소드를 포함하는 경우 반드시 추상 클래스로 선언해야 한다.
  • 추상 클래스의 구현
    • 서브 클래스에서 슈퍼 클래스의 모든 추상 메소드를 오버라이딩하여 실행가능한 코드로 구현한다.
  • 추상 클래스의 목적
    • 객체를 생성하기 위함이 아니며, 상속을 위한 부모 클래스로 활용하기 위한 것이다.
    • 여러 클래스들의 공통된 부분을 추상화하여 상속받는 클래스에게 구현을 강제화하기 위한 것이다.
    • 즉, 추상 클래스의 추상 메소드를 자식 클래스가 구체화하여 그 기능을 확장하는 데 목적이 있다.
abstract class Shape {
    Shape() { ... }
    void edit() { ... }
    abstract public void draw();  // 추상 메소드
}
class Circle extends Shape {
    public void draw() { System.out.println("Circle"); }  // 추상 메소드 오버라이딩
    void show() { System.out.println("Show Circle"); }
}

인터페이스 (Interface)

  • 추상 메소드와 상수만을 포함하며, interface 키워드를 사용하여 선언한다.
  • 인터페이스의 구현
    • 인터페이스를 상속받고, 추상 메소드를 모두 구현한 클래스를 작성한다.
    • implements 키워드를 사용하여 구현한다.
  • 인터페이스의 목적
    • 상속받을 서브 클래스에게 구현할 메소드들의 원형을 모두 알려주어, 클래스가 자신의 목적에 맞게 메소드를 구현하도록 하는 것이다.
    • 구현 객체의 같은 동작을 보장하기 위한 목적이 있다.
    • 즉, 서로 관련이 없는 클래스에서 공통적으로 사용하는 방식이 필요하지만 기능을 각각 구현할 필요가 있는 경우에 사용한다.
  • 인터페이스의 특징
    • 인터페이스는 상수 필드와 추상 메소드만으로 구성된다.
    • 모든 메소드는 추상 메소드로서, abstract public 속성이며 생략 가능하다.
    • 상수는 public static final 속성이며, 생략하여 선언할 수 있다.
    • 인터페이스를 상속받아 새로운 인터페이스를 만들 수 있다.
      • interface MobilePhone extends Phone { ... }
interface Phone {
    int BUTTONS = 20;  // 상수 필드, public static final 생략
    void sendCall();  // 추상 메소드, abstract public 생략
    abstract public void receiveCall();  // 추상 메소드
}
class FeaturePhone implements Phone {
    // Phone의 모든 추상 메소드 구현
    public void sendCall() { ... }
    public void receiveCall() { ... }
    
    // 추가적인 메소드 생성 가능
    public int clickButton() { ... }
}

추상 클래스와 인터페이스의 공통점

  • 객체는 생성할 수 없다.
  • 선언만 있고 구현 내용은 없다.
  • 서브 클래스가 메소드의 구체적인 동작을 구현하도록 책임을 위임한다.

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

  • 서로 다른 목적을 가지고 있다.
    • 추상 클래스는 추상 메소드를 서브 클래스가 구체화하여 그 기능을 확장하는 데 목적이 있다.(상속을 위한 슈퍼 클래스)
    • 인터페이스는 서로 관련이 없는 클래스에서 공통적으로 사용하는 방식이 필요하지만 기능을 각각 구현할 필요가 있는 경우에 사용한다.(구현 객체의 같은 동작을 보장)
  • 추상 클래스는 클래스이지만 인터페이스는 클래스가 아니다
  • 추상 클래스는 단일 상속만 되지만 인터페이스는 다중 상속이 가능하다.
  • 추상 클래스는 "is a kind of", 인터페이스는 "can do this"
profile
Alex's Develog 🤔

0개의 댓글