언어/Java

[Java] Java란?

차가운오미자 2021. 6. 25. 16:35

구조적 프로그래밍과 객체지향적 프로그래밍

1. 구조적 프로그래밍:

- 기능별로 나누어서 모듈을 통해 프로그래밍한다.

- 장점: 빠르다, 구현이 쉽다

- 단점: 유지보수가 비싸다

 

2. 객체지향적 프로그래밍

- 현실세계를 묘사해서 프로그래밍한다.

- 장점: 빠른 변화에 빠르게 적응할 수 있다. 

 

객체지향적 프로그래밍

어떻게 하면 현실 세계를 묘사할 수 있을까? 

1. 구성요소 파악

ex) 은행: 은행직원, 지점, 은행업무 등등
만약 구조적프로그래밍(기능별 분류) 이었다면 은행업무: 예금>입,출금/ 대출>담보,신용

2. 구성요소 간 데이터 흐름 파악

구성요소를 어떻게 프로그램으로 표현하는가?

클래스를 이용해서 현실과 비슷하게 만든다. 즉, 구성요소의 상태(데이터 값)와 행위(행동) 파악해 이를 변수와 메소드로 만든다.

도구: class (객체 모델링의 수단) = 상태(field)+행위(method)

 

Java Virtual Machine

.class bytecode 를 실행시키는 주체는 JVM이다. JVM과 API(라이브러리)를 합친 것이 JRE이다.
class를 기반으로 메모리에 공간을 확보한 것을 instance라고 부른다. 

 

소스파일 만들기

  • new - project - java project - perspective 바꿔줘? -yes
  • class 이름은 반드시 영문이어야 하고 첫 글자는 대문자여야 한다.
  • public class를 선언하는 경우 class 이름하고 파일명하고 일치해야 한다. 
  • 한 파일에 public class는 하나만 존재해야한다. 하지만 public class없이 class만 여러개 있어도 된다.
  • string은 일종의 문자변수
  • C언어에서는 current_speed형태처럼 네이밍하는 것이 일반적이지만 자바에서는 두단어 혼합형에서 대문자를 사용
  • method로 field의 값을 변하게 만들 수 있다. (클래스 개념의 기본 아이디어)
  • 메소드와 필드의 위치 순서는 크게 상관없다. 하지만 관용적으로 맨 위에는 필드 나온 후 메소드가 나온다.

데이터타입 2가지

- primitive data type

기본형, 기본적으로 제공되는 타입, 8가지

  1. byte
  2. short
  3. int
  4. long(정수)
  5. float
  6. double (실수)
  7. char (문자)
  8. boolean (논리): true & false 를 저장하는 데이터 타입이 따로 있음

대부분 int 타입을 사용한다. 나중에 결국 다 4바이트로 바뀌어서 처리되기 때문에 처리 속도가 제일 빠르기 때문이다.

- reference data type

class는 ADT (abstract data type)이다. class 같은 걸 reference data type이라고 할 수 있다. 

인스턴스화 될 수 있는 클래스를 말한다. 배열도 이에 포함된다. 

 

main() method

main() 메소드는 프로그램의 시작포인트이다. 프로그램을 시작하면 클래스 내에서 main을 찾아 우선 실행한다.

public static void main(String arfgs[]) {
		
	}

 

  • 이클립스에서는 main 쓰고 ctrl+space==> main method를 띄워준다. 
  • [] 인자: 배열
  • public static void main(String[] args) 도 똑같이 메인 함수이다.
  • System.out.println : sysout 하고 ctrl+space하면 뜸

main method를 호출하는 주체는JVM이다.
method를 호출할라면 instance가 있어야 한다. 근데 main은 인스턴스 만들어지기 전에 호출되어야하기 때문에 static이 붙는 것이다. 

JVM도 하나의 자바 프로그램이라고 생각하면 된다. JVM도 패키지로 이루어져있다. 그럼 이 main을 호출하기 위해서는 다른 패키지(main이 있는 패키지)에서 가져올 수 있는 거여야 한다. 그래서 public이 붙어야 하는 것!

 

instance(객체)란

  • class를 기반으로 확보한 메모리의 일정공간이다.
  • Car타입 변수 car: 클래스 안에 있는 변수들을 다 활용할 수 있게 됨 (owner, cc, currentSpeed)
  • new(): instance 만들때 new class(/constructor)() 이런식으로 선언한다. 
  • Car 클래스로 instance 를 만들었기에 owner, cc, currentSpeed에 맞는 공간이 만든 instance 안에 생김
  • car라는 지역변수 안에는 메모리 주소의 해쉬코드값이 들어감(=>메모리, 포인터 연산 불가), 그리고 그 주소는 instance를 가리키고 있음

생성자

=> instance를 만들어내는 것, new 생성자

 

특징:

  1. 메소드처럼 생겼다. 하지만 리턴하지 않는다. 
  2. 이름이 클래스 이름과 같아야 한다.
  3. 모든 클래스는 적어도 1개 이상의 생성자를 가진다. 만약 생성자를 선언해주지 않으면 컴파일러가 기본 constructor을 생성해서 넣어준다. 
  4. 기본 생성자(default constructor): 인자도, 하는 일도 없는 생성자
  5.  

메소드(method)


행위: ex) 전진한다, 후진한다, 와이퍼를 움직인다 
=> 이렇게 객체가 하는 행위를 method라고 부름(c의 function과 거의 같음)

method의 이름이 같아도 만약 method의 signature가 다르면 (인자가 다른경우-개수, 타입) 다른 method로 구분된다. 이것을 method overloading이라고 부른다. 

 

메모리 영역

JVM이 프로그램을 실행할 때 메모리를 5가지 영역으로 구분해서 사용한다. 

JVM이 관리하는 메모리 영역: 

1. Stack: 메소드가 호출되면 스택의 일정 공간이 할당됨, 해당 method에서 선언된 지역변수가 들어감 (호출된 메소드를 위한 공간)


2. Heap
 2.1. Register 실행 포인터 있는 곳
 2.2. Runtime constant pool: 프로그램에서 사용하는 상수들이 저장된 곳
 2.3. Method Area: class자체에 대한 정보, 해당 클래스를 처음 사용할 때 딱 한 번 메모리에 적힌다. (field, method가 뭐가 있는지만, 클래스 이름)
 2.4. Heap: 모든 instance 가 담긴 곳
Register 과 Runtime constant pool은 JVM이 알아서 이용한다.

public class Car {

	// 자동차에 대한 상태와 행위 묘사
	// 상태(값): 자동차소유주, 배기량, 현재속도 => 변수로 상태의 요소들을 표현 =>이 변수가 field, 아래는 필드선언
	static int cc;
	double currentSpeed;
	Car car1 = new Car();
	
	//생성자(constructor)
	Car(){

	}
	
	// 메소드
	void go(int a) {
		int kk = 100;
	}
	
	void go(double a) {
		int kk = 100;
	}
	
	void go() {
		int kk = 100;
	}
	
	void stop() {
		//정지하는 코드
	}
	
	 public static void main(String[] args) {
		int a = 100; // a는 지역변수
		Car car = new Car();
		//car: 지역변수
		//car: reference 변수
		//reference 변수를 이용하기 위해서 "."을 사용
		Car car1 = new Car();
		car.go();
		car.cc = 3000;//인스턴스가 가지고 있는 cc
		car1.cc = 2000;
		Car.cc = 3000; //클래스가 가지고 있는 cc에 3000을 넣는다
	}
	
}


프로그램을 시작하게되면
1. class에 대한 정보가 method area에 들어가야 호출해서 프로그램을 실행할 수 있다.
   Method Area > Car > 필드는3개구나, 메소드의 실행코드 go(), stop(), main()가 이렇게 있구나
2.1 엔트리 포인트를 호출한다, (메인 메소드 호출)-> 프로그램 시작 -> stack의 아래부터 공간 main()을 위한 공간이 생긴다. (Stack>main>지역변수 담긴다(a=100))
2.2 car라는 레퍼런스 변수가 생김 (Car car): Stack 에 car을 가리키는 변수가 생긴다. 
3. Heap에 car가 가리키는 인스턴스 공간 생성(new Car()): 각 필드별 공간 (owner, cc, currentSpeed)과 메소드 공간도 생겨난다. 즉, 필드에 대한 공간은 heap에 생기고 heap에 go()가 생김(method가 생기는것, 근데 코드에 대한 정보는 method area에 있다) Heap에 들어가는 정보는 go()라는 메소드 있으니, Method Area에 접근해서 그 코드 통해서 실행하렴.
4. 마지막줄(car.go();): car라는 레퍼런스 변수로 힙에서 go()를 찾아간다. method area에서 go()의 코드를 참조해서 실행한다. 그럼 go()라는 메소드를 위한 공간이 stack에 생긴다. stack의 속상상 main() 공간 위에 생긴다.
   그리고 go()가 지역변수를 호출해서 stack>go()에 kk=100이 저장됨
5. go()가 끝나면 stack에 있는 go()공간이 사라진다.
6. main()이 끝나면 stack에 있는 main()공간 사라진다.
7. heap에 필드 공간, 메소드 공간이 있긴 하는데 스택에 있는 인스턴트를 가리키는 메소드가 사라지고 나면 어차피 이 필드들도 사용 불가능하다. 그러면 JVM의 garbage collector가 알아서 지워버림
8. 프로그램이 종료되면 method area에 있는 내용도 다 사라진다.

class member vs. instance member

member = field + method
class member: 인스턴스가 없이 클래스 이름을 이용해서 사용할 수 있는 필드와 메소드 (method area안에)
instance member: 인스턴스가 있어야지 사용할 수 있는 필드와 메소드 (heap안에)

필드를 사용하기 위해서는 인스턴스를 만들어야한다. 실제로 필드의 메모리 공간이 만들어지려면 인스턴스가 힙에 있어야한다. 위에 퍼블릭 클래스에서 int cc;라는 필드를 만들었을때 실제로 메모리 공간이 생기진 않는다. 이후에 이런 공간이 생길거라고 말해주는 것 뿐이다. 

 

하지만 인스턴스를 만들지 않고 사용할 수 있는 필드와 메소드들이 있긴 있음 = class memebr
이런 클래스 멤버는 static으로 지정되어 있는 것이다. 

public class Car {

	// 자동차에 대한 상태와 행위 묘사
	// 상태(값): 자동차소유주, 배기량, 현재속도 => 변수로 상태의 요소들을 표현 =>이 변수가 field, 아래는 필드선언
	String owner;
    	static int cc;
	double currentSpeed;
	Car car1 = new Car();
	
	//생성자(constructor) 
	Car(){
		
	}

	// 메소드(method)
	void go(int a) {
		int kk = 100;
	}
	
	void go(double a) {
		int kk = 100;
	}
	
	void go() {
		int kk = 100;
	}
	
	void stop() {
		//정지하는 코드
	}
	
	 public static void main(String[] args) {
		int a = 100; // a는 지역변수
		Car car = new Car();
		//car: 지역변수
		//car: reference 변수
		//reference 변수를 이용하기 위해서 "."을 사용
		Car car1 = new Car();
		car.go();
		car.cc = 3000;//인스턴스가 가지고 있는 cc
		car1.cc = 2000;
		Car.cc = 3000; //클래스가 가지고 있는 cc에 3000을 넣는다
	}
	
}

 

owner는 힙에 만들어진다. cc는 method area에 올라간다. method area에 실제 공간이 생긴다.

1. method area에 car라는 클래스 정보가 들어간다.

  •    cc는 static 이므로 메모리 공간이 할당이 됨
  •    currentSpeed라는 필드가 있다. (얘는 메모리 공간이 할당이 안됨)
  •    Car class의 car1이라는 필드가 있는데 나중에 객체가 만들어진다!
  •    go(), stop(), main()의 코드가 저장된다. 
  •    생성자 Car() {}도 들어감

 

2. 프로그램 엔트리포인트 main을 호출함.

  • stack에 main()을 위한 공간이 생긴다.
  • main()에 a의 공간이 생기고 100이 들어간다.
  • car라는 변수가 생기고, new를 통해 heap에 instance의 공간이 생긴다.
  • instance에 cc(필드)에 대한 공간이 만들어지긴 한다. 근데 이 공간은 ma에 있는 cc공간과 같다 (서로 연결)
  • instance에 currentSpeed에 대한 공간도 생긴다.
  • car.go()는 ma에 go()코드를 참고함, 그리고 스택에 공간이 생김

 

3. Car car1 = new Car();

stack main()에 car1이라는 변수가 생김, 그리고 car instance와 같은 모양의 car1 instance가 생김.

메소드 앞에도 static을 붙여서 클래스 이름으로 호출할 수 있다. (cc처럼) 인스턴스 없이 쓸 수 있는 메소드이다.
(그럴땐 Car.stop()을 인스턴스 없이 사용할 수 있고, 당연히 인스턴스 만들기 전에도 사용 가능하다)

Method Overloading

  • 메소드 이름이 같은 걸 여러 개 만들 수 있다. 이는 만약 메소드의 signature 가 다를 경우 가능하다.
  • 생성자도 overloading 가능하다.
  •   ex) Car(){] 와 Car(int k){} 의 공존
  • 대신 기본 생성자 말고 다른 생성자가 있으면 기본 생성자가 자동 삽입되지 않음
  • 메소드 오버로딩의 사용례: 전진을 하긴 하는데, 인자에 따라서 좀 다르게 하고 싶을때, 계속 새로운 메소드 이름으로 생성하는것보다 같은 이름으로 인자만 다르게 해서 처리하고 싶을때 사용하면 좋음

Package & Import

패키지란?

클래스를 논리적인 단위로 묶는 개념이다.

  • 자바에서 나오는 모든 class는 무조건 특정 package에 포함이 된다.
  • 만약에 package를 명시하지 않으면 default package로 포함된다. (default package는 실제로 사용하지 않는다)
  • 물리적으로 볼 때는 폴더 구조로 표현된다. 
  • package는 중첩 구조를 허용한다 -> 폴더를 중첩해서 표현 가능 (폴더 안에 폴더)
  • 제일 상단에 package를 넣어서 패키지 표현

용도:

1. 다른 사람의 이름이 같은 클래스를 구분하기 위해서
2. 유지 보수를 위해 클래스를 묶어서 관리하기 위해서



다른 패키지에서 Car car = new Car();만 써서 인스턴스 만들라하면 안된다. 다른 패키지라 JVM이 못찾는다 
=> 패키지명. 을 앞에 붙여야함

인스턴스를 만들 때 패키지명을 같이 넣어줘야함
보통 패키지명은 url을 기반이라서 너무 길기 때문에 > import를 사용한다.