복습

변수
1. 지역변수
2. 멤버변수
3. 정적 멤버변수 (= 정적필드, 나중에 공부)

객체모델링
속성 -> 필드
동작 -> 메소드

- 클래스(설계도) -> 객체
- 대부분의 클래스는 객체 생성시 new연산자 사용

필드
- 메소드 바깥쪽에 정의되는 변수
- 힙메모리에 저장되고 자동초기화된다.
- 할당시점 : new연산자로 객체 생성시 힙메모리상에 할당

생성자
- 클래스명과 동일, 앞에는 접근제어자만옴, 필드값을 초기화 시키는 역할

메소드
- 객체의 동적인 것 표현

기본자료형인 필드
- 객체생성시 힙메모리할당되며
- 자동으로 초기화
정수형 : 0
실수형 : 0.0
논리형 : false

참조형인 필드
- null , 참조하는 주소가 없다.

생성자 호출
- 생성자 매개변수에 맞는값 넣어서 생성

생성자 오버로딩
- 한개 클래스 안에 동일한 이름으로 만든 여러 생성자

this
this. : 필드 생성자 메서드 안에서 멤버변수와 매개변수 이름이 같을때사용
this() : 같은 클래스내의 생성자 호출하라는 의미

과제풀이(Lotto.java) 설명
https://laker99.tistory.com/17

- 새로 발생된 난수값과 이전의 난수값들을 비교하기 위해 중첩 for문 사용
- i-- 한 뒤 괜히 더 돌아가는걸 막기위해 break 해주는게 좋다 
- 하나 중복을 발견하면 다음꺼부터는 중복일리가 없다, 이전에 이미 다 처리되었기 때문에
- 오름차순 적용

1. num[0] = 5, num[1] = 5 일때, 안의 for문이 돌아가면서  num[0] 과 num[1]을 비교해서 같으므로 i--시킴
2. 그럼 i=0이 되고 break 되어 나옴 이해 바깥 for문에 의해 ++ 되며 i=1 이 됨
3. 다시 num[1]값을 랜덤으로 받는것

오름차순하기
- 정렬알고리즘 통해서 (버블정렬 = 자신의 옆자리에 있는 것과 비교)
- Arrays 클래스의 sort()함수이용해서 num 배열이름 넘겨주면 오름차순 정렬해줌(java.util.Arrays)

필드 = 멤버변수
- 메소드 바깥쪽에 정의됨
- 기본자료형은 초기화가 됨

파일 생성
- 메인메소드를 가진 클래스만 public class가 될 수 있다!
+ 생성자의 접근제어자 주로 public 이다.

클래스 실행하기
1. 클래스 안에 메인메소드 넣기(독립적실행가능)
2. 메인 메소드가 있는 클래스에서 실행시켜주기

 

필드로 직접 접근하기 예제

class Korean{
	//필드
	String nation = "대한민국";
	String name;
	String ssn; //전화번호
	
	public Korean(String name, String ssn) {
		this.name = name;
		this.ssn = ssn;
	}
	
	
}

public class KoreanEx {

	public static void main(String[] args) {

		Korean k1 = new Korean("박자바","011225-1234567");
		System.out.println("k1.name : " + k1.name);
		System.out.println("k1.ssn : " + k1.ssn);
		
		Korean k2 = new Korean("김자바","930525-0654321");
		System.out.println("k2.name : " + k2.name);
		System.out.println("k2.ssn : " + k2.ssn);
	}

}

- k1객체 만든 후 k1. 통해서 필드로 접근
- k2객체 만든 후 k2. 통해서 필드로 접근
- 필드 name, ssn을 private으로 바꾸게 되면 KoreanEx클래스에서  k1.name k2.ssn 해서 접근 불가(출력 불가)
다른 클래스라서, 다이렉트 접근을 막는다

 

필드값
- nation은 "대한민국"으로 초기화
- name과 ssn은 객체를 생성할때 생성자를 통해 전달된 값으로 각각 초기화됨

할당 시점
- new연산자로 힙메모리에 새로운 공간 생성할때 힙메모리상에 새로운 공간 할당받음(참조형은 다 마찬가지)
- 자료형이 String이라서(필드값) null로 자동초기화되지만 여기선 객체생성시 생성자호출시 받는 값으로 초기화 (name,ssn)
- 주소를가진 레퍼런스 변수 : k1, k2
- 필드들 nation, name, ssn 의 접근제어자가 default이므로 같은 패키지 내는 모두 접근 가능. 그래서 다른 클래스에서 k1.ssn 가능

 

그림


자바의 접근 제어자 정리

접근제어자   자신의클래스   같은패키지                하위클래스       다른패키지

private                    O                    X                                X                    X
생략(default)          O                    O                                X                    X
protected                O                   O                                O                    X
public                      O                   O                                O                   O

+ 같은 클래스 내 : 접근 제어자 의미 없다. 뭐든 접근 된다.
- private : 오직 같은 클래스에서만 됨 , 다른 클래스에서 접근하는걸 허용하지 않음, 가장 좁은 접근허용
- public : 가장 넓은 접근 허용함, 다른 패키지(폴더) 안의 클래스까지 접근가능
- default : 중간정도 접근 범위, 같은 패키지(폴더) 내에선 다 가능
- protected : 상속관련, 상속 배우고 난후 공부

접근제어자 범위 비교
가장넓음 public > default > protected > private 가장좁음

생성자 오버로딩
- 생성자 여러개 생성
- 구분되는 점이 있어야함

생성자 오버로딩 구분
1. 매개변수 자료형
2. 매개변수 개수
3. 매개변수 순서

메소드
- 언어에 따라 함수라고도 한다
- 쓰는 이유 : 객체의 동작 + 여러개 코드를 모아두고 한번 메소드가 정의되면 호출을 통해 재사용하기 위해서

메소드 만드는법
ex) public static void main(){}
1. 접근제어자 
2. static (특별한 경우에만 쓴다,공유 원할때)
3. 자료형 / void
4. 메소드이름 + ()

+ 자바에는 정적 클래스는 없다. 
+ 정적 메소드는 흔하지 않다.

 

접근제어자 예제

 

package p2022_06_29;

class Calculator {
	// 메소드
	void powerOn() {
		System.out.println("전원을 켭니다.");
		return;
	}

	int plus(int x, int y) { // 지역변수 : x, y, result
		int result = x + y;
		return result;
//		System.out.println("test");
	}
//return문 : plus() 메소드를 호출한 곳에 값을 돌려주는 역할
//return문은 메소드 가장 마지막 줄에 사용해야한다.
	double divide(int x, int y) {
		double result = x / (double) y;
		return result;
	}
	
	void powerOff() {
		System.out.println("전원을 끕니다.");
		return;
	}

}

public class CalculatorEx {
//p217 ~ 218
	public static void main(String[] args) {

		Calculator cal = new Calculator();
		cal.powerOn();
		
		int result1 = cal.plus(5, 6);
		
		byte x = 10;
		byte y = 4;
		double result2 = cal.divide(x,y);
		System.out.println("result2 : " + result2);
		
		cal.powerOff();
	}

}

- Calculator 클래스 앞에 private 쓰면 CalculatorEx 클래스에서 객체를 만들 수 없음(클래스 접근 불가)
- Calculator 클래스의 메소드 powerOff 앞에 private쓰면 cal.powerOn() 을 할 수 없음(메소드 접근 불가)

패키지 = 폴더
- 같은 폴더 안 = 같은 패키지 안
- 서로 다른 폴더 안 = 서로 다른 패키지 안 = public만 접근가능


위 예제의 부분1

	int plus(int x, int y) { // 지역변수 : x, y, result
		int result = x + y;
		return result;
		//System.out.println("test"); 오류남
        }

+ return문 : plus() 메소드를 호출한 곳에 값을 돌려주는 역할
+ return문은 메소드 가장 마지막 줄에 사용해야한다.
- 메소드가 실행되는동안 필요한 값들을 매개변수로 전달해줌(매개변수 = 지역변수)
- 메소드 실행되는동안만 스택에 값 존재, return되면 자동으로 지워짐
- 그래서 메모리 관리 크게 신경안써도 된다.

위 예제의 부분2

	cal.powerOn();

- 메인 메소드 안에서 객체 생성하며 생성자 호출후 메소드 호출
- 필드처럼 메소드에 접근할때도 객체.메소드() 로 호출함 (정적메소드가 아닌경우)

위 예제의 부분3

	int result1 = cal.plus(5, 6);


- Call by Value로 값 전달하며 메소드 호출
- plus()는 결과를 리턴자료형 int로 돌려줌 그래서 int result1으로 받아야하는것

위 예제의 부분4 (주의)

	double divide(int x, int y) {
		double result = x / (double) y;
		return result;
	}


- 리턴자료형이 double이므로 double형 값을 돌려준다
- int형인 x와 int형인 y를 산술연산시 int형으로 처리됨
ex) x = 10 , y = 4 이면 다 잘리고 2만 나온다. (손실 발생)
- 손실 발생을 막기 위해서 (double)을 붙여줘서 강제 형변환 -> 2.5
- 그걸 double로 return 시켜줌
- (double) 을 빠뜨리면 자동형변환되어서 2 -> 2.0 이 나옴(손실발생)
- 10/4 는 2.5이므로 살리려면 (double)해서 강제형변환시켜서 값이 double로 처리되도록 해야함.

위 예제의 부분5(CalculatorEx의 main 메소드 내부)

		byte x = 10;
		byte y = 4;
		double result2 = cal.divide(x,y);
		System.out.println("result2 : " + result2);


+ byte는 1바이트 정수형 자료형
- cal.divide에서 매개변수로 byte를 넘김 -> 근데 devide 메소드의 매개변수는 int 형 4바이트 이다. 
- 4바이트짜리 변수에 1바이트 짜리 값을 할당 => 컴파일러가 자동형변환시켜줌. 큰자료형으로 작은값으로 들어가므로
- 자동형변환되어서 위 코드 가능함

+ plus와 divide 메소드의 매개변수 이름들이 같지만 그 메소드 내에서만 사용되는 지역변수이므로 충돌이 발생하지 않음

메소드의 매개변수에 참조형이 오는 예제
- 값이 아닌 주솟값을 전달해야한다.
- sum1은 배열에 전달된 값들의 합을 돌려주는 함수

package p2022_06_29;

//p220 ~ 221
class Computer {
	// 주솟값 전달에 의한 메소드 호출(Call by Reference 방식)

	int sum1(int[] values) {
		int sum = 0;
		for (int i = 0; i < values.length; i++) {
			sum += values[i];
		}
		return sum;
	}

	// vargus : 전달된 값은 배열로 받음
	int sum2(int... values) {
		int sum = 0;
		for (int i = 0; i < values.length; i++) {
			sum += values[i];
		}
		return sum;
	}

}

public class ComputerEx {

	public static void main(String[] args) {

		Computer com = new Computer();
		
		int[] values1 = { 1, 2, 3 };
		int result1 = com.sum1(values1); // sum1() 메소드 호출 , 주솟값을 가진 values1을 넘김
		System.out.println("result1 : " + result1);

		int result2 = com.sum1(new int[] { 1, 2, 3, 4, 5 }); // sum1() 메소드 호출 , 배열을 만들어서 그 주소를 넘김
		System.out.println("result2 : " + result2);

		int result3 = com.sum2(1, 2, 3); // sum2() 메소드 호출 ,
		System.out.println("result3 : " + result3);

		int result4 = com.sum2(1, 2, 3, 4, 5); // sum2() 메소드 호출 ,
		System.out.println("result4 : " + result4);

	}

}

- "같은 int형 배열"의 주소값을 써서 메소드를 호출해야함
- Computer 클래스의 참조형변수인 int[] values는 아직 주솟값이 없는 상태 , new를 써서 int형 배열을 만들어 주솟값을 가진 걸 넘겨줘야함
- 그래서 main쪽에 int형 1차원배열을 만들어줌
- sum1에서 참조형이 매개변수로 왔으므로 같은 int형 배열의 주솟값을 넘겨야함
- new연산자를 아직 안썼으므로 아직 int[] values는 가리키는게 없음 
- 주솟값 전달에 의한 메소드 호출임
+ 값전달보다 주솟값 전달이 더 효율적이고 빠른 방식임

 

vargus (...)
- ...은 vargus 라고 함
- 전달된 값들은 1개일수도 여러개일수도 있지만 전달되는 값들은 모두 배열로 받음
- 매개변수가 있으면 매개변수의 개수대로 메소드 호출시 써줘야하지만 ... 은 int값을 1개 전달하든 여러개 전달하든 모두 배열로 처리됨

 

Call by Reference
- values1 int형 배열 힙메모리상에 4바이트 공간 3개 만들어지고 1,2,3이 들어가있고, 그 걸 values1이 그 스택에서 그 배열의 주소를 가지고 있음

 

	int result1 = com.sum1(values1)

- 에서 주솟값을 담고있는 values1을 전달 = 주소를 전달 = Call by Reference
- 주솟값이 없었던 Computer 클래스의 sum1의 values는 주솟값을 전달받아서 Computer 클래스의 values는 이제 이 {1,2,3} 배열을 가리키게됨
- 합을 구해서 리턴형 int로 result1에 값을 돌려줌

- 매개변수 중에서 참조형이 오는 경우 중 클래스/인터페이스가 가장 많다(배열은 많진 않다)
- API 제공 클래스 + 사용자 정의 클래스 => 이것들도 자료형이다
- 참조형변수는 주솟값을 가진다

 

매개변수에 주소값을 전달하는 법(위 예제 부분)

int[] values1 = { 1, 2, 3 };
int result1 = com.sum1(values1); // sum1() 메소드 호출 , 주솟값을 가진 values1을 넘김
System.out.println("result1 : " + result1);

int result2 = com.sum1(new int[] { 1, 2, 3, 4, 5 }); // sum1() 메소드 호출 , 배열을 만들어서 그 주소를 넘김
System.out.println("result2 : " + result2);

1.이렇게 values1 처럼 만들어진 배열공간의 주소값을 전달하는방법이 있다.
- values1이 가진 주솟값을 전달 


2.(new int[] { 1, 2, 3, 4, 5 } 처럼 오른쪽의 new연산을 써서 새로운 공간을 만들어서 그것의 주솟값을 넘겨줄 수도 있음
- 기억공간이 만들어지고 그거의 주솟값이 sum1 메소드의 매개변수로 넘어감
- 값을 받는 변수가 없기 때문에 이건 재사용이 안된다. 이후 가비지 콜렉터가 이 힙메모리상 배열을 지워버린다.
- 더이상 이 힙메모리에 접근할수없을때 해제된다.
- 할당시점은 new를 썼을때 할당된다

 

그림

 

+ 배열 생성

int[] score = {80,90,100} // new안쓰지만 힙메모리에 데이터 개수만큼 공간 만들어짐
int[] score = new int[]{80,90,100}

 

+ 배열등의 참조형을 매개변수로 쓰는이유
- 매개변수가 100개라면?
- 값들은 힙메모리에 저장시켜놓고 주솟값만 매개변수로 전달하는게 훨씬 효율적

 

vargus(위 예제 부분)

	// vargus : 전달된 값은 배열로 받음
	int sum2(int... values) {
		int sum = 0;
		for (int i = 0; i < values.length; i++) {
			sum += values[i];
		}
		return sum;
	}

- 메소드의 매개변수가 2개면 2개 전달 1개면 1개 전달 해야했었다.
- but vargus쓰면 1개 전달하든 2개전달하든 3개전달하든 모두 매개변수로 받을 수 있다
- 전달된 값은 모두 배열로 처리됨
ex) 첫번째 전달된값은 0번방 두번째 전달된 값은 1번방...
- 다만 자료형은 맞춰줘야함 int ... values 면 몇개이든 int형 값을 전달해야함

 

		int result3 = com.sum2(1, 2, 3); // sum2() 메소드 호출 ,
		System.out.println("result3 : " + result3);

- 1,2,3을 sum2로 전달하면 values가 1,2,3 을 배열로 저장함
- 전달된값들은 "같은 int형 배열"로 처리됨
- 자주쓰는 기능은 아님

 

		int result4 = com.sum2(1, 2, 3, 4, 5); // sum2() 메소드 호출 ,
		System.out.println("result4 : " + result4);

- 로 하면 1,2,3,4,5를 넘기고 배열로 받아서 처리해줌

 

메소드안에서 다른 메소드를 호출하기
- 여태껏은 메인메소드안에서만 메소드를 호출했었다
- 이젠 main 메소드가 아닌 일반 메소드안에서 다른 메소드를 호출해보자

 

package p2022_06_29;

// p227
// 클래스 내부에서 메소드 호출 : 메소드 안에서 다른 메소드 호출
class Calculator1 {
	int plus(int x, int y) {
		int result = x + y; //17
		return result;
	}

	double avg(int x, int y) {
		double sum = plus(x, y); // plus() 메소드 호출
		double result = sum / 2;
		return result;
	}

	void execute() {
		double result = avg(7, 10); //avg() 메소드 호출
		println("실행결과 : " + result); //println() 메세지 호출
	}

	void println(String message) {
		System.out.println(message);
		return;
	}
}

public class CalculatorEx1 {

	public static void main(String[] args) {

		Calculator1 mycal = new Calculator1();
		mycal.execute(); // execute() 메소드 호출
//		execute(); //오류발생
	}

}

1. 메인메소드에서 메소드 호출시
- 객체.메소드() 해서 메소드를 호출해야함

ex)

		Calculator1 mycal = new Calculator1();
		mycal.execute(); // execute() 메소드 호출
//		execute(); //오류발생

 

2. 일반메소드에서 메소드 호출시(같은 클래스 내부)
- 객체.메소드() 가 아니라 객체없이 그냥 메소드() 만으로 호출 가능하다!

ex)

		double result = avg(7, 10);

- avg() 메소드 호출 그냥 avg(7,10)만으로 호출했음

 

위 예제 흐름
- JVM이 main메소드 실행 -> mycal.execute() 호출함-> execute()이 실행됨
-> 그 메소드에서 avg메소드를 호출하면서 매개변수를 7, 10 넘겨줌
-> avg 매개변수의 x에 7, y에 10이 들어감, avg에서 다시 plus() 메소드를 7,10을 넘겨주며 호출
-> plus() 메소드에서 합을 구해서 합을 result 해서 plus()를 "호출"한곳에 값을 돌려줌 즉 avg로 돌아감
-> 그걸 avg의 sum이 받아서 %2 한뒤 돌려줌
- (주의) plus()가 돌려줄땐 int형인 17을 돌려줌, 근데 sum을 double로 받았으므로 17.0 해서 /2 해서 8.5가 result가 됨
-> 그 8.5 값을 avg를 호출한 execute()에 돌려줌, 그걸 println()메소드에 결과값을 넘겨서
-> println()이 출력시킴

+ 자바는 객체지향언어라서 호출할 메소드가 뒤에있어도 상관없다
+ execute() 아래 println() 있지만 execute()에서 println() 호출가능
+ 일반 메소드끼리는 메소드 이름만으로 서로를 호출한다

 

메소드 오버로딩(Method Overloading)
- 1개의 클래스 안에 동일한 이름을 가진 메소드를 여러개 정의하는 것.
- 생성자 오버로딩 처럼 메소드도 한개의 클래스 안에 동일한 이름의 클래스 여러개 정의할 수 있다

메소드 오버로딩 구분하는 법
1. 매개변수 자료형
2. 매개변수 개수
3. 매개변수들의 순서

- 한가지를 이상을 만족해서 구분이 되어야만 올바르게 메소드 오버로딩 시킨것임
* 나중에 메소드 오버라이딩과의 차이를 알아야 한다. 완전히 다른 개념
+ 메소드 오버라이딩 : 두 클래스 사이에 상속이 정의되어야만 사용가능

String 클래스 (API 문서)
- 필드 생성자 메소드 순
- 필드 : 메서드 바깥쪽에 정의되는 변수

- 생성자 : 클래스명과 동일, 형식상 괄호가 반드시 있다
- 매개변수가 없는 생성자는 기본생성자
- 나머지는 클래스명과 동일하게 생성자가 만들어지는데 구분이 되도록 정의됨
-> 생성자 오버로딩

- 메소드도 똑같은 이름을 가진 메소드들이 있다
ex) copyValueOf(char[] data) 와 copyValueOf(char[] data, int offset, int count)
- equlas 메소드, format 메소드들은 같은이름인 메소드가 여러개다 -> 메소드 오버로딩

 

메소드 오버로딩

class Calculator2{
	//정사각형의 면적을 구해주는 메소드
	double areaRectangle(double width) {
		return width * width;
	}
	//직사각형의 면적을 구해주는 메소드
	double areaRectangle(double width, double height) {
		return width * height;
	}
}

- 메소드가 같은 이름이다
- 매개변수가 1개인 areaRectangle 과 매개변수가 2개인 areaRectangle
- 매개변수의 개수가 다르므로 올바르게 메소드 오버로딩 되었음
- 매개변수 1개 전달하면 매개변수 1개인 areaRectangle() 이 호출되고 2개 전달하면 매개변수 2개인 areaRectanble()이 호출됨
- 메소드 오버로딩은 아무 언어나 되는게 아니라 객체지향언어만됨(c++,java는 되고 c는 안됨)

 

앞으로 공부할 내용

1. static이 붙은 정적 필드(정적변수)
2. static이 붙은 정적 메소드

변수
지역변수
멤버변수
정적변수
중에서 정적변수를 하는 것이다

3. 상수를 만드는 법 (Constant)
- final을 붙이거나 static final 을 붙인다
- 기존 변수에 final 붙이면 상수가 되는것
- final을 클래스, 필드, 메소드 에 붙일 수 있다-> 어디에 붙이냐에 따라 의미가 달라짐
4.접근제한자와 패키지 의 관계
5. getter와 setter 메소드

 

정적 필드 (정적 변수)

- static 이 붙은 변수 

ex)

static int a; // 그냥 변수앞에 static을 붙이면 정적변수가 됨

- static : 공유를 목적으로 해서 누구나 쉽게 접근하도록 만들때만 static 붙인 정적 필드형태로 만듬
- API 보면 클래스들 정적필드, 메소드들 정적메소드들 엄청 많다


ex) Math 클래스안엔 정적필드랑 정적메소드뿐
- 정적 필드는 클래스명.필드 로 사용
- 누구나 쉽게 생성할수있도록 따로 객체생성없이 클래스명.필드로 사용함

 

ex) 

int n = Integer.parseInt(String s);

- 에서 parseInt는 정적메소드라서 이렇게 클래스명.parseInt()로 사용함
- 세번째 변수인 정적멤버변수(정적 필드)
- 정적 필드 = 정적 멤버변수 = 정적 변수
- 메모리상에 할당되는 시점과 저장되는 영역이 (지역변수,멤버변수, 정적변수) 다 다르다(잠시 후 공부)

 

Math 클래스(정적 필드/메소드 예시)
- 내부에 정적 필드 뿐이다
- 정적필드 정적메소드 뿐
- 정적필드 E , PI 는 Math.E 로 접근가능
- 정적 메소드 , 정적 필드뿐이라 객체 생성할 필요가 없음
- math클래스는 생성자가 아무것도 없다 -> 생성자 자체를 못씀
- random() 메소드의 타입은 static double이다. 즉 정적메소드이고 리턴값이 double
- 정적 메소드 이므로 Math.random()으로 사용할수있다

 

정적변수의 메모리 할당 시점/장소
- 할당 시점 : 정적 멤버변수는 클래스가 메모리에 로딩되면(실행될때) 할당됨 
- 초기화 : 자동으로 설정되고 (정수형 0 실수형 0.0 논리형 false)
- 값 유지 : 프로그램이 종료될때까지 값을 유지한다
- 저장 영역 : 메모리의 static영역 (공유영역)에 자동으로 할당됨
- 저장 영역 : 공유영역 = 메소드영역 = static 영역 <->힙,스택과 다름
- 주의 : 장 오래 메모리에 상주하므로 많이쓰면 메모리가 부족해짐, 특별한경우아니면 만들지 않음

+ 특별한 경우, 반드시 정적멤버변수 만들어야하는 경우
- 싱글톤 : 객체생성을 1번만 하는 것, 이 경우엔 정적필드를 만들어야함

자동초기화
- 정적멤버변수는 자동초기화 된다.
- 배열과 마찬가지로 int는 0 , double 은 0.0, boolean은 false로 초기화 된다.
- 메소드영역에 값을 저장하고 한번 저장된값은 프로그램이 완전히 종료될때까지 값을 유지

정적 멤버변수에 접근하는 방법
- 정적 변수를 가지고 있는 클래스명으로 직접 접근 할 수 있다.

class StaticTest{
satic int a;

public static void main(String[] args) {
	System.out.println(StaticTest.a)
	}
}

- 정적메소드 사용시 클래스명.메소드()

 

정적 필드 / 정적 메소드 정리
- 정적 필드 = static이 붙은 변수
- 정적 메소드 = static이 붙은 메소드
- static이 붙은 필드를 가진 클래스가 로딩이 되면 이 정적필드는 메소드 영역에 저장이되고
자료형에 따라 기본자료형 변수들은 자동초기화됨

 

정적 멤버변수 만드는 법

- static 붙이기
- 예제 : NoneObject.java/UseNoneObject.java / UseNoneObject.java에만 메인메소드 있음

package p2022_06_29;

public class NoneObject {
    static int number = 3; // 정적 필드
    
    public static void printNumber() { // 정적 메소드
        System.out.println("number = " + number);
    }
}

- 메인메소드없으므로 독립적 실행은 안됨,
- 정적필드하나 정적메소드 하나 있는 NoneObject 클래스
- 이 클래스의 필드에 접근하고 메소드를 호출해보자

package p2022_06_29;

public class UseNoneObject {

    public static void main( String[] args ) {
    
//이 방식 잘 안쓴다
    NoneObject no = new NoneObject();
    System.out.println("no.number = " + no.number);
    no.printNumber();
    
//아래방식을 주로 쓴다
    System.out.println("NoneObject.number = " + 
					NoneObject.number);
    NoneObject.printNumber();
    
    }
}
출력
no.number = 3
number = 3
NoneObject.number = 3
number = 3

- NoneObject 클래스는 정적필드와 정적메소드를 가지고 있다
- UseNoneObject 클래스에서 접근할때 객체를 생성한 후 필드와 메소드를 사용할 수도 있지만
- 정적 필드와 정적메소드이므로 이렇게 안쓴다 (가능은 하지만 안쓴다)
- 필드 접근/메소드 호출하는 법 : NoneObject 클래스에서 .을 찍어서 정적필드, 정적메소드 로 접근

 

정적 필드 / 정적 메소드 접근 정리
- 누구나 쓸수있도록 하려고 static 붙인거임-> 객체생성해서 접근하지 않는다
- 결론 : 정적필드 , 정적메소드는 클래스명.필드, 클래스명.메소드() 해서 접근해라

정적 필드의 자동초기화
- 예제 : NoneObject.java 파일

package p2022_06_29;

public class NoneObject {
    static int number = 3; // 정적 필드
    
    public static void printNumber() { // 정적 메소드
        System.out.println("number = " + number);
    }
}

- 에서 static int number 에 3 초기화 안시킨다면?
- 자동으로 0으로 초기화시켜주므로 UseNoneObject 에서 실행해보면 0으로 출력됨

정적 멤버변수의 메모리 할당/해제(위 예제)
- NoneObject클래스가 로딩되자마자 number는 공유영역에 저장되면서 int형이니 0으로 초기화됨
- number의 값은 프로그램 종료시까지 계속 메모리에 상주함
- static 정적 필드 많이쓰면 메모리 부족

객체를 생성해서 정적필드/정적메소드에 접근(위 예제 부분)

//이 방식 잘 안쓴다
    NoneObject no = new NoneObject();
    System.out.println("no.number = " + no.number);
    no.printNumber();

- 가능은 하다
Q. 그럼 이때 new를 쓰면 정적필드는 어디로 저장될까? (질문하기) -> 그래도 메소드 영역

 

메모리 정리
- 힙 메모리에 저장 : JVM 시작할때 생성, 객체와  배열 저장, 가비지 콜랙터가 참조되지 않는 즉, 사용될수 없는 객체 제거
- 메소드영역 메모리 : static이 붙은 필드를 가진 클래스가 로딩이 되면 이 정적필드는 메소드 영역에 저장이됨.

 

static 필드의 의미(그 안의 값)

정적 필드 값의 유지 예시1 : StaticCount.java, Shared.java / 메인메소드는 Shared 클래스에만 있다

package p2022_06_29;

public class StaticCount {
    static int number = 3;
}

- 정적 필드 하나만 있다. 프로그램 종료까지 값을 계속 유지함
- 정적필드는 싱글톤을 만들때만 주로 쓴다. 객체를 1개만 생성해서 공유를 한다는 개념인 싱글톤

package p2022_06_29;

public class Shared {
    public static void main( String[] args ) {
    
        StaticCount sc1 = new StaticCount();
        System.out.println("sc1.number = " + sc1.number); //3
        
        sc1.number++;
        System.out.println("sc1.number = " + sc1.number); //4
        
        StaticCount sc2 = new StaticCount();
        System.out.println("sc2.number = " + sc2.number); //4
        
        sc2.number++;
        System.out.println("sc2.number = " + sc2.number); //5

        StaticCount.number ++;
        System.out.println("StaticCount.number = " + StaticCount.number); //6
    }
}
출력
sc1.number = 3
sc1.number = 4
sc2.number = 4
sc2.number = 5
StaticCount.number = 6

- 에서 StaticCount 클래스로 sc1라는 객체를 만들었음 
- (정적필드, 정적메소드 가진 클래스로 객체 만드는건 자주안하지만 가능하긴 함)
- sc1을 통해서 접근 된다!

 

값의 변화(값이 유지됨)
1. 처음 sc1.number 출력했더니 3 을 출력함 = 초기값이 3임
2. sc1.number++; 해서 sc1통해서 증가시킴 
3. sc1.number 출력시 4를 출력함

- 그 후 같은 StaticCount로 sc2 라는 새로운 객체도 만듬

4. 근데 힙메모리 영역이 아니라 메소드 영역이라는 공유영역이기 떄문에 sc2.number로 sc2에 접근해서 출력해도 number는 3이 아닌 가장 마지막에 저장한 값 4를 출력시킴
5. sc2.number 로 또 접근해서 ++ 증가시킴
6. sc2.number 출력시 5를 출력

- 마지막엔 객체가 아닌 StaticCount.number 로, 즉 클래스 명으로 접근한다 
6. StaticCount.number 를 ++
7. 출력하면 6이 나옴

 

정적 필드 값의 유지 예시2 : StaticTest01.java

package p2022_06_29;

class StaticTest {
	static int a = 10; // 정적 필드 : 메소드영역(공유영역) 에 저장
	int b = 20; // 인스턴스 멤버변수 : heap 메모리에 저장
}

class StaticTest01 {
	public static void main(String[] args) {
		System.out.println("StaticTest.a->" + StaticTest.a);
		StaticTest s1 = new StaticTest();
		StaticTest s2 = new StaticTest();

		System.out.println("s1.a->" + s1.a + "\t  s2.a->" + s2.a);
		System.out.println("s1.b->" + s1.b + "\t  s2.b->" + s2.b);

		s1.a = 100;
		System.out.print("s1.a->" + s1.a);
		System.out.println("\t  s2.a->" + s2.a + "  ");
		System.out.println(StaticTest.a);

		s1.b = 200;
		System.out.print("s1.b->" + s1.b);
		System.out.println("\t  s2.b->" + s2.b);
	}
}

- StaticTest01이 메인메소드가지고 있다
- StaticTest 클래스에는 static 정적 변수 1개, 일반적인 필드 1개 이렇게 있다
- 이런 일반적인 필드 는 instance 변수 또는 instance 필드 라고 부름
- 즉 a는 정적필드 b는 인스턴스필드

정적필드와 인스턴스 필드 비교
- StaicTest.a 는 정적필드기 때문에 클래스명. 으로 접근 가능
- 이때 초기값이 10으로 있기떄문에 10으로 출력됨

- 그 후 StaticTest 클래스로 new해서 객체 2개를 생성함 s1, s2
- new연산자로 할떄마다 힙메모리상에 새로운 공간을 할당받음
- 그래서 인스턴스 멤버변수인 b는 힙 메모리상에 할당받음
- 정적 변수인 a는 그대로 공유 영역에 있음

현재 상태
     a=10     //정적 멤버변수
 (공유영역)

s1             ------->  b=20
s2             ------->   b=20
                               
(Stack영역)                 (Heap영역)    


초기 상태
- b는 s1의 b, s2의 b 각각 있고, 힙메모리 상에 20으로 각각 있다.
- 이 값의 주소를 s1, s2가 스택메모리에서 갖고 있음

- a는 정적멤버변수라서 공유영역(메소드영역) 에 초기값 10을 저장하고 있는 상태
- 그래서 s1.a, s2.a는 10으로 출력됨 s1.b나 s2.b는 20으로 출력됨

변화
- s1.a 에 접근해서 값을 100으로 수정함
- s1.b 에 접근해서 값을 200으로 수정함

    a=100     //정적멤버변수
 (공유영역)

s1             ------->  b=200
s2             ------->   b=20
                               
(Stack영역)                 (Heap영역)   

변화된 상태
-  s1.a 와 s2.a 모두 출력시 100이 나옴
- 또한 클래스명으로 접근한 StaticTest.a  해도 100이 출력됨
- 즉 a는 가장 마지막으로 저장된 값이 공유됨

- s1.b만 200으로 수정됨(공유 안됨)
- s1.b를 출력하면 200, s2.b를 출력하면 20이 나옴

정적필드와 인스턴스 필드의 비교
- 정적 필드들은 마지막에 저장된 값을 계속 공유함
- 인스턴스 필드들은 클래스를 가지고 객체 생성할때마다 힙 공간 할당받으며 각각 초기값을 가지게 됨

정적 필드와 접근제어자 예제 : StaticTest02,03,04

StaticTest02.java
 
package p2022_06_29;

class StaticTest2 {
	private static int a = 10; // 정적 필드
	private int b = 20; // 인스턴스 필드

	public static void setA(int new_a) { // 정적 메소드
		a = new_a;
	}

	public static int getA() { // 정적 메소드
		return a;
	}
}

public class StaticTest02 {
	public static void main(String[] args) {
		//  System.out.println(StaticTest2.a); //a가 private으로 선언되어서 컴파일 에러 발생 
		System.out.println(StaticTest2.getA());

		StaticTest2 s1 = new StaticTest2();
		StaticTest2 s2 = new StaticTest2();

		s1.setA(10000);
		int res1 = s1.getA();
		System.out.println(res1);
		System.out.println(s2.getA());
	}
}
출력
10
10000
10000

- StaticTest2.a 로 접근이 안된다. 
- 이유 : 아무리 정적필드라도 외부클래스의 접근을 허용하지 않는 private 이 a 앞에 붙어서 다른 클래스인 StaticTest02 에서 접근시 에러 생김

 

private static int a = 10;

 

- 모순이 발생한다
- static은 공유를 하겠다는거고 private은 보호를 하는거라서 컴파일상 오류를 발생시키며 접근이 불가능하다.
- 결과적으로는 클래스명으로 접근하는 것이 허용되지 않음

 

private인 static 필드값 가져오는 방법
- getA() 메소드를 이용해서 접근한다
- getA() 메소드는 정적 메소드이고 public 이라 클래스명으로 접근가능하다\
ex)

System.out.println(StaticTest2.getA());

- 가능하다, 10이 출력됨

 

private인 static 필드값 설정하는 방법 (위 예제 부분)

		StaticTest2 s1 = new StaticTest2();
		StaticTest2 s2 = new StaticTest2();

		s1.setA(10000);
		int res1 = s1.getA();
		System.out.println(res1);
		System.out.println(s2.getA());

- StaticTest2로 새로운 객체 2개  s1, s2 생성함
- setA 메소드는 public static 이라 호출 가능하다. 클래스명으로 접근 가능하지만 이렇게 s1.setA(10000)처럼 객체로 접근도 되긴함
- s1.set(10000)으로 a값을 10000으로 셋팅
- s1.getA() 해서 접근도 되고, s2.getA() 해서도 됨 둘다 출력시 10000 됨

정적 필드와 접근제어자 결론
- private static하면 모순이 생겨서 결국은 다른 클래스에서 접근 못하는 필드임
- 그래서 StaticTest2.a가 에러생김(다른 클래스에서 호출하였기 떄문에)
-> private이 붙으면 정적 static 필드라도 다른 클래스에서 접근이 불가능함

정적 필드와 접근제어자 주의
- 정적 메소드 안에는 정적 필드만 사용가능함 (중요)
- 정적 메소드 안에 일반적인 필드 쓰면 오류발생 (저장영역과 기능이 다르기 떄문에)
- 정적메소드와 일반메소드는 기능이 다름

 

정적 필드 / 정적 메소드 주의 예제1 : StaticTest03

package p2022_06_29;

class StaticTest3 {
	private static int a = 10; // 정적 필드
	private int b = 20;

	public static void printA() { // 정적 메서드에서는 this를 사용하지 못함
		System.out.println(a);
		// System.out.println(b); //정적메소드 안에는 일반적인 필드 사용불가
		// System.out.println(this.a); //컴파일 에러 발생

	}

	public void printB() { // this는 인스턴스 메서드에서 여러 객체에 의해서
		System.out.println(b); // 메서드가 호출될 때 이를 구분하기 위해서 사용된다.
	}
}

public class StaticTest03 {
	public static void main(String[] args) {
		StaticTest3.printA();
		StaticTest3 s1 = new StaticTest3();
		StaticTest3 s2 = new StaticTest3();
		s1.printB();
		s2.printB();
	}
}

정적메소드를 쓸 때 주의사항


1. 정적 메소드에서는 this 레퍼런스 변수를 사용할 수 없다.
- this.는 힙메모리의 주소를 참조하는게 this.이고, this.는 개별적인 객체에 대한 주소를 가진 레퍼런스 변수라서 정적메소드 안에선 this. 를 사용할 수 없다


2. 정적 메소드에서는 일반적인 변수(인스턴스 필드)를 사용할 수 없다.
- 정적 메소드에서는 정적멤버변수만 사용가능함
- 일반적인 필드 = 힙메모리 이고,  정적필드 = 메소드 메모리(영역) 이라서 영역이 다르기 때문


3. 정적 메소드는 메소드 오버라이딩되지 않는다.
- static이 붙은 정적메소드는 메소드 오버라이딩이 되지 않는다.

 

+ 메소드 오버라이딩 : 두 클래스 사이 상속관계가 있을때, 부모로부터 상속되는 필드와 메소드 중, 메소드를 상속받을때, 이름과 형식은 똑같이 하면서 내부 내용은 다르게 쓰는 것.

정적 필드 / 정적 메소드 주의 예제2 : StaticTest04

package p2022_06_29;

class StaticTest4 {
	private static int a = 10; // 정적필드
	private int b = 20;

	public static void printA() {
		System.out.println(a);
//    System.out.println(b);   //컴파일 에러 발생 : 정적메소드 안 일반필드
	}

	public void printB() {
		System.out.println(b);
	}
}

public class StaticTest04 {
	public static void main(String[] args) {
		StaticTest4.printA();
		StaticTest4 s1 = new StaticTest4();
		StaticTest4 s2 = new StaticTest4();
		s1.printB();
		s2.printB();
	}
}

- 정적메소드 안에는 정적필드만 사용가능하다
- 일반 메소드 안에서만 일반필드 사용가능
- 정적 메소드 , 정적 필드는 클래스명. 해서 사용함 !    StaticTest4.printA();  
- 하지만 객체를 만들어서 객체.메소드 해서도 메소드 호출가능, 객체.필드 해서 필드 접근하는것도 가능

    StaticTest4 s1 = new StaticTest4();
    StaticTest4 s2 = new StaticTest4();
    s1.printB();
    s2.printB();

 

Math 클래스 (API 문서)

- 모두 정적필드 뿐
- 모두 정적메소드 뿐
- Math 클래스를 가지고 정적 필드와 정적메소드를 사용해보자

Math의 정적필드 2개
- E
- PI

Math의 생성자
- 생성자 자체가 없다
- 생성자는 제공되지 않는데 쓸수없다 Math 클래스로 new해서 객체생성하면 오류발생

Math의 메소드
- 모두 static 붙은 정적 메소드 -> 굳이 객체를 생성할 필요도 없다
- 그냥 Math.E , Math.random() 으로 쓰면됨

Math 클래스의 필드 사용 예제
+ Math라는 이름으로 사용자 지정 클래스 생성할 수 없다. 라이브러리에 이미 쓰고 있는 이름이라서

		System.out.println("E = " + Math.E);
		System.out.println("PI = " + Math.PI);

- Math클래스는 생성자가 제공되지 않기때문에 Math 클래스로 직접 객체를 생성할 수 없다
- 하지만 Math 클래스 = 정적 필드 + 정적 메소드 뿐이라서 객체 없어도 아무 문제 없음

Math 클래스 메소드 사용 예제(다양한 메소드 사용)

 

1. abs() 메소드
- 절대값을 구해서 결과를 돌려줌 
- abs() 메소드 여러개임 (메소드 오버로딩) , int, double, long, float등 타입별로 존재

	System.out.println("abs() = " + Math.abs(-10)); //절대값 , 결과는 10

 

2. ceil() 메소드
- 안에있는 소수점 이하 값을 무조건 올려버림 (올림) , 소수 첫째자리에서 올림함

	System.out.println("ceil() = " + Math.ceil(3.14)); //올림, 출력은 4.0

 

3. round() 메소드
- 반올림을 해주는 메소드
- 소수첫째자리에서 반올림해주고 결과는 long으로 돌려줌 11이 나옴 
- 매개변수 double, 반환은 long

	System.out.println("round() = " + Math.round(10.5)); //반올림, 출력은 11

 

4. floor() 메소드
- 무조건 내림을 해주는 메소드
- 소수점 이하는 다 버림, 매개변수 double, 반환은 double 
- 10.9 -> 10.0

	System.out.println("floor() = " + Math.floor(10.9)); //내림, 출력은 10.0

 

5. max() 메소드
- 최대값을 구해주는 메소드
- 메소드 오버로딩이 되어있다

ex) max(int a, int b) , max(double a, double b) 등
- 2개짜리 매개변수 있는 메소드들만 있다
- 자바에는 2개짜리만 제공함 -> 3개 이상이 필요하면 내가 만들어서 써야함 (파이썬은 제한 없음)
- 10과 20중 큰 값을 return 구문으로 돌려줌

		System.out.println("max() = " + Math.max(10, 20)); // 최대값 , 출력은 20

 

5. min() 메소드
- 최솟값을 구해주는 메소드
- 메소드 오버로딩이 되어있다
- min메소드도 2개짜리 매개변수 있는 메소드들만 있다

		System.out.println("min() = " + Math.min(10, 20)); // 최솟값, 출력 : 10

 

6. pow() 메소드
- 지수를 구할때 사용한다.
ex) 2의 3승 구할때 쓰는 메소드 Math.pow(2,3);
- pow(double a, double b) 이고 리턴은 double 형

		System.out.println("pow() = " + Math.pow(2,3)); // 2의 3승 , 출력은 8.0

 

7. random() 메소드
- 양수값으로 0.0보다 크거나같고 1.0보다 작은 범위의 실수형태의 난수 리턴
- 0.0 <= Math.random() < 1.0 범위의 난수 발생
- double형으로 리턴

		System.out.println("random() = " + Math.random());

 

8. sqrt() 메소드
- 제곱근을 구해주는 메소드
- 루트를 씌운값을 돌려줌
- 리턴은 double
ex) 루트5를 구할때 쓰는 메소드 Math.sqrt(5);

		System.out.println("sqrt() = " + Math.sqrt(5)); //루트5(제곱근5) , 출력은 2.23606...

 

우리가 쓰는 println() 의 구조

System.out.println("");

- System 클래스의 필드를보면 모두 정적필드
- 객체생성안하고 System.out으로 썼었던 이유 : 정적필드 중 out 이 있다
- out이 정적필드이기때문에 System.out을 쓴다

- 이 out이란 필드의 결과를 돌려주는 자료형이 PrintStream 이 리턴형이다 (객체로서 리턴)
- 즉 System.out은 자료형이 PrintStream이라는 자료형
- 이 PrintSteram 클래스를 찾아보면 println / print / printf 메소드가 들어있다(정적 메소드 아님)

+ void println()이 메소드 오버로딩되어있다. ex) void println(int i), void println(char x) 등

우리가 쓰는 Scanner 객체 생성하고 안에 System.in 썼던 이유
- Scanner 클래스를 찾아보면 Scanner(InputStream source)라는 생성자 가 있다.
- Scanner 생성자의 매개변수가 InputStream 타입이라서
- Scanner 객체 생성할때 생성자의 매개변수가 System.in 이었다
- System.in의 리턴형을 보면 InputStream 이다
+ in은 static이 붙은 정적필드라서 System.in 이라고 쓴다.

자료형과 메모리

- 기본자료형 && 지역변수 -> 스택에 저장됨, 자동으로 초기값이 설정되지 않음.
- 기본자료형 && 멤버변수/정적변수 -> 아직 안함
- 참조형 -> 값은 힙메모리에 저장됨
- 기본자료형이라도 참조형이면 자료형에 따라 자동 초기화
- 클래스들도 필드들이 자동 초기화됨

 

new 연산자

- String 클래스를 제외한 클래스, 배열, 인터페이스는 필수적으로 new 연산자 사용함
- 힙에 새로운 공간을 형성하라는 표시

 

참조형

- 클래스, 배열, 인터페이스, 열거타입(잘 쓰지 않음)
- 값이 힙메모리에 저장됨, 그 값이 저장된 영역의 시작주소를 스택메모리에서 가짐
- 힙메모리 : 동적으로 계속 공간을 늘릴 수 있는 특징

 

메모리 영역

- 스택 메모리 영역
- 힙 메모리 영역
- 메소드 메모리 영역

 

참조형

+ 인터페이스(자료구조)
- 대표적인게 List

 

배열 정리

- 동일한 자료형만 저장가능한 정적인 자료구조
- 정적 자료구조 = 크기가 딱 정해져 있음. new int[3] 하면 딱 3개만 생성
- 배열이름.length 속성 : 배열의 크기 = 배열 방의 개수 

 

배열 매개변수 예시1
- 메소드의 매개변수가 기본자료형이 아니라 참조형 중 배열일때

 

public static void main(String[] args) {

		int[] scores; // 여기 int[] scores ; 는 아직 주소를 가지지 않은 상태

		scores = new int[] { 83, 90, 87 };

		// int[] scores = new int[] {83,90,87}

		int sum1 = 0;
		for (int i = 0; i < 3; i++) {
			sum1 += scores[i];
		}
		System.out.println("총합 : " + sum1);

		// add 메소드를 호출해서, 리턴된 총합을 sum2에 저장
		int sum2 = add(new int[] { 83, 90, 87 });
		System.out.println("총합 : " + sum2);

	} // main() end

	// 사용자 정의 메소드 : 합을 구해주는 메소드 : 배열을 매개변수로
	public static int add(int[] scores) {
		int sum = 0;
		for (int i = 0; i < scores.length; i++) {
			sum += scores[i];
		}
		return sum;
	}

- int[] scores 는 주솟값을 가지지 못한 형태다
- 메소드의 매개변수가 참조형 중 배열이다.
- 이땐 배열의 주솟값을 전달해야함
- Call by Reference 방식으로 호출해야한다.
- 이 int 형 배열의 주솟값을 전달하자
- 매개변수자리에 클래스, 배열, 인터페이스 다 올 수 있다.

 

배열 매개변수 주의(위 예제의 부분)

 

	public static int add(int[] scores) {
		int sum = 0;
		for (int i = 0; i < scores.length; i++) {
			sum += scores[i];
		}
		return sum;
	}


	public static void main(String[] args) {

		int[] scores; // 여기 int[] scores ; 는 아직 주소를 가지지 않은 상태
	}

- main의 int[] scores 는 주솟값을 가지지 못한 형태다
- new 연산자를 써야만 새로운 공간을 힙메모리에 할당받는데 아직 안썼으므로
아직 주솟값이 없는 상태
- add함수로 전달하는 건 주솟값을 전달해야함 = Call by Reference

 

	public static void main(String[] args) {
		int sum2 = add(new int[] { 83, 90, 87 });
	}

- 이 경우엔 리턴받는게 없으니 이 공간은 재사용을 못한다
- 이렇게 해서 new를 써서 add 메소드로 주솟값을 전달함
- 힙 메모리 상에 있는 "같은 자료형 "(여기선 int형) 배열의 주솟값을 전달해야함
- new를 쓸때마다 새 공간이므로 이 sum2가 가리키는 new의 공간이랑 맨 위에 scores 이 가리키는 공간은 다른 주소이다
- 힙메모리상에 불필요하게 공간을 사용하는건 Garbage Collector 프로그램이 주소를 전달한 뒤 자동으로 지워버림 = 재사용 불가

 

+ 값 전달하는거보다 주솟값을 전달하는게 처리가 빠르다
+ C언어에선 이걸 포인터로 전달함

 

참조형인 매개변수 정리
- 주솟값을 할당받기 위해선 반드시 new 연산자가 있어야함
- String s= "자바" 가 가능하므로 String s 가 매개변수로 올때만 예외적으로 바로 check("자바") 로 호출 가능
- 또는 String s = new String("파이썬") 도 가능하므로 check(new String("파이썬") 으로 호출해도 된다.
- 다른 참조형 변수는 99% new를 써야함

메소드 정리
- 메소드 앞에는 return 자료형이 반드시 와야함
- 정적메소드이기 때문에 클래스명.add 또는 같은 클래스 내에선 .add 로 생략하고도 쓸수있다
- 정적메소드 아니면 객체를 생성후 호출해야한다.

배열 초기화 정리
- int뿐아니라 정수형 배열들은 다 0 으로 초기화 됨(char제외)
- 실수는 float 는 0.0f double 은 0.0
- 클래스/인터페이스/배열은 null로 초기화
* null : 주솟값이 없다는 의미


확장 for문 = 향상된 for문
- 순차적인 자료구조인 배열, 리스트같은 곳의 원소를 끄집어낼때 사용함
- 배열에 있는 값을 원소값이 더이상 없을떄까지 하나씩 왼쪽의 변수로 옮김
- 간결하기때문에 자주 씀

 

for( 타입 변수 : 순차적인 자료구조(배열,컬렉션)) {
             실행문 ;
}

* 타입변수 : 전달 받을 값 
* 컬렉션 = 자료구조(여기선 순차적인 자료구조를 의미), 대표적인게 리스트

 

확장 for문 예제

		int[] score = { 95, 71, 84, 93, 87 };


		// 확장 for문
		int sum1 = 0;
		for(int s : score) {
			sum1 += s;
		}

- 값을 받는 변수 s 도 배열의 자료형과 같은 int 형으로 받아야함
- score 배열에 들은 원소(값)들을 왼쪽의 s변수에 하나씩 전달, 이걸 원소값이 없을때까지 반복한다
- 전달된 값을 sum1 변수에 누적 

+ 순차적인 자료구조 :List, Vector
+ stack은 순차적인 자료구조 아님 다른 방식

 

main 메소드의 매개변수

- public static void main(String[] args){}
- JVM에서 여태껏 main 실행할때 아무 값 전달하지 않았음
- 하지만 전달 할 수도 있다.
- 전달시 args[0]에 첫번째 값이, args[1]에 두번째 값이 들어감
- String 자료형이므로 숫자를 적어도 문자로 처리됨

 

main 메소드의 매개변수 활용

package p2022_06_27;

public class ArrayEx07 {

	// 절대값을 구해주는 메소드
	static int abs(int data) {
		if (data < 0)
			data = -data;
		return data;
	}

	public static void main(String[] args) {

	// args[0] = "-10", args[1] = "-20"
		System.out.println("args[0] : " + args[0]);
		System.out.println("args[1] : " + args[1]);
	// args[0] = "-10" ---> -10 : 형변환(int로)
		int num = Integer.parseInt(args[0]);
		System.out.println("절대값 : " + abs(num));
	}

}

- 이 코드를 그냥 실행시 오류
- main 메소드 통해서 값을 전달할땐 그냥 실행시 오류가 생김
- 실행시키는 방법이 다름 ! (자주 쓰는건 아니지만 알아두기)

 

이클립스로 실행법
1. RUN 초록 화살표 버튼 마우스 대고 있으면  Run Configuration  메뉴 잇다
2. 두번째 탭인 arguments 선택
3. 위칸 program arguments 에서 -10 -20 을 입력(뛰어쓰기로 args[0] args[1] 값 구분)

- args[0]에 -10, args[1]에 -20 이 전달됨
- (-10)을 써도 String[] 이 매개변수이므로 문자인 "-10" 인것임
+이클립스가 아닌 콘솔창 자바 가상머신에서 실행시

java ArrayEx07 -10 -20

- 이렇게 실행함


의미 설명

1. java : 자바 가상머신 JVM
2. ArrayEx07 :ArrayEx07.class 란 바이트 코드를 실행함
3. -10 -20 이렇게 구분해서 입력

 

- args[0]에 -10, args[1]에 -20 이 전달됨
- (-10)을 써도 String[] 이 매개변수이므로 문자인 "-10" 인것임

 

자료형 변환

- 형변환된 값을 abs 메소드에 전달해야하는데 abs는 매개변수가 int 형이므로 그래서 문자를 숫자로 일단 변경하고 메소드 호출해야함.
-이걸 절대값 구할때는 args[]에 들은 데이터는 String은 문자열 이므로 int 로 바꿔야함
- "-10"을 숫자 -10 으로 바꿀땐 

int num = Integer.parseInt(args[0]); // 자주씀 외우기

- 자바의 3가지 자료형 변환 중 두번째 자료형 변환 방법임

 

Wrapper 클래스 (자료형 변환 원리)

- 기본자료형마다 Wrapper 클래스가 있다 .
- Integer 는 int 의 wrapper 클래스임
- 그래서 Integer.parseInt("20") 을 사용해서 문자 20을 숫자 20으로 변환
- Wrapper 클래스를 쓰면 기본자료형과 참조형 사이의 자료형 변환이 가능하다 (ex) string <-> int)
- 모두 java.lang 패키지안에 있어서 import 필요없다
-  Wrapper 클래스 쓰면 다른 자료형으로 쉽게 변환 가능

 

Wrapper Class

- boolean 은 Boolean
- byte 는 Byte
- char 은 Character
- int는 Integer

 

Wrapper 클래스를 이용한 변환 방법 2가지
1.

 int num = Integer.parseInt("20")


- pasreInt는 정적메소드라서 따로 객체 생성없이 클래스명. 으로 호출 parse() 안에는 String 자료형
2. 

Integer in01 = new Integer("20");
int num01 - int01.intValue();


- 언박싱

wrapper클래스의 주요 2가지 기능
1. String -> int (이게 거의 대부분임)
2. int -> String ex) String s - String.valueOf(20);

Integer 클래스 구조 (api 문서)
java.lang.Object
java.lang.Number
java.lang.Integer
- 최상위 클래스 = 슈퍼클래스는 Object
- 부모 클래스는 Number
- 상속 관계가 이미 다 형성되어있다.


1. Integer 의 필드(변수, 상수 의 개념)
- MAX_VALUE 쓰면 int형 변수가 가질 수 있는 최대값을 구해줌(정적필드) 약 +21억
- MIN_VALUE 스면 int형 변수가 가질 수 있는 최솟값을 구해줌


2. Integer 의 생성자
- 2개뿐


3. Integer의 메소드
- 메소드 중 pasreInt 는 2개가 있다 = 메소드 오버로딩
* 메소드 오버로딩 에서 이름은 같아도 매개변수등 구분이 되어야 잘 사용한것
- parseInt (String s) : 우리가 쓴 메소드 . 타입은 static int다 정적메소드이므로 Integer.parseInt로 사용하고, int 형 변수에 결과를 저장해서 돌려줌 매개변수 안엔 String 형만 들어가야함
- parseInt (String s, int radix) 도 있다.

+ 오라클등의 DB 연동할때 java.lang.Class 클래스 사용


배열을 복사하기
- 여러 방법 있다
1. for문
2. System.arrayCopy() 메소드
3. Arrays 클래스 이용

 

for문으로 배열 복사하기

public class ArrayEx08 {

	public static void main(String[] args) {

	//p167~p168
	//배열 복사 : for문으로 배열 복사
		
		int[] oldArray = {10,20,30}; //원본 배열
		int[] newArray = new int[5]; //새로운 배열
		
		for (int i = 0; i < oldArray.length; i++) {
			newArray[i] = oldArray[i]; //배열 복사
		}
		
		//복사된 배열 출력
		for(int i : newArray) {
			System.out.print(i + "\t");
		}
	}

}

- newArray는 배열이므로 0으로 다 초기화 된 상태
- oldArray -> newArray 로 복사할때 for문돌아가면서 10이 newArray[0] 으로 20이 newArra[1]으로 30이 newArray[2]로 복사됨
- 한줄 엔터키를 안쓰고 그냥 띄우기나 \t를 쓸때는 println이 아니라 print인점 주의

 

위 예제 그림

2차원 배열 정의방법 2가지

1.

int[][] score = new int[5][3];

- 메모리상에 값 저장위한 기억공간만 생성하고 그 값이 아직 뭔지 모를때 사용
- 2차원배열은 [][]처럼 2개임, [][]가 score 뒤에 가도 됨
- new란 연산자를 쓰는 형식
- 왼쪽, 오른쪽 자료형 같은걸로 맞추기
- 첫번째 괄호에 들어가는건 행의 수 (가로방향)
- 두번째 괄호에 들어가는건 열의 수 (세로방향)
- 4바이트짜리 기억공간을 행 5, 열 3으로 15개 생성하라는 뜻. 5행 3열짜리 기억공간 생성 

 

그림

2.

int[][] score = {{0,0,0},{0,0,0},{0,0,0}};

- 값이 고정되어있을때 쓰는 방식

 

예시

 

int [][] score = { { 85,  60,  70},      //0 행
	            { 90,  95,  80},       //1 행
	            { 75,  80, 100},       //2 행
                    { 80,  70,  95},       //3 행
	            {100,  65,  80} };     //4 행

- 0행 0열에 85, 4행 2열에 80이 들어감

 

2차원 배열 인덱스
- 행 = row = 가로번호
- 열 = colume = 세로번호
- 행 번호는 가로번호 의미
- 배열에 인덱스는 0번부터니까

배열 인덱스 예시

score[0][0] = 85; //0행0열에 85점을 할당하라
score[4][2] = 80; //4행2열에 80점을 할당하라

 

2차원 배열 입력/출력

 

public class Arr04 {

  public static void main(String[] args) {
   
    int [][]score = { { 85,  60,  70},   //0 행 = 1번학생
			{ 90,  95,  80},   //1 행 = 2번학생
			{ 75,  80, 100},   //2 행 = 3번학생  
                        { 80,  70,  95},   //3 행 = 4번학생
			{100,  65,  80}    //4 행 = 5번학생
					};
    int [] subject = new int[3]; //과목총점 저장할 1차원 배열
    int [] student = new int[5]; //학생의 총점 저장
        //    subject[0]=0, student[0]=0;
    int  r, c;  
	    
    System.out.println("각 과목별 총점구하기 "); //열방향으로 다 합쳐야
    for(c = 0; c < 3 ; c++){ // 과목         
      for(r = 0; r < 5 ; r++){ //학생      
        subject[c] += score[r][c];   
      }//subject[c]=subject[c]+score[r][c];
      System.out.println(subject[c]);  
    }

    System.out.println("학생별 총점구하기");
    for(r = 0; r < 5 ; r++){    //학생      
      for(c = 0; c < 3 ; c++){  //과목    
        student[r] += score[r][c];  
      }//student[r]=student[r]+score[r][c];
      System.out.println(student[r]);
    }

  }//main() end
}// class end

- 행 열을 따로 처리해야하므로 중첩 for문을 쓴다
- 행번호는 0~4이기 때문에 for문으로 0부터 시작해서 <5까지 즉 4까지 함, == 학생수는 5명
- 그 학생 당 과목 성적을 위해서 안쪽 for문으로 0부터 2까지 3번 돌림 == 과목수 3개(국영수)
- 행과 열이 만나는 곳의 점수를 출력하면 score[row][col]
- 더 빨리 바뀌는 부분이 for문의 안쪽에 와야함 나중에 움직이는 부분이 바깥쪽에
- 과목 총점 구하기는 [0][0] [1][0] [2][0] ... 을 더해야하고 ->과목은 열이기 때문에 for문 안쪽에 r 가 와야함
- 학생별 총점 구하기는 [0][0] [0][1] [0][2] ... 를 더해야함 -> 학생은 행이기 때문에 for문 안쪽에 c가 와야함
- int [] subject = new int [3] 이나 int [] student = new int[5]; 는 자동초기화 0 이므로 sum = 0 같은
번거로운일 할 필요 X

 


객체지향언어

 

클래스
- 클래스도 자료형이다
- 배열과 메모리상 처리는 거의 비슷함

String 클래스
- 클래스 중에서 쉽게 이해할 수 있는 String 클래스로 예시들어서 설명
- 클래스 중 사용빈도 가장 높음

String 클래스와 메모리
- String 클래스로 String 객체를 만든다
- 객체를 만들면 배열과 마찬가지로 문자열 " " 들은 모두 힙메모리상에 저장됨(참조형이 가지는 공통적인 특징)
- 그 메모리의 시작주소값을 변수가 스택에서 가지고 있다

 

String name;
name = "신용권"

- 그냥 이름을 저장하는것같아 보이지만 "신용권"은 힙의 공간에 저장, 그 주소를 가진 name은 스택에서 주소를 가지고 있다.

 

String 클래스와 메모리2
- String 클래스의 경우에는 문자를 바로 할당해도 되고 new 연산자를 사용해도 된다
- 이 두가지 되는건 String 밖에 없다
- 보통의 클래스는 new 연산자를 써서만 객체 만들어야함
- 하지만 new 연산 썼을때와 쓰지 않았을때 메모리에 차이가 있다.

String name1 = "신용권";
String name2 = "신용권";

- new 연산자를 쓰지 않고 만들면 처음 한번은 "신용권"을 저장한 기억공간을 힙메모리에 만듬
- 두번째의 경우에는 새로운 공간 만들지 않고 이미 "신용권"이 저장된 공간의 주솟값을 리턴받음
- name1 == name2 주솟값이 같다

 

String name1 = new String("신용권");
String name2 = new String("신용권");

- new 연산자를 쓰면 매번 새로운 공간을 힙메모리에 생성하라는 명시적인 표시
- new 연산자를 2번 썼기 때문에 새로운 공간이 2번 만들어짐
- 그림을 보면 힙 메모리상에 공간이 따로 따로 만들어짐
- name1 != name2 주소가 다르다

 

참조형의 비교

- 참조형들은 비교대상이 2개다
- name1 == name2 처럼 비교연산자로 주솟값을 비교
- equals() 란 메소드로 값들끼리 비교

 

주솟값 비교 예시

		String str1 = "자바";
		String str2 = "자바";

		if (str1 == str2) { //비교연산자(==)로 참조하는 주소를 비교
			System.out.println("같은 주소"); //같은 주소
		} else {
			System.out.println("다른 주소");
		}



		String str3 = new String("자바");
		String str4 = new String("자바");
		
		if (str3 == str4) { //비교연산자(==)로 참조하는 주소를 비교
			System.out.println("같은 주소"); //같은 주소
		} else {
			System.out.println("다른 주소");
		}

- 비교연산자(==)로 참조하는 주소를 비교

 

그림

값 비교 예시

		if(str1.equals(str2)){ // 참조하는 값(데이터)을 비교
			System.out.println("같은 값"); //같은 값
		}else {
			System.out.println("다른 값");
		}

- 값비교 equals() 메소드를 사용
- 같으면 true를 반환

 

참조형의 비교 정리

- 비교연산자(==) : 참조하는 주소를 비교
- equals() : 참조하는 값(데이터)을 비교

 

+ 메소드를 찾는 법
ex) equals() 메소드를 어디서 찾아야할까
1. 1차적으로 api에서 equals() 메소드가 어디 붙어있는지 보자 -> String
2. String클래스 찾아야
3. String클래스 안에 없으면 그거 조상들 클래스를 찾아야
- String의 경우엔 부모가 java.lang.Object가 최상위 클래스 , 자기 부모 클래스 임. 
- String 안에 없더라도 조상이 그 메소드를 가지고 있으면 상속 받아 string 객체에서도사용할 수 있다.
- 만약 String클래스도 String의 부모클래스에도 equals()없다면 그건 없는 것임.

+ 클래스 구조
- 필드 1개 있고 생성자있다
- 생성자 : 객체를 생성할때 자동으로 호출되는 메서드, 클래스와 같은 이름이다.

 

String 클래스 구조 생성자
- 우리는 매개변수가 String으로 된 생성자를 호출해왔었음 String(String original) 을 써왔던것

 

String str3 = new String("자바")

- 에서 오른쪽은 String은 생성자를 호출하는 것임
- 생성자는 없으면 못씀 제공되는것만 쓸 수 있다

 

String 클래스 구조 메소드
- String 클래스 안 메소드 많다(기능 많다 )
- equals() 메소드의 리턴타입은 boolean, 값이 같으면 true, 다르면 false를 리턴해줌
- 그래서 이 메소드 자체를 if문 안에 넣었던 것

 

Object 클래스와 equals()

- equals() 메소드의 매개변수는 Object
- 자바의 가장 최상위 클래스가 Object임 = 슈퍼클래스= 최상위 부모 클래스
- 패키지가 엄청 많지만 그게 뭐든지 가장 위는 Object 
- 즉, Object 는 모든 클래스의 최상위 부모, 조상
- equals() 메소드 매개변수가 equals(Object anObject) 
- 값을 비교할때 Object의 자식들은 다 equals 안에 들어갈 수 있다. 모든 클래스 다 들어갈 수 있다.
- 즉, equals() 괄호 안에 int, boolean, String등 다 들어갈 수 있다
- String뿐만 아니라 Object의 자식들은 모두 비교 equals로 비교가능, 즉 모든 자료형 다 비교 가능

 

예시1

		boolean b = "자바".equals("파이썬");
		if(b) {
			System.out.println("같은 값");
		}else {
			System.out.println("다른 값");
		}

- 가능함
- 3번째 자료형형변환 방법, 레퍼런스 관련이 있다

 

예시2

		if(new Integer(30).equals(30)){
			System.out.println("같은 값");
		}else {
			System.out.println("다른 값");			
		}

- int형끼리 비교도 가능하다.
- int, double, boolean 등 모든 걸 equals 로 비교 가능
- wrapper 클래스 , 오토박싱,오토언박싱 등의 개념 앞으로 공부하는것과 연관

 

객체배열
- 객체의 주소를 참조하는(저장하는) 배열
- C++은 많이 쓰지만 String은 많이 쓰진 않음 객체배열보다 성능 좋은 list등이 있기 때문에

 

ex) String객체를 3개 저장하기 위한 배열 = 객체배열

		String[] strArray = new String[3]; // 객체배열
		strArray[0] = "Java";
		strArray[1] = "Java";
		strArray[2] = new String("Java");

- 이렇게 객체 생성시시에 2가지 방법 써서 가능
- 0번방, 1번방 가리키는 "Java"는 같은 곳임
- 0번방, 2번방 가리키는 "Java"는 서로 다른 곳음

		System.out.println(strArray[0] == strArray[1]); //주소값을 비교, true
		System.out.println(strArray[0] == strArray[2]); //주소값을 비교, false
		System.out.println(strArray[0].equals(strArray[2])); //값을 비교, true

 

사용자 정의 클래스
- String 클래스와 비슷한 방식으로 메모리상 처리가 됨

객체 지향 프로그래밍(OOP)
- 부품 객체를 먼저 만들고 이것들을 하나씩 조립해 완성된 프로그램을 만드는 기법

객체
- 물리적으로 존재하는 모든게 객체가 될 수 있다 ex) 자동차, 사람, 책
- 추상적인 것도 객체가 될 수 있다 ex) 회사, 날짜
- 현실세계에선 사람이란 객체가 있을때 사람에 대한 속성이 있다 ex)나이, 이름 => 속성
- 사람이란 객체가 있을때 있는 동작 ex) 달린다, 걷는다 => 메소드

객체 모델링
- 자바같은 객체지향언어에선 객체 모델링이란 작업을 수행한다
- 사람이란 객체의 속성을 표현할때는 '필드'라는걸가지고 속성을 나타남
- 메소드 바깥쪽에 쓰는 변수 = 멤버변수 = 필드 변수 = 객체의 속성 나타냄
- 메소드를 가지고 객체의 동작을 표현함

현실세계의 자동차 객체
- 필드를 가지고 객체의 속성에 대한 것들을 표현
- 속성 : 색상, 속도 -> '필드' 로 표현함, 필드는 쉽게 말하면 멤버변수임
- 필드는 메소드 바깥쪽에 정의되는 변수로서 멤버변수라고 불린다. 자바에선 필드라고 불림
- 동작 : 메소드를 가지고 표현. 달린다 멈춘다 등의 동작을 메소드로 표현

객체 지향 프로그래밍이 가지는 특징
1. 캡슐화
- 한개의 클래스가 만들어져 있을때 외부클래스에서 접근하지 못하도록 캡슐로 보호를 한다.
- 캡슐화위해선 접근제어자로 접근을 허용을 하기도하고 허용을 하지않기도 한다.
ex) private 써서 외부로부터 접근 막음 = 캡슐화로 안전하게 안의 정보를 보호함

2. 상속
- api에서 제공되는 클래스는 이미 상속관계 정의 다 된 상태임.
- 상속을 함으로서 중복적인 코드를 많이 줄일 수 있다
- 또 유지보수를 편리하게 해주는 기능을 제공하기때문에 상속을 많이 사용함.

ex) 부모 클래스가 있고 자식 클래스가 있을떄
- 클래스 = 필드, 메소드, 생성자 로 구성
- 상속이 되는건 2가지 뿐! 필드와 메소드만 상속이 되고! 생성자는 상속되지 않음!

3. 다형성(Polymorphism)
- 부모로부터 상속받은 것들을 다양한 형태로 바꿔서 쓴다는 것

객체와 클래스
- 설계도 역할을 하는게 클래스다
- 현실세계 : 설계도 -> 객체  를 만들어냄 (ex)설계도로 자동차를만들어냄)
- 자바 : 클래스 -> 객체. 설계도역할하는게 클래스, 클래스 가지고 객체를 무한히 많이 만들어 낼수 있다.

클래스 이름
- 하나이상의 문자로 이루어져야
- 변수명과 마찬가지로 첫번째 글자는 숫자올수없다 ex) Car 3Car (x)
- $나 _ 외의 특수문자 사용불가
- 자바 키워드는 사용할 수 없다
- 변수명,함수명,클래스명등은 한글명으로 클래스 명 쓰는건 바람직하지 않다. 웹으로 가면 여러 문제 발생!

클래스와 소스파일
- 이클립스에서 클래스를 만들면 소스파일이 생성됨 클래스이름.java 가 생성됨
- 이걸 javac.exe가 컴파일 해줘서 클래스이름.class 생성됨
- 앞으로는 한개의 .java 파일에 클래스가 여러개가 들어가는 소스파일 .java 을 만들것
- 소스 파일 당 public class 는 1개만 사용가능함! 이 public 을 가진 클래스와 파일명을 일치시켜야함
- 클래스명과 파일명이 일치되어야하는데 단, 이때 메인메소드를 가진 클래스명과 파일명을 일치 시켜야함
- 컴파일이 되면 파일 안의 여러개 클래스가 각각 따로 따로 .class 파일들로 만들어짐(클래스 수만큼)

객체 생성

new 클래스();

- 클래스와 동일한 이름의 생성자를 호출하라는 코드
- 생성된 객체는 힙메모리상에 객체가 생성됨
- new 연산자는 객체를 생성후 객체 생성 주솟값을 리턴하므로, 왼쪽의 변수가 그 주솟값을 갖고있게됨

 

객체 생성 방법 2가지

1.

클래스 변수;
변수 = new 클래스();

2.

클래스 변수 = new 클래스();

- 한줄

 

클래스 구성 멤버와 역할
- 필드 : 변수기때문에 메모리상의 값을 저장하는 역할
- 생성자 : 객체가 생성시 호출되며 필드값을 초기화하는 역할
- 메소드 : 객체의 동작적인 걸 표현하는 역할

사용자 정의 클래스
- api 에 있는 클래스를 모방하여 생성
- 메소드 바깥쪽에 사용되는 변수 = 필드 = 멤버변수, 변수기때문에 값을 저장함, 속성을 표현
- 생성자는 클래스명과 동일한 이름으로 만들어야함. 객체가 생성될때 생성자가 호출되며
필드값을 초기화시키는게 생성자의 역할
- 메소드는 객체에 대한 동작을 나타냄, ex) public void static main

 

정리
메인 메소드 안의 변수 = 지역변수 = 스택메모리 = 메소드종료시 삭제
메소드 밖의 변수 = 멤버변수 = 필드 = 전역변수 = 힙 메모리 = 초기화

 

사용자정의 클래스 만들기 예시

 

public class Animal {
//Animal 은 사용자 정의 클래스(자료형)

	
	int age; //자바에선 멤버변수, 필드(field) 라고 한다. C에선 전역변수라고 부른다.
		// : 메소드 바깥쪽에 정의되는 변수
	
	public static void main(String[] args) {

	}

}

- age는 메소드 바깥에 있고, 이 클래스 전역에 사용 가능
- 멤버변수= 필드 = 전역변수 는 메모리 중 힙메모리 상에 저장됨!
- 클래스도 참조형이기 때문에 int age; 는 힙메모리상의 공간을 할당받고 초기화 0 으로 자동초기화됨

 

* JAVA구조 : 클래스 내에 메소드가 있다

 

생성자
- 멤버 함수 중 하나
- 반드시 클래스명과 동일한 이름으로 생성해야함.
- () 괄호가 반드시 있어야한다.
- 생성자명앞에는 접근제어자만 올 수 있다.

기본생성자(default constructor)
- 생성자 중 매개변수가 없는 생성자

 

	int age; 
	public Animal() {
		System.out.println("생성자 호출 성공");
	}

 

사용자 정의 클래스와 클래스의 구조 3가지

 

public class Animal {
//Animal 은 사용자 정의 클래스(자료형)

	
	int age; //필드
	public Animal() { //생성자
		System.out.println("생성자 호출 성공");
	} 
	
	public static void main(String[] args) {  //메소드
		
		int a = 10;

	}

}

- 필드, 생성자, 메소드가 다 있는형태
- 생성자는 주로 객체생성과 동시에 필드값의 초기화를 설정하기 위한 용도로 객체가 생성될때 호출되면서 실행
+ a는 지역변수, stack 메모리 영역에 저장, 이 메소드 안에서만 사용가능
+ 지역변수와 멤버변수는 스택과 힙 이라는 다른 공간에 저장되는것 뿐만 아니라 메모리상에 저장되는 영역과 할당되는 시점이 다름

 

	public static void main(String[] args) {

		int a = 10; //지역변수
		String str = new String("자바");
		Animal a1 = new Animal();
	}

+ 이 main메소드는 Animal 클래스 내부임. Animal 클래스 내부에 Animal 클래스로 객체 만들어도 된다.

 

그림

필드 접근

    Animal     a1         =   new       Animal();
// 클래스 레퍼런스변수 연산자 생성자호출

- 이렇게 객체를 생성시 4바이트짜리 Animal 클래스의 '필드'를 저장하기 위한 기억공간을 힙에 생성함
- 그 필드는 age (=0 , 자동초기화) 이다. 그 주솟값을 a1이 가지고 있는 상태
- a1이 age가 저장된 힙메모리상의 시작주솟값을 가지고 있다.
- 이 a1으로 접근해야지만 이 age에 접근가능하다!

 

System.out.println(age); // 불가능
System.out.println(a1.age); // 로 해야함

- 반드시 a1이 가진 주소 이용해서 a1.age로 접근해야함!
- 객체 생성될때마다 새로운 age만들어지므로 어느 영역에 있는 age인지 알 수 없기 떄문이다

- age의 값을 수정하고 싶을때도  a1.age로 접근해서 수정해야한다

		a1.age = 5;
		System.out.println(a1.age); //5가 출력됨

 

생성자 호출

- 오른쪽의 Animal() 은 생성자를 호출하라는 코드임

	public Animal() {
		System.out.println("생성자 호출 성공");
	}

- 출력이 됨

 

생성자를 안쓴다면?
- 기본으로 알아서 생성해줌 

 

객체 생성2

ex) 이번에는 Animal 클래스로 다시 new 연산자로 다시 객체 생성해보자

		Animal a2 = new Animal();
		System.out.println(a2.age);

- 이러면 힙메모리상에 새로운 공간이 또 생성됨!

- 그림 참고

 

그림

- a1이 가진 주소와 a2가 가진 주소를 비교해보자

		if (a1 == a2) {
			System.out.println("같은 주소");
		} else {
			System.out.println("다른 주소");
		}
출력 : 다른 주소

- new로 힙메모리에 새로운 공간을 만들었기 때문이다

자바의 보조 제어문 break

1. switch-case문 빠져나가기 
2. 반복문 빠져나갈때 (while, for, do~while문)

- 주로 무한 루프를 빠져나올 때 break문을 이용함
- 어떤 무한루프에서 조건식을 쓰고 그 조건을 만족하면 빠져나오는게 일반적

 

for 무한루프 돌리는 방법 2가지

1. 초기, 증감, 조건 식 안적기

		for(;;)
		{
			System.out.println("무한출력");
		}

2. 조건 식 안적기

		for (int i = 1;; i++) {
			System.out.println(i + "무한출력");
			if (i == 100)
				break;
		}

break문 주의1

- break 뒤에 다른 내용 있으면 안된다.

while(true)
{
	break;
	System.out.println("출력"); // 오류생김
}

 

break문 주의2

- break문 만나는 순간 그 밑은 아예 안보고 바로 빠져나옴
- break문의 위치를 잘 설정해야함

- 비교해보기(아래 예제2개)

		while(true) {
			
			System.out.println(i+ "무한루프");
			if(i==100) break;
			i++;
			
		}

- 이러면 100번 출력

		while(true) {
			
			System.out.println(i+ "무한루프");
			i++;
			if(i==100) break;
			
		}

- 이러면 99번 출력됨 
* "if"나 "메소드"를 빠져나올땐 break가 아닌 return문을 써야함!!

 

break문 예시

- 1부터 45사이의 난수를 발생 시킬때, 6이 나올때까지 몇번 루프가 돌아가는지 구해보자

package p2022_06_24;

public class Break03 {

	public static void main(String[] args) {

		
		int i = 1;
		while (true) {

			i++;
			int num = (int) (Math.random() * 45) + 1; // 난수발생 : 1~45

			if (num == 6)
				break; // 무한루프를 빠져나옴
		}
		System.out.println("루프횟수 : " + (i - 1)); 
		System.out.println("프로그램 종료");

	}

}

- 루프횟수에서 초기값이 0이 아니라 1이니까 -1 해줌.(한번 루프 돌아도 i값이 2가 되기때문)

 

continue

- 반복문 안"에서만" 사용가능!! (while, do~while, for)
- 다시 반복문으로 돌아가라는 의미
- break문처럼 반복문 가장 위에있으면 오류가 생김
- break문처럼 if문과 함께 쓰임.

		for (int i = 1; i <= 10; i++) {

			if (i == 5)
				continue;
			System.out.println("출력 : " + i);

		}

- i==5일때 출력5는 실행되지 않음
- i==5일때 아래를 실행안하고 i++쪽으로 돌아감, 6이되고 다시 조건식 참이니 출력 : 6이 출력됨

 

메소드 호출

- 여태껏 main 메소드 안에 모든 내용을 다 집어넣었다 이젠 사용자 정의 메소드 만들고 호출해볼것
- 나중에 클래스로 객체 쓸때도 메소드는 계속 쓰므로 중요함.

 

메소드

- 여러가지 코드를 묶어둔 집합체
- 한번 정의된 메소드를 호출 통해서 재사용하기 위해 사용
- 어떤 언어에선 함수 라고 부른다.
- 각 언어마다 메소드 만드는 방법이 꽤 다르다.

 

메소드 호출 방법

- Call by Value
- Call by Reference

 

메소드 의미

접근제어자     공유      자료형     메소드명(매개변수)
public           static         void         check(){

 return   값;
}

 

접근 제어자 종류

-  public
- 생략(default접근제어자)
- private
- protected

 

접근 제어자

- 접근 허용할지 막을지 설정
- 클래스 앞에 도 붙일수 있고, 클래스를 구성하는 3가지 필드(변수), 생성자, 메소드 앞에도 붙일 수 있다
- default : 아무 표시 안하면 default 접근제어자
- public : 모든 접근을 허용한다는 의미로 사용됨, 가장 많이 사용됨

 

static 자리

- 공유를 할경우, 누구나 쉽게 접근할 수 있도록 공유원할때 붙임
- static이 붙은 메소드를 정적메소드라고 불린다.
- 어제 배운 Math 클래스는 정적메소드 밖에 없었다.
+ 아직 클래스-객체 개념 안배웠기떄문에 모두 정적메소드로 해서 공부/실습할것

 

void 자리 = 리턴자료형 자리

- void 대신 기본자료형도 들어갈 수 있고, 참조형인 클래스, 배열, 인터페이스도 여기에 올 수 있다
- void는 값을 돌려주지 않아도 된다는 의미이므로 void 가 왔을땐 마지막의 return이란 구문을 생략 할 수있다
- 자료형이 오면  return 자료형 ; 해서 자료형에 맞는값을 반드시 돌려줘야함
ex) void대신 int란 자료형이 왔을땐 int형 값을 return으로 돌려줘야함.

 

메소드 명 

ex) check()
- 예약어로 설정된 Class If Switch 같은건 메소드 명으로 쓰면안됨
- 메소드 쓸땐 괄호를 반드시 가져야함 . 괄호가 없는 메소드는 거의 없다.
- 괄호만 써도 되고, 메소드가 실행되는 동안 필요한 값이 전달되어야할 땐 변수를 쓴다. 기본자료형, 참조형 다 올 수 있다.

 

메소드 호출/반환

- 기본자료형의 경우 값을 전달한다.
ex) int형이 매개변수로 있다면 int형 값을 전달해서 호출을 해야함
- 클래스가 오면 객체를 전달해야하고, 배열이 오면 배열주소값을 전달해야한다
- void 자리에 클래스, 인터페이스, 배열등의 참조형이 올땐 주소값을 리턴해줘야 한다.

 

main 메소드

-main 메소드는 이름 바꾸지 못함
- public static void check(){}
- 개발자가 호출 할 수 없다 JVM이 해줌

 

사용자 정의 메소드 작성

- 자바는 메소드 안 메소드가 들어가는 중첩메소드 허용안함
- 즉 메인 메소드 안에 메소드가 들어갈 수 없다. (파이썬은 중첩함수 허용)
- 그러므로 메인 메소드 바깥 (위,아래) 에 메소드 작성하기

 

Main 메소드 호출 vs 사용자 정의 메소드 호출

- Main 메소드는 MethodEx01.class란 바이트 코드에서 JVM이 호출해줌. 
- 사용자 정의 메소드는 프로그래머가 직접 호출해줘야함

 

static이 붙은 정적메소드 호출 vs static이 없는 메소드 호출

- static이 붙은 메소드는 그 클래스 . 해서 바로 호출 ex) Math.random()
- static이 없는 메소드는 그 클래스로부터 객체를 생성해서 . 을 해서 메소드를 호출

 

접근 제어자

- 같은 클래스 내에선 접근 제어자가 아무 의미 없다
- protected이든 private이든 public이든 default든 같은 클래스 내에선 다 접근 가능
- 이 클래스,메소드,변수,생성자에 접근을 허용할건지 말건지를 정해둔 것임.
- 아무것도 없어도 default 접근제어자이다

 

return 자료형 적는 자리

- void 가 오든지 자료형이 오든지 둘 중 하난 반드시 와야함
- void면 return구문 생략 가능 또는 return;

 

메소드 호출 방법

- 매개변수가 없는 check() 는 그냥 check(); 라고 호출해주면 됨.

 

메소드 작성 순서
- 자바는 객체지향언어라서 메소드가 적힌 순서가 상관없다
ex) check()가 main() 보다 밑에 있어도 main()에서 check() 호출 가능
- 메소드가 적혀있는 순서가 중요한 언어가 있다.
ex) 파이썬, C

static 메소드 호출
- Math는 정적메소드만 있다. 그래서 Math.random()처럼 사용함
- 원래 static 메소드 호출 시, 클래스명.메소드명() 이 원칙이지만 같은 클래스내에 있는 정적메소드를 호출시엔 클래스명을 생략 가능
ex) MethodEx01.check(); 이지만 같은 클래스 내에선 check(); 만 작성해도 됨.

+ Math메소드의 호출법
- static이 붙은 필드 = 정적 필드 만 있다
- static이 붙은 메소드 = 정적 메소드 만 있다.
- random() 메소드는 static double random() 이다.
- 그러므로 객체 생성하지 않고 Math.random()으로 호출함.

* 클래스 : 필드, 생성자, 메소드가 있다.(api문서)

 

static이 없다면?

MethodEx01 mx = new MethodEx01();
mx.check()

- 이런식으로 객체를 생성하여 호출해야 한다.

 

매개변수가 없을때 vs 매개변수가 없을때 호출

- 매개변수가 없을때 : check(); 으로 호출
- 매개변수가 있을때 : check(ck) ; 로 호출, ck는 int값이어야

	static void check(int a) { //매개변수(parameter) : int a
		System.out.println("전달된 값 : " + a);
	}

- 즉 정수값을 전달해야 함수가 실행될때 매개변수는 스택에 자리가 잡혔다가 메소드 끝나면 지워짐
- check(30); 시 매소드 실행될때 a에게 30을 주게 되고 이 매개변수(파라미터)를 출력
* 매개변수는 지역변수

 

Call by Value

- 이렇게 매개변수가 기본자료형일떈 값을 전달해서 호출하는 것.
- 값 전달에 의한 메소드 호출 방식

Call by Reference
- 매개변수가 참조형 일땐 주소값을 가짐
- 주소값을 전달해서 호출

메소드 "오버로딩"
- 매소드 정의 할때 이름이 똑같음 check(), check(int a)
- 한개 클래스내 동일 이름 클래스 정의할 수 있는 것.
- 하지만 매개변수를 다르게 함으로서 구분이 가능하도록 해야한다. 

지역변수 정리
- 메소드 안에서 사용되는 지역변수 = 매개변수 = 스택에 저장됨 = 메소드 종료시 삭제됨
- 블럭문 안에서 사용되었던 i 같은것도 지역변수

 

메소드 예시

	static void check(int a, double d) {
		double result = a + d;
		System.out.println("전달된 값의 합 : " + result);
	}

- check(10, 10.5); 로 호출 (Call by Value)값을 전달해서 호출함
- 순서에 맞게 자료형에 맞게 전달해야함 int, double 순으로

 

매서드의 매개변수에 참조형이 오는 경우

ex) String 클래스

	static void check(String s) { 

		System.out.println("전달된 값 : " + s);
	}

- main 에서 

check("자바");
check(new String("파이썬"));

- 호출 시 둘 다 잘 출력됨.

- 바로 check("자바") 해서 객체 만들 수도 있고 new 연산자를 써서 String객체를 만들 수도 있다.

 

+ String클래스만 두가지 방법 모두 가능.
1. String s = "자바"
2. String s = new String("파이썬");

static void check(String s) { //String s = "자바"

		System.out.println("전달된 값 : " + s); 
		//String s = new String("파이썬");
}

- 바로 check("자바") 해서 객체 만들 수도 있고 new 연산자를 써서 String객체를 만들 수도 있다.

 

Call by Reference (위 예시 참고)

- Call by Reference = 주솟값 전달에 의한 매서드 호출 방식
- 우리가 볼땐 '자바' '파이썬'을 직접 전달하는거같지만 사실 주솟값을 전달하는것
- 그 데이터가 저장된 영역의 주솟값을 메소드로 전달하는것임
- "자바' "파이썬"데이터는 모두 힙이란 영역에 저장
- 매개변수 s는 스택영역에서 "자바", "파이썬" 의 주솟값을 가지게 됨

 

그림

 

Math 클래스의 리턴자료형

- Math클래스 random() 메소드의 리턴값은 double
- 그 우리는 그것을 int 강제형변환 해서 사용했었다.

 

메소드 예시1

// return문 : 메소드를 호출한곳에 값을 돌려주는 역할을 한다.
static int check01()
{
	System.out.println("출럭");
	return 50; 
	System.out.println("출럭"); //오류발생

}

- 리턴이 void가 아니므로 필수, int형 값만을 돌려줘야한다. 50.5를 리턴할순X

* 리턴구문은 메소드 가장 마지막 줄에 써야한다. 아니면 오류 발생
* 저걸 check()라는 이름을 쓸 수 없다 .  맨 위에서 check()를 썼기때문에 오류 발생
check01로 만들었다.
- Main에서 check01() 로 호출하면 출력은 되지만 리턴으로 돌려받은 값을 받지 않았으므로 그 값을 쓸수 없게됨

 

int result = check01();

- 리턴형이 int이기 떄문에 그 값을 받는 변수도 int여야함

 

값 돌려받는 2가지 방법

1. System.out.println("돌려 받은 값1 : " +  result);
2. System.out.println("돌려 받은 값1 : " +  check01());
- check01()에서 리턴값을 돌려받자마자 바로 출력해도 된다. 변수로 안받아서 출력해도됨

 

메소드 예시2

- 더블형이 리턴일땐

static double check02(int a, double d)
{
	double result = a + d;
	return result;
}

- 이 result도 이 메소드 안의 지역변수다 그래서 이 메소드 말고 다른 메소드에선 사용가능
- main 메소드에서

double result2 = check02(50,3.14);
System.out.println("돌려 받은 값3 : " + result2);
System.out.println("돌려 받은 값4 : " + check02(50,3.14));

 

return

- 메소드를 호출 한 곳으로 값을 돌려줌
- static int check01 에서 int자리에 참조형이 올땐 값이 아니라 주솟값을 돌려줌!

 

메소드 주의

- 클래스 배열 인터페이스도 매개변수 자리, 리턴 자료형자리 들어 갈 수 있다.
- 값을 돌려받을 때는 그 메소드의 리턴 자료형과 일치하는 자료형으로 값을 받아야함.
ex) int i = sc.nextInt();
- public static void main 에서처럼 이 순서 바뀌면 안됨 접근제어자 다음 static 다음 리턴자료형 다음 함수명
- 지역변수는 다른 메서드일땐 이름같아도 충돌 발생하지 않는다

System.out.println(max(n1,n2));
System.out.println(min(n1,n2));

- 가능함
- 원래는 MethodEx03.max(n1,n2)지만 같은 클래스라 생략(max는 static 함수이므로)

 

메모리
- 기본 자료형들은 값을 참조형은 주소를 저장
- 기본 자료형이라 하더라도 항상 스택에만 저장되는게 아님
- 기본 자료형 중 지역변수 만 스택이란 영역에 값이 저장됨
- 멤버,정적 변수는 기본자료형이라도 스택에 저장되지 않음

메모리 예시1
- 참조형 중 클래스 중 String 클래스 예시

String name = "신용권"


- 값인 "신용권"은 힙이란 메모리에 저장되고
- 이 저장된 값의 시작 주소값을 스택 영역에서 가지고 있다


메모리 예시2

String hobby = "독서"


- "독서" 는 힙에 저장 , 그거의 시작 주소값은 참조형 변수가 가지고 있는데 그건 스택에 있다
- (name, 2312415) 이런식으로 (주솟값 : 2312415) 스택에 있는거

 

배열

- 동일한 타입의 데이터를 연속된 공간에 저장하는 정적인 자료구조
- 변수를 확장시킨 개념이 배열 (변수는 1개의 데이터만 저장)
- 변수가 여러개 필요할때 간결하게 쓰기 위해 배열을 쓴다.
- 10개과목 점수 입력받으려면 변수가 10개나 필요함 - > 배열을 쓰면 코드가 늘어나지 않음
- 1가지 자료형 데이터만 저장 가능
- 거의 대분의 언어는 배열을 지원함
- 배열 정의 할때도 반드시 자료형을 적어야함.
- 1차원 배열은 [] 1개 2차원은[][] 2개... 

int[][] score = new int[5][3];


- 배열이름 (변수)쓰고 new를 씀 = 명시적으로 힙메모리상에 새로 공간을 만드는것
- 왼쪽이 int면 오른쪽도 int형으로 해야

 

배열 의미

int score[] = new int[3];

- 힙메모리에 int인 4바이트 연속된 공간을 3개를 생성하란 의미

 

그림

 

배열 기타
+ 우리가 여태껏 봤던 main 메소드의 매개변수는 String 형 1차원 배열
- main(String[] args)
- []는 자료형 뒤에 써도 되고 변수명 뒤에 써도 된다
- String[] args == String ar[] 도 가능하다

new
- 연산자 오퍼레이터
- 힙 메모리상에 배열을 위한 새로운 공간을 만들라는 의미
+ 클래스로 객체 생성할때 쓰는 new도 같은 원리로 힙 메모리 상에 새 공간 만들라는 의미임
- String 클래스만 new를 써도 되고 안써도 되지만 다른 클래스 99%는 new를 꼭 써야만 객체 생성 가능

배열의 초기화
- 배열을 정의 시 힙메모리 상의 연속된 공간은 자동 초기화 된다.
- 자료형에 따라 초기화 되는 값이 다르다
- int 형 배열을 정의하면 힙메모리상의 공간(배열)이 자동으로 0으로 초기화 된다.
- boolean 배열 은 false 로 double 배열 은 0.0 으로 int는 0 으로 초기화 됨
- 또는 원하는 할당값이 있을 때는

score[0] = 80;
score[1] = 90;
score[2] = 100;

 

* 지역변수는 초기화되지 않지만 참조형은 자료형에 따라  초기화 되는 값들이 있다

 

배열을 만드는 2가지 방법
1.

int score[] = new int[3]


2-1.

int[] score = {80,90,100};


2-2. int[] score = new int[]{80,90,100}

int[] score = new int[]{80,90,100}; // 도 가능함

 

 

1. int score[] = new int[3] 방법

- 배열에 어떤 값이 들어가야할지 아직 안정해지거나 모를때
- new가 반드시 들어가야함

2. int[] score = {80,90,100}; 방법
- 값이 정해져있을때 쓰는 방식
- 배열 선언과 동시에 초기화를 할 때 주로 사용

 

int[] s1 = {80,90,100};
int[] s2 = new int[]{80,90,100};
//두가지 형식으로 선언 가능하다

 

- 다른 자료형도 마찬가지

double[] d = {3.14,10.5,42.195}

 

- 같은 자료형만 가능

int[] score = {80,90,100,3.14} // 오류 발생

 

변수->배열->리스트

- 변수를 확장시킨게 배열이고 배열을 확장시킨게 리스트(List)
- 배열은 한가지 자료형만 가능하고 리스트 라는 자료구조를 쓰면 자료형 혼용가능, 동적으로 자료크기 늘릴수도있다

 

char형 배열 / String형 배열

 

char[] c = {'j','a','v','a','안'};
String[] str = {"java", "jsp","oracle"}
String[] str = new String[]{"java", "jsp","oracle"}

- 모두 가능

 

메모리 정리
- 모든 참조형으로 변수 만들땐 거의 다 new를 필수적으로 쓴다 (클래스,배열,인터페이스)
- 힙메모리상에 저장된 값은 초기화 된다!
- 스택 메모리상에 저장된 값은 초기화 되지 않음

 

선언 이후 값 할당

 

score[0] = 80; //0번 방에 80점을 할당
score[1] = 90; //1번 방에 90점을 할당
score[2] = 100; //2번 방에 90점을 할당

 

배열 자동초기화

- int형 배열은 자동초기화 0으로 됨
- double형 배열은 자동 초기화 0.0으로 됨
- char형 배열은 자동으로 초기값 설정이 안됨!
- char 배열은 자동으로 초기화가 되지 않는다.
- boolean 형 배열은 자동초기화 false 로 됨!

 

참조형 배열 예제 : String 배열

- String형 배열은 자동 초기화 null 로 됨 (초기값이 없다는 의미)
* null : 값이 없다 는 의미

배열과 반복문
- 배열을 의미있게 쓰려면 반복문을 써야(ex) 합, 곱 등 구하기

배열의 크기 구하기 : length 속성
- length란 속성 이용해서 배열의 크기 구할 수 있다.
- 메소드가 아니라서 괄호가 없다! 속성이다. 
- 그 배열이름.length 하면 된다

 

배열의 인덱스 주의
+ 배열은 인덱스 번호가 0번 부터 시작함 
- 출력시 for문 쓸때 주로 i=0 해야하는점 주의, 
- <=말고 < 써야하는거도 함께 주의 

 

배열에서의 형변환
- double형 배열 예시

	double[] dd = { 3.14, 10.5, 42.195, 50 }; 

	for (int i = 0; i < dd.length; i++) {
	 	System.out.println(dd[i] + "\t");
	}

- int형 값인 50을 넣으면? 내부적으로  double 로 바뀜(자동형변환)
- 이 반대의 경우는 안됨 double 이 int보다 크므로

- 반대로 int 형 배열에 double 형 자료를 넣어선 안됨

 

크기 구하는 방법 3가지의 비교(중요)

1. 배열크기 구할땐  length 속성
2. 문자열의 길이 구할땐 length() "메소드"
3. list같은 자료구조는 size() "메소드"

 

+ 형변환 항상 주의

double avg = (double)sum / 3; // 또는  sum/3.0
System.out.println("평균 : " + avg);

- sum은 int 형 3도 int형이라 (double)을 안쓰면 소수점 전부 짤려서 나옴.

- 살리려면 (double)을 붙여야함 또는 3.0으로 연산

 

+ 평균을 소수점 2째자리까지 출력하려면

System.out.printf("평균 : %.2f",avg); // 평균 : 86.67

- 실수값일땐 뒤에 f를 써줌, %.2 는 둘째자리까지 출력하란 뜻이고 셋째자리에서 반올림된다.

 

출력형태 정리

 %b : boolean 형식으로 출력 
 %d : 정수 형식으로 출력
 %o : 8진수 정수의 형식으로 출력
 %x / %X :16진수 정수의 형식으로 출력
 %f : 소수점 형식으로 출력
 %c : 문자형식으로 출력 
 %s : 문자열 형식으로 출력
 %n : 줄바꿈 기능
 %e / %E : 지수 표현식의 형식으로 출력

 

복습

char 자료형

- 영문자 1글자는 1바이트
- 한글자 1글자는 2바이트

 

- 하지만 char 안에는 모두 한글자만 가능

char c1 = 'k'
char c2 = '안'

 

참조형

- 기본 자료형과 달리 값 저장 방법이 다르다.

- 값은 힙에 주소는 스택에 저장된다.

 

자바의 구조, api 문서

- jre의 패키지는 비슷한 클래스끼리 묶여져 있다.
- 바이트 코드를 가져와서 import해서 사용하는것이다.
- 바이트 코드 = 기계어
- 그것의 설명서가 api문서

 

필드 : 쉽게 말하면 멤버변수

생성자

- 여기서 제공되는 생성자중 하나를 선택해서 써야함.
- 클래스명과 반드시 동일한 이름으로 되어있고, 메소드라 무조건 괄호가 있는 형태

 

if~else if~else 문

- 가장 먼저 만족한 하나만 실행하고 조건문 나간다.

 

if (score >= 90)
grade = 'A';
else if (score >= 80)
grade = 'B';
else if (score >= 70)
grade = 'C';
else if (score >= 60)
grade = 'D';
else
grade = 'F';

- 가장 먼저 해당하는 것의 문장을 실행하고 if문 전체를 나간다

ex) 90점이면 60점이상이므로 아래 else if 도 만족하지만 첫번째에서 걸리므로 'A'만 출력된다.

 

난수발생 공식

- 난수 = (정수화)(Math.random() * (상한값 - 하한값  + 1)) + 하한값;

 

난수발생 공식 설명

0.0 <= Math.random() < 1.0

- 실수형태의 난수 발생시킴.

* 자세한 설명은 아래에서

 

난수발생 예시

 

// 주사위 번호 뽑기 : 1 ~ 6
		int num = (int) (Math.random() * 6) + 1; // 1~6
		System.out.println("num = " + num);

		if (num == 1) {
			System.out.println("1번");
		} else if (num == 2) {
			System.out.println("2번");
		} else if (num == 3) {
			System.out.println("3번");
		} else if (num == 4) {
			System.out.println("4번");
		} else if (num == 5) {
			System.out.println("5번");
		} else {
			System.out.println("6번");
		}

 

난수 발생 2가지 방법

1. Math 라는 클래스 중 random()이란 '메소드'를 사용. Math.random()
2. Random 이라는 클래스를 import 하고 랜덤 객체를 생성해서 난수 발생

 

// 난수 발생
// 0.0 <= Math.random() < 1.0
//  1         ~            6

 

Math 클래스 (by API 문서)

- java.lang의 클래스이므로 import필요없다.

 

java.lang.Object
java.lang.Math

- Object 클래스가 자기 부모이다(상속관계)

 

1. Math 클래스의 필드 = 멤버변수

* 직접 클래스를 우리가 만들떈 필드를 변수 형태로 만들게 됨.
- E는 자연로그 2.7xx , PI는 파이(원주율) 3.14xx

- static 이 붙은 변수(필드) = 정적 필드
- E는 자료형이 static double
- PI도 자료형이 static double

+ 정적 필드
- 정적 필드 들은 객체를 따로 만들지 않고 클래스명.필드 로 접근해서 바로 해당 필드 값 사용가능
ex) Math.E , Math.PI 하면 값이 나옴

 

		System.out.println("E = " + Math.E); //E값
		System.out.println("PI = " + Math.PI); //PI값
		System.out.println(Math.random()); //난수 발생

 

2. Math 클래스의 생성자

- Math 클래스는 객체를 생성할 필요가 없으므로 (static) 생성자가 없다.

ex) Math m = new Math(); 라는 식으로 사용 불가!
- Math 클래스는 아무 생성자도 제공이 안된다
- 즉, 생성자 자체가 없기때문에 new를 쓰면 오류가 남. 

 

3. Math 클래스의 메소드
- 정적 메소드 = static이 붙은 메소드
- Math는 전부 static이 붙은 정적메소드 뿐이다.
- Math의 메소드도 객체를 생성해서 사용하지 않고 클래스명.메소드 해서 바로 사용함
- Math 메소드 중 random() 메소드가 난수 발생 시켜주는 메소드

 

+ random() 메소드 : 
- Type : static double
- double 형이니 실수값으로 처리됨, 양수로 double 형 값을 리턴한다.
- 0.0 보다 크거나 같고, 1.0 보다 작은 범위의 난수를 리턴 
- double이 return 되므로 정수로 값을 받고 싶으면 (int) 강제 형변환

 

Math.random() 난수 공식의 이해

- 공식 : 난수 = (정수화)(Math.random() * (상한값 - 하한값  + 1)) + 하한값;
ex) int num = (int) (Math.random() * 6) + 1; // 1~6

- 0.0 <= Math.random() < 1.0

 

1. 1.0 미만 이니 1.0 이 포함되지 않는다.
2. Math.random() * 6 을 하면 0.0 <= 난수 < 6 까지 난수발생
- 즉 5.99999..까지 난수가 발생되지 6이 발생될 수 없다.
3. 그래서 +1 을 시키는 것
4. 난수값이 0.0 <= 난수 이므로 0.0 이 나온다면 6을 곱해도 0.0 이다.
- 이걸 int로 형변환하면 0이 된다.
5. 그래서 + 하한값 을 해주는 것

 

예시1
- 1~45사이의 난수 발생

int random;
random = (int) (Math.random() * 45 + 1);
System.out.println("난수 = " + random);


예시2
// 5~70사이의 난수 발생
int r;
r = (int) (Math.random() * 66) + 5;

- 일단 5부터가 아니라 0 부터의 기준으로 생각해야한다
- 그러면 5 ~70까지 몇개의 숫자가 있는지 생각 (70-5+1)
- 그다음 5부터 시작한다 생각해서 5를 더해주면 된다.

 

switch~case문

 

  switch(변수){

	case1: 실행될 문장;
		break;
	case2: 실행될 문장;
		break; 
	default: 위의 case를 만족하지 않을때
	            실행될 문장;
     }

- case를 빠져나가려면 반드시 break;를 써야한다.
- break;를 안쓰면 밑으로 내려간다.
- 아무것도 만족 안하면 아래의 default값을 실행한다.

 

break

- 반복문, 조건문(switch~case 만)에서 빠져나갈 때 break;
- break문은 현재 위치에서 가장 가까운 switch문 또는 반복문을 벗어나는데 사용된다.
- 주로 if문과 함께 사용되어 특정 조건을 만족하면 반복문을 벗어나도록 한다.

 

switch~case문 사용법

- 그냥 case 값: 이라 적고 그걸 만족하면 그 아래있는 case 가 실행됨

		switch (score/10) {
		case 10 : 
		case 9 : 
			grade = 'A';
			break;
		case 8 :
			grade = 'B';
			break;

+ score/10 == 10일때, case 9의 문장 실행됨, 즉 100점일때 break문이 없기때문에 내려감

 

switch~case문 단점

- 100~90 이런 범위값 처리위해서 위의 예제처럼 나누기하는등의 처리가 필요함

 

 

반복문 : 반복적인 걸 할 때 사용

- for , while, do~while

 

for문

for(초기값,조건식,증감식){
	반복 실행할 문장;
}

- 초기값이 있어야함
- 비교연산자로 조건식을 씀
- 증감연산자로 증감식을 씀
- 조건식을 만족하는 경우에만 안의 식들을 수행함
- 만족안하는 경우엔 수행 안함

 

자바의 if 초기값 설정 2가지 방법

1. 선언하면서 초기화
2. 선언은 위에하고 for문 ()안에서 초기화

- 자바는 두가지 방법 다 가능하다
- C등의 언어는 2번 방법만 가능 

if문 작동원리 예시1

for (int i = 1; i <= 10; i++) { 
	System.out.println(i + "사랑해요.");
}


1. i=1로 설정된다.
2. i<=10을 만족한다
3. 1사랑해요 출력
4. i++해서 i==2가 된다
5. i<=10 만족한다
6. 2사랑해요 출력
7. i++해서 i==3이 된다.
8. ...
9. 10이 되면 <=10 만족하기떄문에
10. 10사랑해요 출력하고
11. i++되어 11이 되면
12. <=10만족하지 않기 때문에 
13. 출력안하고 나가게됨!

 

지역변수
- 지역변수는 초기화가 자동이 안됨. ->  초기화는 필수!
- 선언된 {}안에서만 사용가능
- 스택이란 메모리 영역에 공간을 할당받음
- 메소드가 실행될때 할당받고 종료되면 자동으로 지워진다
+ 멤버변수(클래스 변수, 인스턴스 변수)와 배열의 초기화는 자동(기본값으로)


if문 작동원리 예시2

int sum = 0;
for(int i = 1; i<=3; i++)
{
	sum = sum + i;
}

 

변수값 변화

변수     sum  = sum + i
                        0        1
1차           1
                        1       2
2차           3
                        3        3
3차           6
                              4 (조건 불만족) -> 끝. sum은 6이고 i는 4인 상태로 끝

- 지역변수 이므로 int sum = 0 라고 초기화를 꼭해줘야함
- 덧셈일땐 영향이 없는 0으로 초기화
+ int 형 i 도 for 문안의 지역변수 이기 때문에 for문 안에서만 사용 가능하다.
+ for문 밖에서 i를 사용하면 오류가 생김 


지역변수 정의
1. 메소드 안에서 정의되는 변수 (그 안에서만 사용가능 sum은 메인 메소드의 지역변수
2. 매개 변수
3. 블럭문(조건문, 반복문) 안에서 사용되는 변수 i는 for문 안의 지역변수

* 증감식 영역에서 i++, ++i, i=i+1, i+=1 다 가능함
+ \t는 탭키만큼 간격벌림, print("\t") 라고 하면 된다.

 

while문

while(조건문){
	반복 실행할 문장;
}


- 비교연산자로 조건문을 작성하고 조건이 참일때만 반복수행함.
- 초기값이 조건식에 안맞으면 아예 실행 안됨


while문 주의
- for문은 조건식, 증감식, 초기값 자리가 있지만 while은 조건식 외는 내가 설정해야한다
- 일반적으로, 초기값은 while문 밖 위에
- 일반적으로, 증감식은 보통 while문 맨 밑에 
- 증감식 안쓰면 항상 참이라서 무한루프가 돌아감

do~while문

do{
	반복 실행할 문장;
}while(조건식);


- 조건식이 거짓이라도 최소 1번은 실행됨
- 끝에 세미콜론 기억하기!!

do~while문 예시

int i = 1;
do {
	System.out.println(i + "사랑해요");
	i++;
}while(i<=10);


- i 초기값이 11이어도 11사랑해요 가 출력된다.
- i 가 10일때, 10사랑해요를 마지막으로 i는 11이 되어 조건 불만족하여 빠져나가게된다

do~while문 예제

System.out.println("메세지를 입력하세요?");
System.out.println("프로그램을 종료하려면 q를 입력하세요");

Scanner sc = new Scanner(System.in);
String input;

do {
	System.out.println(">");
	input = sc.nextLine();  //문자로 입력을 받는다.
	System.out.println("입력문자 : " + input);
}while(!input.equals("q"));

System.out.println("프로그램 종료");
sc.close();


- String을 입력받기 위해 .nextLine() 메소드로 입력받는다.
- do while은 최소 1번은 실행하므로 실행 하자마자 >가 출력되며 입력할 수 있음
- 그 뒤 q를 입력시 do while을 더이상 못하고 나간다
- scanner 함수를 안전하게 close()로 닫아주는게 좋다.


+ input.equals("q") 메소드
- 값을 비교할때 사용하는 메소드, 값이 일치하면 true인데 앞에 NOT연산자 !를 붙여서 q일땐 false를 만들어서 반복문을 빠져나오게 한다.

+ nextLine() 메소드
- 문자열을 받을때 nextLine() 사용
- 결과는 String 타입 자료형에 저장한다.
- 뛰어쓰기 있어도 된다. 
- 사용자가 입력한 한 줄을 통째로 받음.

지역변수 정리
- 메소드 안에서 사용되는 지역변수 = 매개변수 = 스택에 저장됨 = 메소드 종료시 삭제됨
- 블럭문 안에서 사용되었던 i 같은것도 지역변수

변수 종류
1. 지역변수 (메소드 안에서 정의)
2. 멤버변수
3. 정적변수

메소드 호출
- 괄호, 괄호안의 변수가 기본자료형으로 되었을땐 Call by Value 로
- 클래스, 재열, 인터페이스면 주소를 넘기는 방식으로 호출 Call by Reference로

자료형 변환 3가지 방법
1. 기본 자료형 변환 : 기본자료형 변수들끼리 변환 ex)double <-> int
2. Wrapper 클래스를 이용한 자료형 변환 기본자료형과 참조형사이 변환 ex)int <-> String
3. 두 클래스사이에 상속이 전제되어야가능한 (업캐스팅, 다운캐스팅) 레퍼런스 형변환

자바 패키지
- java.io.* : 입출력관련 클래스를 모아둔 패키지 ex) BufferedReader, FileReader, FileWriter, File 등
- java.net.* : 소켓통신관련 패키지
- java.sql.* : 오라클,mysql등의 데이터베이스와 연동할때

*지금까지 만든 것들은 모두 괄호 안의 지역변수
ex) main 메소드 안에서 선언한 지역변수는 main 안에서만 사용가능

지역변수가 되기 위한 조건 
1. 메소드 안에서 정의되는 변수
- 메소드 안에서만 정의되어 사용되는 변수. 그 안을 벗어나는 순간 메모리에서 지워짐
- 스택이라는 메모리 영역에 저장된다.
2. 매개변수도 지역변수다.
- 메소드 괄호안에서 사용되는 변수
3. 블럭문(조건문 , 반복문)안에서 사용되는 변수도 지역변수다.

지역변수 특징
- 해당 메소드가 호출될때 스택 메모리에 할당되고, 메소드 실행이 종료되면 자동으로 메모리가 해제된다.

기본 자료형 변환 2가지


1. 묵시적 형변환(자동 형변환) :  컴파일러가 컴파일러하면서 자동으로 형변환 시켜준다.
- 작은 자료형 데이터를 큰 자료형 데이터로 형변환할때는 자동으로 변환해준다.
- int -> float 같은 4바이트지만 float형이 더 큰 자료형으로 인식된다. 그러므로 묵시적 형변환(자동) 된다.
- byte < short = char < int < long < float < double
- long 은 8 바이트, float은 4바이트지만 float(실수형) 이 더 큰걸로 취급된다.

2. 명시적 형변환(강제 형변환) : 컴파일러가 자동으로 변환시켜주지 않는다, 우리가 직접 강제로 형변환 시켜야함
ex) int -> char, char c = 97 일때는 오른쪽은 int이므로 자동으로 형변환 안됨 그러므로 char c = (char) 97; 해야함
ex) double -> int, int a = (int) 3.14 (오른쪽은 double 이므로 강제형변환해야)

패키지 추가
- 위에 1라인 좌측의 x를 더블클릭

아스키코드
- 문자는 내부적으로 아스키코드에 따른 숫자로 표현됨(십진수)
ex) 'a'를 int 형 자동 형변환 되면 출력하면 97이 나온다.

아스키코드 값
- 'A' : 65
- 'a' : 97

명시적 형변환(강제 형변환)
- 직접 변환 시키는것, 강제 형변환
- 큰 자료 데이터 -> 작은 자료 데이터 
- 괄호안에 왼쪽과 일치되는 자료형을 써준다.
ex) char c = (char)97; 
ex) int a = (int)3.14;
ex) random 메소드 쓰면 double형 데이터가 나옴 -> int로 강제 형변환

명시적 형변환 주의점
- int -> char 강제형변환하면 아스키코드 맞는 값 나온다.
- '형변환 과정에서 데이터 손실이 일어난다'
- float -> int : 소수점 이하를 '버림' (반올림 X)
- double -> float 강제형변환 : 소수점 길이가 긴상태에서 하면 짤림, 정확성이 보장되지 않는다.

+변수 선언
- int a = 10, b = 3, c; 이런식으로 int 변수 3개 생성 가능

연산자
- 언어 공통적으로 씀
- 변수와 변수사이 관계 연결할때 씀
- 산술연산자
- 비교연산자
- 조건연산자
- 논리연산자
- 대입연산자
- 증감연산자


산술연산자 : 산술적인 연산
+ , - , * , / , % (나머지)

산술연산자 주의1
- System.out.println("a / b = " + (a/b)); // 3(몫), 
- int와 int 연산이라서 같은 int형으로 출력되는거임. 3.333..아니라 3만 나옴.
- 기본자료형끼리만 산술적인연산이 가능
ex) String 클래스 와 기본자료형 끼리 결합시 "파이썬" + 50 하면 "파이썬50" 으로 '연산'이 아닌 '결합'된다

산술연산자 주의2

int n1, n2, n3, n4, n5, total;
double avg;

total = n1 + n2 + n3 + n4 + n5;
avg = total / 5;

 

- int형인 total과 int형인 5끼리 연산했으므로 결과는 int형으로서 뒤의 소숫점이 모두 잘리게 나온다. (정수로)

처리방법
1. avg = total / 5.0
- 5.0은 더블형이므로 소숫점이 짤리지 않는다.
2. avg = (double)total / (double)5;  
- 둘 중 하나만 double넣어도됨
- int와 double을 산술연산하면 double로 처리된다. (더 큰 자료형으로 처리된다.)

산술연산과 자료형
같은 자료형끼리 산술연산 -> 같은 자료형으로 결과가 처리된다
다른 자료형끼리 산술연산 -> 더 큰 자료형으로 결과가 처리된다.

문자열 연결/결합
- + 연산자

비교연산자 (=관계연산자) : 변수의 크기 비교해줌
- 값은 true / false
- if 문 조건식 만들때 많이 사용한다. ex) if(a == b) 나 if(a != b)
- > , >= , < , <= , == , !=
- char 끼리 비교 가능(문자가 아니라 내부 아스키코드 번호로 변환되어 비교)

참조형 변수의 비교
- 기본형 변수는 값을 저장하므로 값을 연산자로 비교 가능
- 참조형 변수들은 값을 저장하지 않기때문에 주의해야함
ex) String은 참조형 변수 중 '클래스' 중 하나

지역변수
- 지역변수는 "스택 영역"에 저장됨.

참조형 변수 (클래스, 배열, 인터페이스)
- String 클래스는 기본 자료형처럼 String s1 = "50" 문자열을 저장하는것처럼 보임
- but 메모리상에서 데이터 저장방식이 다르다.
- 값을 저장하는 영역과 그 영역의 주소값을 저장하는 영역이 따로 분리되어있다.
- 값은 힙에 , 주소값 저장하는 변수는 스택에 저장된다. 배열,인터페이스도 마찬가지이다.

 

참조형 변수의 비교 예시(String)
- 참조형은 값은 모두 힙이란 영역에 저장되고, 스택이란 메모리 영역에서 변수들이 값의 시작 주소값을 가지고 있다.
- s1, s2는 이 "자바"란 값을 가리키고 있다, 즉 주솟값을 가지고 있다.

String s1 = "자바" ; 
String s2 = new String("자바")


- 이 두가지 방식은 메모리상에서 처리되는데 차이가 있다(의미가 다르다)

* String 클래스만 값을 바로 저장해도 되고 new 를 통해서 String객체 생성하는 방식으로 
만들수도 있다.

String str1 = "자바";
String str2 = "자바"; 
String str3 = new String("자바");


1. str1, str2 처럼 기본 변수처럼 선언할땐,
- "자바"가 적힌 곳의 시작 주소값을 갖게 된다.
- str2 에 같은값인 "자바"를 할당하면 str2도 str1이 가리킨 같은 "자바" 를 같이 가리키게 됨. (새로운 공간을 만들지 않음)
- 즉 str1, str2는 같은 주소가 된다.

if(str1 == str2) {
System.out.println("같은 주소");
}else {
System.out.println("다른 주소");
}


출력 : 같은 주소

2. str3처럼 new 써서 객체를 만들어 선언할땐,
- new는 새로운 공간을 힙메모리에 만들어서 자바란 값을 저장하겠다는 의미!
- 그래서 힙메모리상에 "자바"를 새로 또 만들고 주솟값을 str3가 가진 형태로 된다.(그림참고)

if(str1 == str3) {
System.out.println("같은 주소");
}else {
System.out.println("다른 주소");
}


출력 : 다른 주소

 

그림

마우스로 그린거라..



참조형 변수의 비교 (값을 비교)
- 참조형은 주소값을 비교할 때 비교연산자를 써야하는 것이고
- 참조형들은 값을 비교하려면 비교연산자로 비교할 수 없다.
- equals 메소드를 사용해서

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


- 해야 값을 비교할 수 있다.

클래스로 입력받기
- 키보드 입력받기 위한 클래스가 여러개 있다.
- java.io 패키지 안 클래스로 입력받을땐 예외처리 해야한다.
- 여기선 일단 예외처리 필요없는  Scanner 객체 생성해서 입력받자 java.utility

Scanner sc = new Scanner(System.in); //Scanner.class 라는 바이트 코드 안에 있는 클래스/메소드

int n1 = sc.nextInt(); //첫번째 값과 두번째 값 구분은 스페이스바 or 엔터키로 구분함.
int n2 = sc.nextInt();


+ Scanner 쓸때 부분 입력과 동시에 import하는법 Ctrl + Space

클래스 구조 (api 문서)
- 클래스는 생성자, 메소드, 필드 가 있다
- 클래스로 객체를 만들때 생성자를 호출하게된다
- 생성자는 클래스와 동일한 명으로 되어있고 제공되는 것들만 쓸 수 있다. (제공되지 않은 생성자로는 불가능)
- 생성자는 메소드 형태로 되어있기 때문에 괄호가 반드시 있다 


Scanner 클래스 구조
- 라이브러리는 클래스형태로 되어있다 입력을받을때 쓰는 Scanner 클래스
- Scanner 객체 만들어서 사용한다.
- java.lang 패키지 안의 클래스 아니므로 import해야함

Scanner Class는 
java.lang.Object (부모)
     java.util.Scanner 

1. Scanner 생성자
- Scanner 중 매개변수가  InputStream source라고 되어있는거를 선택하여 입력받을 수 있다. 

Scanner(InputStream source)
Constructs a new Scanner that produces values scanned from the specified input stream.
- 우리는 생성자 중 이걸 쓴다.
- (InputStream source) 안에 System.in 이라고 쓴다(입력위해)
+ system 클래스 안에 in은 자료형이 InputStream

2. Scanner는 필드는 없다.

3. Scanner 메소드
nextInt() 메소드 : 키보드로 정수형태의 값 입력 받을때 쓰는 Scanner 안의 메소드
+ nextDouble(), nextInt() 등 자료형에 따라서 있다.
- nextInt() 메소드는 return형이 int형이다. 그래서 왼쪽도 int 변수가 와야함.
- nextDouble()오면 실수형으로 처리됨 (return형이 Double)
- nextLine() 오면 내가 10 와 20 입력해도 숫자가 아니라 문자로 처리됨 (return형이 String)

Scanner sc = new Scanner(System.in); 
//Scanner.class 라는 바이트 코드 안에 있는 클래스/메소드
//표준 입력받을땐 System.in을 생성자로
int n1 = sc.nextInt();
//첫번째로 정수를 받아서 n1에 저장하란 뜻

int n1 = sc.nextInt(); //첫번째 값과 두번째 값 구분은 스페이스바 or 엔터키로 구분함.
int n2 = sc.nextInt();


+ sc.nextInt() '객체'에 메소드! 이걸 int 형 변수에 저장
+ 파일로 부터 입력을 받을때 쓰는 생성자는 Scanner(File source) , Ctrl + Space 하면 볼 수 있다

조건 연산자
변수 = (조건식) ? 값1 : 값2;
- 조건식이 참이면 값1을 변수에 할당
- 조건식이 거짓이면 값2를 변수에 할당

+ 자바는 변수선언을 꼭 위에만 할수있는건 아니다

논리연산자 : ||, &&, ! ( 자바는 기호를 써야함)
- OR연산자 , AND 연산자, NOT 연산자
- 조건식이 2개 이상인 경우에 논리연산자(||, &&) 를 쓴다.
ex) if( a>b || a>c)
ex) if( a>b && a>c)

1. OR 연산자(||)
- 둘중 하나라도 True 가 있으면 True가 됨
- 둘다 False 여야만 False가 됨

2. AND 연산자(&&)
- 둘 다 true 인경우에만 true가 되고 나머지는 false가 됨

3. NOT 연산자(!)
- 기존 논리값을 반대로 바꿔줌
- true앞에 !가 오면 false가 되고 반대도 성립

확장 대입 연산자(= 복합 대입 연산자)
- 간결히 표기할때
- a += b; 는 a+b를 먼저 수행하고 결과를 a로 다시 할당 시켜란 의미

a+=b;	// a = a + b;
a-=b; 	// a = a - b;
a*=b; 	// a = a * b;
a/=b; 	// a = a / b;
a%=b;	// a = a % b;


증감 연산자
- (++) : 1씩 증가   

++a(선행 처리) // a=a+1;
a++(후행 처리) // a=a+1;


- (--) : 1씩 감소

--a(선행 처리)   // a=a-1;
a--(후행 처리)  // a=a-1;



증감 연산자 주의
- 변수명 앞에 오느냐 뒤에오느냐에 따라 다르다.
- ++가 앞에있으면 먼저 처리하고 그 줄을 넘어가라
- ++가 뒤에있으면 그 줄을 넘어가고 연산을 수행하라.

ex)

b= 10;
b1 = b++; // 후행 연산, 이 줄에선 b가 증가하지 않음.


출력 : b = 10, b1 = 11

 

자바의 제어문
1. 조건문(=선택문)
- if문
- switch~case문
2. 반복문
- for문
- while문
- do~while문
3. 보조제어문
- break문
- continue문

1. if문

    if(조건식){
         조건식이 참인경우 실행될 문장;
    }
   if(조건식){
         조건식이 참인경우 실행될 문장;
   }else{
         조건식이 거짓인경우 실행될 문장;
   }
   // 둘 중 하나는 반드시 실행됨

 

   if(조건식1){
          조건식1이 참인경우 실행될 문장;
   }else if(조건식2){
          조건식2가 참인경우 실행될 문장;
   }else{
          위의 조건식을 만족하지 않을때 실행될 문장;
   }
// 가장 먼저 해당하는 것의 문장을 실행하고 if문 전체를 나간다
// 딱 1개만 수행된다. 즉 위에서 조건이 참인걸 만나면 수행후 if를 나감, 밑으로 내려가지 않는다.

JAVA
웹, 앱을 만드는데 사용됨.

1. 객체 지향 언어이다. C++ JAVA C#
<-> 절차 지향 언어 : C언어, 변수와 함수의 위치가 중요함.
+ JAVA 는 C++과 다르게 클래스 다중상속 연산자 오버로딩 등은 지원안함.
2. 플랫폼에 독립적이다.
자바 가상 기계만 있다면 운영체제/하드웨어에 상관없이 자바 프로그램의 실행이 가능
3. 멀티쓰레드를 지원한다.
+ 동시에 여러 작업 수행할 때 ex)게임
4. 자동 메모리 관리 기능
5. 동적인 성능 확장의 제공

JAVA의 종류
- JAVA SE : 우리가 공부할 것, 스탠다드 에디션, PC용 애플리케이션 개발
- JAVA EE : 웹 애플리케이션 개발시 사용되는 자바 ex)JSP, Spring 개발시 사용
- JAVA ME : 휴대폰, PDA 등 모바일 환경에서 사용되는 자바

+ JAVA SE 를 설치시 2개의 프로그램이 설치됨.
1. JDK(자바 개발 키트) : 안에 컴파일러인 javac.exe, 자바가상머신인 java.exe 등이 포함되어 있다.
* 컴파일러 : 소스코드 -> 기계어 변환해줌
2. JRE(자바 런타임 환경) : 자바 실행환경 제공함, 클래스 형태의 라이브러리들을 묶은것이다.

자바 개발을 위한 통합 개발 환경(IDE)
1. 이클립스 (대표적 IDE)
2. IntelliJ IDEA

설치 다운 2가지 방법
1. Oracle 에서 JDK 설치하기 (8까지 무료, 라이센스 O) -주로 8 사용
2. OpenJDK 무료로 쓸수있는 JDK (라이센스 X) - 주로 11 이상 사용

JDK 안 bin 폴더 내부
- javac.exe : 컴파일러 프로그램
- java.exe : 자바 가상머신
*JDK 설치되면 bin안에 컴파일러와 자바 가상머신이 설치됨

+ JRE 안에 lib안의 rt 라는 패키지들이 압축된 파일도 있다.

JAVA를 설치 후 환경설정
bin 디렉토리까지의 PATH를 설정해야지만 위치와 상관없이 이 JDK안의 javac를 사용할 수 있다.
즉, cmd 명령프롬프트 창에서 컴파일을 하기위해서는 환경변수를 설정
1. JAVA_HOME : 환경변수 를 추가
2. 시스템 변수 중 PATH를 편집 %JAVA_HOME%\bin

JAVA가 실행되는 과정
1. 소스파일(.java)를 컴파일러가 기계어로 변환한다.
2. (.class) 바이트코드 파일이 생성된다.
3. 이 바이트코드를 자바 가상머신(JVM)이 실행해준다.

JAVA의 구조
- JAVA에선 class가 가장 큰 틀이고, 가장 먼저 class로 시작해야한다.
- 이 클래스명은 파일명과 반드시 같아야함 (자바만)
ex) Test class의 파일명은 Test.java
- 대소문자를 구분하여 코드를 작성해야함.

+ 메모장에 JAVA를 코딩할때
- ANSI 로 저장해야 한글 안깨진다.
- 메모장을 "Test.java"로 저장하자.

+ 메모장의 코드를 컴파일/실행할때
- javac Test.java // 컴파일, 바이트코드인 Test.class가 만들어짐
- java Test // JVM이 실행


JRE : 라이브러리를 묶어둔 클래스
- 자바에서 필요한 클래스를 import 해서 불러서 쓸때 필요하다.
(클래스 형태의 라이브러리로 제공딤)

JAVA 8 API Documentation : 이 JRE에 대한 설명서
API = 라이브러리 클래스
API 문서 = 라이브러리 클래스 설명서, 알파벳순 정렬
ex) String, System도 라이브러리 클래스임


IDE 프로그램 = 소스작성/컴파일/실행/디버깅 등 통합적으로 개발해주는 환경을 제공함
ex) 이클립스(무료), 인텔리제이(부분무료)

+ 이클립스는 다양한 플러그인을 지원함.
- JSP 가능, Spring,SpringBoot,C,C++ 등 관련 플러그인을 깔면 이런 언어들도 개발 가능하다.

이클립스 설치
1. Eclipse IDE for JAVA developers 버전을 설치시 자바 애플리케이션(내컴에서만 실행됨) 개발 가능
2. for JAVA EE Developers 버전을 설치시 JAVA 웹 애플리케이션 뿐 아니라 JSP. Spring 개발도 가능함
-> 우리는 JAVA EE Developers를 설치

기타
이클립스 2020-06는 자바 8까지 지원함
이클립스 2020-09 부터는 자바 11이상이 설치되어있어야만함
-> 이클립스 2020-06버전 사용할 것

- 워크스페이스 지정하기
- 프로젝트를 만들기 File - New - Java Project
- 인코딩 설정하기 Windows - Preference - encoding - UTF-8 로 통일 (한글 출력과 관련)
- 우측 상단 Perspective 눌러서 JAVA나 JAVA EE등 설정 가능 ex) JAVA EE 선택시 JSP, Spring등을 위한 메뉴로 바뀜

Project = 1개 폴더, 이 안에 클래스(.java)들을 넣는다
* JAVA 8 = 1.8로 나타남.
* (.class) 파일은 Project 폴더 밑 bin 디렉토리 가야 볼 수 있다. 이클립스에서 볼 수 없다.
* 소스파일과 바이트파일을 분리가능

- src폴더에 자바 소스파일(.java)를 넣는다
- Test라는 이름의 클래스 -> Test.java가 만들어짐
- 한개 클래스가 독립적으로 실행되기 위해 main 체크 해준다.

기타
컴파일 실행하는 법
- 상단의 실행버튼 (RUN) 누르면 컴파일 & 실행 해줌

글자크기 폰트 조절하는 법
Preferance - Appearance - Colors and Fonts
단축키 : Ctrl + '+' / '-'

초기 셋팅으로 돌아가기
Windows - Perspective - Reset Perspective

 

언어
- 고급언어 : C, C++, JAVA등
- 저급언어 : 어셈블리어 등

자바 특징
- 소스프로그램을 한번 작성하면 윈도우/리눅스/맥에서 다 실행가능
- 각 운영체제별로 자바 가상머신을 지원하기 때문임.
- 어떤 운영체제에서 개발되었든 운영체제에 맞는 바이트 코드로 실행됨(플랫폼의 독립)

자바언어의 특징
- 객체 지향 언어 : 부품 객체 먼저 만들고 조합
- 함수 스타일 코딩인 람다식도 지원
- 동적로딩,멀티스레드,오픈 라이브러리가 많음

정리
소스 작성 -> javac.exe로 컴파일 -> java.exe (각 운영체제의) 가 실행시켜줌)

주석 2가지
- // : 한줄주석 -> 그 줄 아무곳에서 단축키 Ctrl + /
- /* ~ */ : 블럭주석(다중행주석) -> 블럭 잡은 뒤 단축키 Ctrl + Shift + /

*문장끝은 ; 로 끝내기

클래스 Class
- 접근제어자/접근지정자 : 외부 클래스 접근 허용할지 안할지 public/default(없는상태)/protected/private 으로 지정
- 사용자정의 클래스 : 개발자가 만든 클래스 ex)우리가 만든 Test 클래스
*클래스명 = 파일명 , 대소문자 구분됨

메소드 : 코드의 묶음
- 메소드 코드 재사용 가능
- 메소드는 반드시 괄호를 가지고 있다


main 메소드
- 한개의 클래스 안의 main : 'main 메소드' 라고 부른다 (= 다른 언어의 '함수).
- main() 메소드는 자바가상머신(JVM,java.exe)이 가장 먼저 호출하는 메소드(개발자가 호출하는게 아님)이다.
- 하나만 있어야한다.
- main 메소드는 이름과 형식을 바꿀 수 없다.

* public static void main(String[] args){}
접근제어자/공유(static = 정적메소드) / 돌려줄값 / main메소드

바꿀 수 있는건 2가지
1. String[] args 의 [] 위치 바꿀 수 있다. (String args[]) 가능
2. args 대신 ar 이라고 바꿀 수 있다(String[] ar) 가능 (String ar[]) 가능, 즉 변수명 변경 가능
- main이 있어야만 독립적 실행가능하다
- main이 없으면 컴파일까지만 가능하고 실행은 안된다.

클래스(라이브러리)
- 입출력은 각 언어마다 제공되는 '클래스' 로 한다. scanf, input등
- 자바에선 system 클래스, io패키지, scanner등 (라이브러리로 제공되는 클래스)
- 이 system class는 JRE 안에 들어가있다.
- 이 라이브러리들도 class 형태로 되어있다. rt.jar (자르) 가 JRE안에 있다


패키지(package) : 관련있는 클래스를 묶어 놓은것

jar : 자바에서 사용하는 압축 클래스(여러 클래스를 묶어둔)
* rt.jar안에 몇십개의 패키지, 클래스가 있다.

- java.lnag 패키지 : 자바에서 가장 사용빈도 높은 패키지, 기본 패키지
- java.lang라는 패키지 안에 system 클래스 , String 클래스
ex) java.lang.String, java.lang.System, java.lang.Integer

- 라이브러리 형태로 제공된 패키지임
- 이 라이브러리들을 묶어놓은 것들이 JRE
- 이 클래스를 import해서 불러와서 쓰는것임
- java.lang 외의 모든 패키지는 import해야함. import 생략가능한 기본패키지 = java.lang
- 나머지 패키지는 무조건 import해야함.

정리
가장 간단한 예제 만들더라도 java.lang 패키지 안의 String 클래스 쓰고 있는것임
이 클래스는 기계어라서 이거에 대한 설명서는 아까의 api 문서임
이 클래스가 어떻게 만들어졌는지 api문서 보면 알 수 있다.
이 클래스를 비슷한 기능끼리 묶어둔게 패키지임
java.lang 누르면 그 안의 클래스들 나온다. (가장 사용빈도 높은 클래스 묶은 패키지)

JAVA Api Documentation
클래스의 기본 요소 : 필드, 생성자, 메서드 (어떤 클래스는 뭐 하나 없을 수도 있다)

1. java.lang 패키지명 System 클래스명
Field 란에 있는 out/in/err 는?
- System 클래스는 static이 붙은 정적 클래스/필드이기 때에 생성하지 않고 .으로 불러서 out을 쓴다.
* 정적 필드는 따로 객체를 생성하지 않고 클래스명에 . 뒤에 붙여서 바로 사용
- System 클래스에 생성자는 없고 매서드는 있다.

ex) println은 메서드임 -> () 를 반드시 가지고 있다. println("")
println 대신 print 쓰면 줄을 바꿔주지 않는다.
out 앞 클래스의 PrintStream 클래스를 찾아가면 println 찾을 수 있다.

2. java.lang 패키지명 String 클래스명
- 필드, 생성자(construactor), 메소드 있다.
- 매일 쓰는 클래스임

api 문서 보면 부모 확인 가능.
상속관계까지 이미 다 형성됨, 위에 나온게 자기 부모
ex) java.lang.String

+ java.io.PrintStream 에 print 여러 종류가 있다. (매서드 오버로딩)

이클립스 실행하기 3가지 방법
1.RUN 초록버튼눌러서 실행
2.오른버튼 눌러서 Run As의 Jav Application 눌러서 실행가능
3. 단축키Ctrl+F11

이클립스 단축키
- 실행 : Ctrl + F11
- 한줄 주석(단일항 주석) : Ctrl + /
- 블럭 주석처리(다중행 주석) : Ctrl + Shift + /
- 블럭 주석풀기(다중행 주석) : Ctrl + Shift + \
- 정렬 : Ctrl + Shift + F
- (중요)복사: Ctrl + Alt + 아래 방향키 - 아래방향으로 복사일어남
- 한줄 삭제 : Ctrl + D
- 이동 : Alt + 방향키(위아래) - 그 줄이 위 아래로 이동함. 자리바꿀때 유용
- 자동 import : Ctrl + Shift + O(영문)


자동 import
Date 클래스는 여러 패키지 안에 들어가있기 때문에 패키지 선택해야

실습

Random r = new Random();
System.out.println(r.nextInt(10)); //정수형태. 0부터 9까지의 난수발생 0부터 n-1까지



JAVA 의 변수
- 모든 언어는 변수, 함수(메소드)가 있다.
- 한번 더 사용하기 위해 메모리 상에 저장시켜두는 것.
- 즉, 메모리상 기억공간의 이름

변수의 선언(만들기) 방법
- 자료형 변수명 ; 으로 선언한다

변수명의 규칙
-변수의 첫글자는 문자, $, _ 여야 가능함.
- 숫자,@로 시작할수 없다.
- 변수명은 대소문자를 구분한다
- 영문 소문자로 시작하고 다른 단어 붙을때는 두번째 단어의 첫자를 대문자로 (낙타)
- 문자수 길이 제한없고 예약어는 사용불가

변수 예시

int score;
score = 90;


- 정수형 공간 만든뒤 90 넣어라는 의미

 

변수 특징
- 초기화 동시에할수도 있고 따로 할 수도 있다
- 변수는 값을 계속 바꿀 수 있다. Variable
- 처음할당되는 값은 초기값

자바 자료형
- 기본자료형
- 참조형 (클래스,배열,인터페이스)

자바의 기본 자료형
1. 정수 (byte 1byte, short 2byte, int 4byte, long 8byte)
2. 실수 (float 4byte, double 8byte)
3. 문자 (char 2byte)
4. 논리 (boolean 1byte)

1. 정수형
- 넘치면 오버플로우 적으면(-값크면) 언더플로우 이 범위 확인
- 보통 int 형 쓰지만 넘치는 경우만 long 형을 쓴다.
- int는 약 2의 32승까지 표기

2. 실수형
- float (정확성 떨어짐)
- double (실수는 보통 double 사용함) ex) double d = 3.5;

3. 문자형
- char는 2Byte(java에선)
- char c1 = 'k'
- char c2 = '안' // 반드시 외따옴표에 영문자든 한글이든 딱 한글자만 저장가능함(한글 한 syllable은 2바이트라 가능)
->그래서 잘 쓰지 않음 보통 String 클래스 쓰게 됨 나중엔

4. 논리형
- boolean 은 true false 값 저장 가능 (language마다 좀 다르다)

*기본자료형끼리 형변환 변경할때를 위해 크기를 기억해야
기본 자료형은 값을 저장(int는 정수값을 , double은 실수값을 boolean은 논리값을 저장)

기본자료형 외에 자바에선
참조형 이라는 자료형도 있다(Reference Type)
참조형 크게 3가지 있음
1. 클래스 ex) String s1 = "50";
- 대표적 자료형인 String 은 클래스형태의 자료형이다. String은 쌍따옴표 필수. 한글자뿐 아니라 여러 글자 저장
- char 처럼 일반적인 문자(값)를 저장하는게 아니라 "주소값을 저장한다!!!!"
- 값을 저장하는 곳과 주소값을 저장하는 곳이 분리되어있다.
2. 배열
3. 인터페이스

명명법
- 패키지명은 숫자로 시작 불가능하다.
- 클래스 명 첫글자는 대문자로 작성하는게 좋다.

JAVA는 , 가 아니라 +로 연결해야한다
ex) System.out.println("b1 = " + b1);

 

정리 & 실습

- 변수 : 메모리상에 데이터를 저장하기 위한 기억 공간
- 변수를 만드는 형식 : 1. 자료형 설정 2. 변수명 설정 3. = 값 설정
- 자료형 변수명 = 데이터(값);

 

기본 자료형 변수
1. 정수형 변수 (Byte, Short, Int, Long)

byte b1 = 10; //-128 ~ +127 까지의 정수값 저장
//byte b2 = 130; //오버플로우 발생
short s = 100; // -32768 ~ +32767
int i = 1000; // -21억 ~ +21억 정도, 10의 9이상은 int사용
long l = 100000L; //long형변수를 만들때 대문자 L을 사용해야함 long형이란 표시
		
System.out.println("b1 = " + b1);  // JAVA는 , 가 아니라 +로 연결해야
System.out.println("s = " + s);
System.out.println("i = " + i);
System.out.println("l = " + l);

2. 실수형 변수 (float, double)

float ft1 = 3.14f; 
float ft2 = 3.14F; 
// 3.14란 데이터는 내부적으로 double형으로 인식하기때문에
// 8바이트를 4바이트로 자동변환이 안되므로 오류가 생김. F나 f를 붙여야함

float ft3 = (float)3.14; //또는 형변환 시켜도 됨

double d = 42.195; //실수형은 주로 double형을 쓴다
			
System.out.println("ft1 = " + ft1);
System.out.println("ft2 = " + ft2);
System.out.println("d = " + d);

+ 소수점 자리 제어하는 법 / 줄바꾸기

- printf라는 함수를 사용해서 쉽게 제어

- printf("%.2f" 라는 서식문자 입력, 출력값) : 소수 둘째자리까지 출력하라는 의미,반올림한다
- \n으로 줄바꾸기

System.out.printf("%.1f\n" , d); 
System.out.printf("%.2f\n" , d);

3. 문자형 변수

- char는 C언어는 1바이트지만 java는 2바이트임, 영어든 한글이든 무조건 1글자만 외따옴표안에 저장가능 'ab'(x) 불가능

+ 문자 두글자 넣을수있는 자료형은? -> 기본자료형으로 불가능 -> 새로운 자료형(참조형)이 있다
+ String 클래스 문자 몇글자든 넣을 수 있고 "" 로, but 중요한건 메모리상에서 데이터를 저장하는 방법이 다름

char c1 = 'A';
char c2 = '안';
System.out.println("c1 = " + c1);
System.out.println("c2 = " + c2);

4. 논리형 변수

- 자료형과 일치되는 값을 적어야, 같다가 아니라 넣어라의 의미

boolean bn1 = true;
boolean bn2 = false;

System.out.println("bn1 = " + bn1);
System.out.println("bn2 = " + bn2);

 

참조형 변수

1. 클래스

- 대표적인 클래스 String

+ String 생성 첫번째 방법 : 스트링 객체를 생성한다.

String s1 = "자바";

+ String 생성 두번째 방법 : new 연산자 써서 만든다.

String s2 = new String("자바");

* String은 두가지 방법 모두가 가능한 유일한 클래스임.
* 다른 클래스는 거의 new 연산을 써야만 만들어진다.

System.out.println("s1 = " + s1); // 자바 라고 출력됨(주솟값 출력되진 않음)
System.out.println("s2 = " + s2); // 자바 라고 출력됨(주솟값 출력되진 않음)

+ 데이터는 힙영역에 저장되고 s2는 그 주소값을 가지고 있게 된다.

 

참조형 변수의 비교

- 주소값 비교할땐 비교연산자로 비교한다.

if(s1 == s2){ 
System.out.println("같은 주소");
}else {
System.out.println("다른 주소");
}

출력 : 다른 주소
- 데이터 (값) 비교할땐 이렇게 해야한다.

if(s1.equals(s2)) { 
System.out.println("같은 값");
}else {
System.out.println("다른 값");
}

 

2. 배열

- 동일한 자료형의 데이터를 저장하는 정적인 자료구조

- int[] : int형배열을 만들겠다, []개수가 한차원

int[] score = {80, 90, 100};
for(int j = 0 ; j <score.length ; j++)
{
System.out.println(score[j] + "\t");
}
System.out.println();

3. 인터페이스

- 대표적인 인터페이스 List

- 인터페이스는 new 연산자로 생상할 수 없다. 자체적으로 객체생성 불가능

+ List 특징
1. 순차적인 자료구조
2. 여러가지 자료형의 데이터를 저장할 수 있다. (배열과 다르게 여러 자료형 혼용가능)
3. 동적으로 공간의 크기를 늘릴 수 있다.

//List list = new List(); //인터페이스는 new 연산자로 생상할 수 없다. 자체적으로 객체생성 불가능
List list = new ArrayList();//자료형 변환 관련 '업캐스팅'이란 개념. 동적으로 계속 늘려줌

list.add(30);//정수값을 저장
list.add(3.14);//실수값을 저장
list.add('j');//문자값을 저장
list.add(true);//논리값을 저장
list.add("자바");//문자(열)값을 저장
		
for(int k = 0 ; k <list.size() ; k++) {
	System.out.print(list.get(k) + "\t");
}

 

+ Recent posts