AWS 클라우드환경 네이티브 수업 55일차
진행
1. 자바 메소드(method)
2. 메소드의 종류
3. Java가 메모리를 사용하는 방식
4. 클래스 변수와 인스턴스 변수
5. 기본형과 참조형 변수의 차이
6. 메소드 오버 로딩
7. 생성자와 생성자 오버 로딩
8. this
요약
1. 자바 메소드(method)
2. 메소드의 종류
3. Java가 메모리를 사용하는 방식
4. 클래스 변수와 인스턴스 변수
5. 기본형과 참조형 변수의 차이
6. 메소드 오버 로딩
7. 생성자와 생성자 오버 로딩
8. this
메소드(method)
보통 타 프로그래밍 언어에서는 함수라는 것이 존재한다.
그리고 그 함수라는 것은 별도 존재하여 이용된다.
하지만 자바는 클래스를 벗어나서는 그 무엇도 존재할 수 없기 때문에
함수도 클래스 내에 존재하게 되고 그 함수를 메소드라고 부른다.
함수는 아래와 같은 구성으로 이루어져 있고 입력과 출력(return)으로 구성이 되어 있다.
함수를 사용하는 이유는 비슷한 작업을 할 때 반복적으로 구문을 만들지 않기 위해서이다.
메소드에 입력받는 변수를 매개변수
메소드 호출 후 넣는 값을 인수
라고 한다.
구조.
리턴자료형 메소드이름(자료형 매개변수, 자료형 매개변수) {
return 반복을 원하는 내용;
}
예.
public class Plus {
int sum(int a, int b) { // a, b 는 매개변수
return a+b;
}
public static void main(String[] args) {
Plus sample = new Plus();
int c = sample.sum(2, 4); // 2, 4는 인수
System.out.println(c); // 6 출력
}
}
메소드의 종류
1. 입력과 출력이 모두 있는 메소드
int sum(int a, int b) {
return a+b;
}
Example example = new Example();
int result = example.sum(2, 4);
2. 입력과 출력이 모두 없는 메소드
public class Example {
void hello() {
System.out.println("Hi");
}
public static void main(String[] args) {
Example aaa = new Example();
aaa.hello();
}
}
3. 입력은 없고 출력은 있는 메소드
public class Sample {
String hello() {
return "Hi";
}
public static void main(String[] args) {
Example aaa = new Example();
String Y = aaa.hello();
System.out.println(Y); // "Hi" 출력
}
}
4. 입력은 있고 출력은 없는 메소드
public class Example {
void plus(int a, int b) {
System.out.println(a + ", " + b + " 의 합은 " + (a+b));
}
public static void main(String[] args) {
Example aaa = new Example();
aaa.plus(2, 4);
}
}
Java가 메모리를 사용하는 방식
메모리는 아래와 같이 구성되어 있다.
코드 실행 영역 | 데이터 저장 영역 | |
코드 실행 영역 | Static 영역 - Class | |
Heap 영역 - 객체 | Stack 영역 - Method |
JRE(Java Runtime Environment)
클래스 라이브러리 및 특정 Java 프로그램이 실행해야 하는 기타 리소스를 제공하는 소프트웨어
JDK(Java Development Kit)
Java 애플리케이션의 개발을 위한 툴 세트
JVM(Java Virtual Machine)
라이브 Java 애플리케이션을 실행
JRE가 main() 메서드를 먼저 확인.후 존재가 확인되면 JVM을 부팅한다.
부팅된 JVM는 Object파일을 받아 실행한다.
JVM은 main() 이 실행되기 전에 기본적인 메모리 구조 세팅을 하고 시작을 하는데
- java.lang이라는 공통된 패키지가 있는데 해당 패키지를 Static 영역에 배치
- import 된 패키지를 Static 영역에 배치
- 모든 클래스를 Static 영역에 배치
이후
- main 메서드 stack frame이 Stack 영역에 배치
- 이후 클래스 내부의 만나는 중괄호 마다 프레임(해당 코드가 사용하기 위한 저장공간)을 만들어 놓는다.
- 이후 만나는 메소드 인자들을 해당되는 프레임 안에 저장 공간을 확보해서 배치한다.
이에 따라 메모리 영역별로
변수도 각각의 이름이 있는데 아래와 같다.
코드 실행 영역 | 데이터 저장 영역 | |
코드 실행 영역 | Static 영역 - Class - 클래스 멤버 변수 | |
Stack 영역 - Method - 지역 변수 | Heap 영역 - 객체 - 객체 멤버 변수 |
클래스 멤버 변수
JVM이 종료될 때까지 고정된(static) 상태로 존재한다.
객체 멤버 변수
가비지 컬렉터라고 하는 heap 메모리 회수기에 의해 일생을 마치게 된다.
클래스 변수와 인스턴스 변수
위와 같은 메모리가 사용되는 방식으로 인해
클래스 변수가 static 영역에 먼저 배치되고
그 이후에 인스턴스 변수가 배치가 된다.
이러한 배치 순서 차이로 인해, 오류가 발생할 수 있는데
아래 구문은 그 예를 보여준다.
package Parameter;
public class variCall {
int iv = 10; // 인스턴스 변수
static int cv = 20; // 클래스 변수
int iv2 = cv ;
//static int cv2 = iv; => 불가
//static이 static 영역에 생성되고 나서 인스턴스가 생성이 되는데
//지금 위의 경우, 동시에 생성이 되게 하고 있으므로 사용이 불가하다.
static int cv2 = new variCall().iv;
// static int cv2 = iv; 를 사용하고 싶다면 위와 같이 만들어야 한다.
static void staticMethod1() {
System.out.println(cv);
// System.out.println(iv); => 불가
// 같은 이유로 불가하다.
variCall c = new variCall();
System.out.println(c.iv);
}
void instanceMethod1() {
System.out.println(cv);
System.out.println(iv);
}
static void staticMethod2() {
staticMethod1();
//instanceMethod1(); => 불가
// 같은 이유로 사용 불가.
}
void staticMethod2() {
staticMethod1();
//instanceMethod1(); => 불가
// 같은 이유로 사용 불가.
}
}
기본형과 참조형 변수의 차이
메소드를 이용하여 기본형 변수와 참조형 변수의 차이를 확인해보려 한다.
기본형의 경우, 해당 값 자체를 가져온다.
참조형의 경우, 해당 값의 주소만을 가져온다.
이로 인해 차이가 생기게 되는데
아래의 예를 보자.
기본형 변수.
package Parameter.param1;
class Data{
int x ;
}
public class ParaExam1 {
public static void main(String[] args) {
Data d = new Data();
d.x = 10;
System.out.println("main() : x => " + d.x);
change(d.x);
System.out.println("After change()......");
System.out.println("main() : x => " + d.x);
}
static void change(int x) { // 기본형 변수를 가져온다.
x = 1000;
System.out.println("change() : x => " + x);
}
}
결과
main() : x => 10
change() : x => 1000
After change()......
main() : x => 10
위의 경우, 처음에 x에 10을 넣고
change(d.x) 에서 x에 1000을 넣었기에 출력이 1000으로 되나
마지막 d.x를 출력시에는 d.x와 change에서의 x는 다른 x이기 때문에 다른 값이 출력이 된다.
참조형 변수.
package Parameter.param2;
class Data{
int x ;
}
public class ParaExam2 {
public static void main(String[] args) {
Data d = new Data();
d.x = 10;
System.out.println("main() : x => " + d.x);
change(d);
System.out.println("After change()......");
System.out.println("main() : x => " + d.x);
}
static void change(Data d) {
d.x = 1000;
System.out.println("change() : x => " + d.x);
}
}
결과
main() : x => 10
change() : x => 1000
After change()......
main() : x => 1000
위의 경우, 처음에 x에 10을 넣고
change(d) 에서 d의 주소에 있는 x에 1000을 넣었기에 출력이 1000으로 되는데
마지막 d.x를 출력시에는 d.x와 change에서의 x는 같은 주소를 가진 같은 x이기 때문에 같은 값이 출력이 된다.
메소드 오버 로딩
같은 이름의 메소드로 다른 행동을 하는 메소드들을 정의하는 것을 의미한다.
오버로딩을 하는 조건
- 메소드 이름이 같아야한다.
- 매개변수의 갯수 또는 타입이 달라야 한다.
쉽게 말해서
같은 이름의 메소드를
매개변수의 갯수와 타입의 변화만으로
함수를 쉽게 추가로 만든다는 의미이다.
아래의 예제로 이해를 해보자.
package object;
public class Lecture {
public static void main(String[] args) {
Calcul cc = new Calcul();
System.out.println("cc.plus( 3, 3) => " + cc.plus( 3, 3));
System.out.println("cc.plus( 3, 3, 3) => " + cc.plus( 3, 3, 3));
System.out.println("cc.plus( 3L, 3L) => " + cc.plus( 3L, 3L));
System.out.println("cc.plus( 3, 3L) => " + cc.plus( 3, 3L));
System.out.println("cc.plus( 3L, 3) => " + cc.plus( 3, 3L));
int[] num1 = {70, 80, 90};
System.out.println("cc.plus(int[] num1) => " + cc.plus(num1));
}
}
class Calcul{
int plus(int num1, int num2) {
System.out.print("int plus(int num1, int num2) => ");
return num1 + num2;
}
int plus(int num1, int num2, int num3) {
System.out.print("int plus(int num1, int num2, int num3) => ");
return num1 + num2 + num3;
}
long plus(long num1, long num2) {
System.out.print("long plus(long num1, long num2) => ");
return num1 + num2;
}
long plus(int num1, long num2) {
System.out.print("long plus(int num1, long num2) => ");
return num1 + num2;
}
long plus(long num1, int num2) {
System.out.print("long plus(long num1, int num2) => ");
return num1 + num2;
}
int plus(int[] num) {
System.out.print("int plus(int[] num => ");
int result = 0;
for(int i= 0 ; i< num.length ; i++) {
result += num[i];
}
return result;
}
}
결과
int plus(int num1, int num2) => cc.plus( 3, 3) => 6
int plus(int num1, int num2, int num3) => cc.plus( 3, 3, 3) => 9
long plus(long num1, long num2) => cc.plus( 3L, 3L) => 6
long plus(int num1, long num2) => cc.plus( 3, 3L) => 6
long plus(int num1, long num2) => cc.plus( 3L, 3) => 6
int plus(int[] num => cc.plus(int[] num1) => 240
생성자
생성자는 인스턴스 변수를 초기화 시키는 역할을 한다.
메소드명이 클래스명과 동일하고 리턴 자료형을 정의하지 않는(void도 사용하지 않는다) 메소드이며,
객체가 생성될 때 호출된다.
즉, 생성자는 다음과 같이 new 키워드가 사용될 때 호출
클래스명 클래스이름 = new 클래스명(입력인수, ...)
만약 생성자가 선언되어 있는 경우라면 생성자의 규칙대로만 객체를 생성할 수 있다.
매개변수가 있다면 입력인수가 있도록 객체를 생성,
없다면 입력인수를 적지 않고 객체를 생성한다.
생성자에 입력인수를 입력할 필요가 없는 생성자를 디폴트 생성자(Default Constructor)라고 한다.
만약 클래스에 생성자가 하나도 없다면 컴파일러는 자동으로 위와 같은 디폴트 생성자를 추가한다.
아래의 예를 보자.
class Animal {
String name;
void setName(String name) {
this.name = name;
}
Animal(String name) {
this.setName(name);
}
// 생성자 선언
}
public class Sample {
public static void main(String[] args) {
Animal dog = new Animal();
// 이 녀석은 컴파일 에러가 발생한다.
Animal dog = new Animal("happy");
// 선언문 형식에 맞췄기 때문에 에러가 발생하지 않는다.
System.out.println(dog.name); // happy 출력
}
}
생성자 오버로딩
메소드 오버로딩처럼 생성자로 오버로딩이 있다.방식은 똑같다.
생성자의 이름은 똑같이, 매개변수만 변화를 주면 된다.
아래의 예를 보자.
package object;
class Data01{
int money;
Data01(){
System.out.println("기본 생성자 입니다.");
money = 100;
}
}
class Data02{
int money;
Data02(int x){ // 매개변수가 있는 생성자
money = x;
}
Data02(){ // 매개변수가 없는 생성자
money = 10;
}
}
public class Practice {
public static void main(String[] args) {
Data01 d1 = new Data01();
System.out.println("나의 돈은 " + d1.money + "만원입니다.");
Data02 d21 = new Data02(200);
System.out.println("나의 돈은 " + d21.money + "만원입니다.");
Data02 d22 = new Data02();
System.out.println("나의 돈은 " + d22.money + "만원입니다.");
}
}
결과
기본 생성자 입니다.
나의 돈은 100만원입니다.
나의 돈은 200만원입니다.
나의 돈은 10만원입니다.
package object;
class Car{
String color;
String gearType;
int door;
Car() {
color = "검정";
gearType = "수동";
door = 4;
}
Car(String c, String g, int d){
color = c;
gearType = g;
door = d;
}
}
public class Practice {
public static void main(String[] args) {
Car c1 = new Car();
System.out.println("c1 => " + c1.color + " : " + c1.gearType + " : " + c1.door);
Car c2 = new Car("노랑", "자동", 3);
System.out.println("c2 => " + c2.color + " : " + c2.gearType + " : " + c2.door);
}
}
결과
c1 => 검정 : 수동 : 4
c2 => 노랑 : 자동 : 3
this
객체 자신의 대한 참조값을 가지는 인스턴스 자신을 가르키는 구문이다.
클래스 메소드 및 생성자 내에서 자기 자신의 데이터를 이용하기 위해 사용한다.
이와 같은 이유로 메소드 내에서만 사용된다.
보통은
1. this.멤버변수 로 사용할 때
메소드 밖에 있는 매개 변수와 객체(메소드) 자신이 가지고 있는 변수의 이름이 같은 경우,
구분을 위해 this를 사용하거나
2. this.지역변수 로 사용할 때
객체 생성자 내에서 사용할 경우, 다른 생성자를 호출한다.
※ 참고
멤버 변수(member variable) : 메소드 밖에서 선언된 변수
지역(local) 변수 : 메소드 안에서 선언된 변수
마지막으로 static 메소드에서는 사용할 수 없다
아래는 this를 사용하는 예이다.
this 사용.
package object;
class Car{
String color;
String gearType;
int door;
Car() {
this("검정", "수동", 4);
}
Car(String color) {
this(color, "수동", 4);
}
Car(String color, String gearType, int door){
this.color = color;
this.gearType = gearType;
this.door = door;
}
}
public class Practice {
public static void main(String[] args) {
Car c1 = new Car();
System.out.println("c1 => " + c1.color + " : " + c1.gearType + " : " + c1.door);
Car c2 = new Car("노랑", "자동", 3);
System.out.println("c2 => " + c2.color + " : " + c2.gearType + " : " + c2.door);
Car c3 = new Car("빨강");
System.out.println("c3 => " + c3.color + " : " + c3.gearType + " : " + c3.door);
}
}
결과
c1 => 검정 : 수동 : 4
c2 => 노랑 : 자동 : 3
c3 => 빨강 : 수동 : 4
'코딩수업 > AWS 클라우드환경 네이티브' 카테고리의 다른 글
8/8 자바(Java) 클래스 활용 연습, comparTo 함수, 상속 (0) | 2022.08.08 |
---|---|
8/5 자바(Java) 초기화 및 순서, nextInt() 과 nextLine() 주의점, 접근제어자(public, protected, default, private), final (0) | 2022.08.05 |
7/29 자바(Java) 클래스와 객체 (참조 변수의 이해, Static ) (0) | 2022.07.29 |
7/28 자바(Java) 다차원 배열, 가변 배열, 배열의 복사, 다차원 배열 연습 문제 (0) | 2022.07.28 |
7/27 자바(Java) 배열, 배열의 반복문, 변수.length , 배열 연습 문제, Spring에 외부에서 가져온 프로젝트 넣기 (0) | 2022.07.27 |
댓글