자바 => 객체지향언어
객체 => 메서드(함수)
변수와 배열의 관계에 유의하며, Java에서는 배열이 객체임을 생각하자.
모든 메서드의 결과는 하나의 형태로 나온다.
메서드는 클래스 내에서 독립적으로 만들어야 한다.
→ 하나의 메서드는 하나의 단위작업을 처리하도록 한다.
자바제어자 반환타입 메서드명(입력매개변수){
수행작업
}
public int add(int x, int y){
int z = x + y;
return z;
}
반환값이 없을 경우 반환타입은 void
로 선언
public int add(int x, int y){
int z = x + y;
return z;
}
int result = add(3, 4); // add메서드 호출
System.out.println(result); // 7
위 예제의 경우 add함수가 z라는 결과를 만들어 낸다.
함수 이름이 변수 역할을 하며 함수 이름으로 값을 전달한다.
변수는 일반 자료형을 담는다면 함수는 데이터를 처리한 결과를 담는다.
add(3, 4)
에서 3. 4는 인수
혹은 매개변수
라고 부름.
매서드는 값이나 번지를 전달받는데, Java는 거의 번지를 전달한다.
1) Call By Value (값 전달)
public class CallByReference {
public static void main(String[] args) {
float a= 56.7f;
float b = 78.9f;
floatAdd(a, b);
System.out.println("종료");
// 결과: hap = 135.6\n종료
}
public static void floatAdd(float a, float b){
float hap = a + b;
System.out.println("hap = " + hap);
}
}
2) Call By Reference (번지 전달)
public class CallByReferenceExam {
public static void main(String[] args) {
int[] a = {1,2,3,4,5,6,7,8,9,10};
int result =addArray(a);
System.out.println("result = " + result);
// 결과: result = 55
}
public static int addArray(int[] a){
int sum = 0;
for (int i=0; i<a.length; i++){
sum+=a[i];
}
return sum;
}
}
위 예제에서 a
는 값이 아니라 배열 객체의 주소(번지)를 가지고 있다.
고로 매개변수로 주소값이 전달되는 것.
패캠Java/Spring 4주차 - Override 오버라이딩
예제
public class OverloadingTest {
public static void main(String[] args) {
int a = 3;
int b = 6;
int result1 = addNum(a, b);
System.out.println("result1 = " + result1);
float x = 3.1f;
float y = 6.2f;
float result2 = addNum(x, y);
System.out.println("result2 = " + result2);
}
// Q. 매개변수로 두 개의 정수값을 받아 총합을 리턴하는 메서드를 정의하시오.
public static int addNum(int a, int b) {
int sum = a + b;
return sum;
}
// Q. 매개변수로 두 개의 실수값을 받아 총합을 리턴하는 메서드를 정의하시오.
public static float addNum(float a, float b) {
float sum = a + b;
return sum;
}
}
두 메서드의 이름은 addNum
으로 동일하지만 매개변수의 타입이 다르므로 다른 메서드로 인식한다.
정적 바인딩이란 컴파일 시점에서 호출될 메서드가 결정되는 바인딩을 말한다.
개발자가 메서드 오버로딩
을 통해 같은 이름의 메서드를 여러개 만들어도 실제로는 컴파일 시 컴퓨터 내부에서는 서로 다른이름의 메서드로 인식된다
=> 즉, 메서드 오버로딩
을 한다고 메서드를 찾느라 속도저하가 발생하지는 않는다.
참고로 오버로딩과 반대로 추후 나올 개념인 오버라이드(override)
의 경우 동적 바인딩을 사용하므로 속도저하의 원인이 될 수 있다.
-학습정리 & quiz-
1. 기능?? → 메서드(Method)
2. 메서드 오버로딩(Method Overloading)
3. 매개변수의 타입, 갯수
4. 컴파일 시점에서 사용될 메서드가 결정되는 바인딩
5. 값 전달 기법(Call By Value), 주소 전달 기법(Call By Reference)
6. 하나의 형태
7. return
객체
를 만들기 위해 모델링 도구인 class
를 사용한다.
객체(Object)
= 모델(Model)
= 덩어리(Value Object)
= 이동(Data Transfer Object=DTO)
해당 클래스가 모델임을 알리기 위해 클래스 이름 뒤에 VO
나 DTO
를 붙이기도 한다. (안붙여도 무관함)
BookDTO b;
=> 책이라는 데이터를 변수에 저장하려면 책이라는 자료형이 필요하다. 이때 bookDTO라는 사용자정의 자료형을 지정한다.
객체를 설계(모델링)하는 도구.
혹은 자료형 측면에서는 사용자 정의 자료형을 만드는 도구.
=> 자료형 측면: 원하는 자료형의 객체를 만들기 위해 사용하는 도구
=> 객체지향 측면: 객체의 멤버변수와 멤버메서드를 가져와 설계하는 도구
public class BookDTO {
// 멤버 변수(필드)
public String title;
public int price;
public String company;
public String author;
public int page;
public String isbn;
// 멤버 메서드
public void printTitle(){
System.out.println("title = "+title);
}
}
new Book();
객체를 메모리에 생성하는 역할.
new
연산 메서드에 의해 호출됨public
인 경우에만 사용가능기본생성자(default constructor)
를 가지고 있음초기화
를 위해 사용됨BookDTO.java파일은 위의 예제를 그대로 사용함.
public class BookTest {
public static void main(String[] args) {
BookDTO book = new BookDTO();
book.title ="자바공부책";
book.titlePrint(); // 결과: title = 자바공부책
}
}
틀을 만들어두고 내용만 바꿔가며 객체를 찍어낼 수 있어 클래스와 객체는 흔히 붕어빵틀과 붕어빵에 비유되곤 한다.
자기 자신을 가리키는 객체변수(참조변수, 포인터 변수).
-학습정리 & quiz-
1. 사용자정의 자료형
2. 객체를 모델링하는 도구
3. 객체생성
4. 멤버변수(필드 Field), 멤버메서드
5. 생성자 메서드(Constructor)
6. this
7. 인스턴스(Instance)
클래스를 역할에 따라 부르는 이름을 모델(Model)
이라고 함.
역할에 따라 다양한 모델을 만들어 사용할 수 있다.
class
- 프로그래밍적 명칭
model
- 소프트웨어 공학적 명칭
종류
main 클래스 : 프로그램을 시작하는 클래스
DTO, VO Model : 데이터를 이동하기 위해 담는 모델
DAO Model : 데이터를 (DB와 연동하여)처리하는 모델
Utitliy Model : 도움을 주는 모델
데이터를 이동하기 쉽게 한번에 담을 수 있는 바구니 역할을 하는 모델.
- CarVO.java -
public class CarVO {
public int carSn;
public String carName;
public int carPrice;
public String carOwner;
public int carYear;
public String carType;
}
- CarTest.java -
public class CarTest {
public static void main(String[] args) {
// Q. 자동차의 정보를 [키보드로 부터 입력]받아 [다른 메서드]로 이동해야 하는 경우를 생각해보자.
Scanner scan = new Scanner(System.in);
CarVO car1 = new CarVO();
System.out.print("자동타 일련번호:");
car1.carSn = scan.nextInt();
scan.nextLine();
System.out.print("자동타 이름:");
car1.carName = scan.nextLine();
System.out.print("자동타 가격:");
car1.carPrice = scan.nextInt();
System.out.print("자동타 소유자:");
car1.carOwner = scan.nextLine();
scan.nextLine();
System.out.print("자동타 연식:");
car1.carYear = scan.nextInt();
scan.nextLine();
System.out.print("자동타 타입:"); // G(휘발유), D(경유)
car1.carType = scan.nextLine();
carInfoPrint(car1);
}
// Q. 매개변수로 자동차의 정보를 받아서 출력하는 메서드르 정의하시오.
public static void carInfoPrint(CarVO car){
System.out.println(car.carSn+"\t"+car.carName+"\t"+car.carPrice+"\t"+car.carOwner+"\t"+car.carYear+"\t"+car.carType);
}
}
위와 같은 예제를 CarDTO
클래스 없이 만드려면 매개변수로 일일히 하나씩 값을 보내줘야 하지만, DTO
클래스를 사용하면 하나의 객체만을 매개변수로 넘겨주면된다.
DB의 데이터를 가져와 사용할때에도 마찬가지.
Data Access Object
데이터베이스에 데이터를 검색, 삭제, 저장, 수정하기 위해 만들어진 클래스(모델)
= CURD동작을 가진 클래스 = 비즈니스 로직을 처리하는 클래스
예제
실제로 DB연결을 하지는 않고 어떤 역할을 하는지만 실습
- CarDAO.java -
public class CarDAO {
// CRUD
public void carInsert(CarVO car){
// DB연결, insert SQL
System.out.println("car정보가 DB에 저장되었습니다.");
}
}
- CarInsertTest.java -
public class CarInsertTest {
public static void main(String[] args) {
// 자동차정보를 키보드로 입력받아 DB에 저장하시오.(JDBC)
Scanner scan = new Scanner(System.in);
CarVO car1 = new CarVO();
System.out.print("자동타 일련번호:");
car1.carSn = scan.nextInt();
scan.nextLine();
// ...생략...
CarDAO dao = new CarDAO();
dao.carInsert(car1);
}
}
java.util
패키지에 Utility클래스가 많으니 참고해볼것예제
- CarUtilityTest.java -
public class CarUtilityTest {
public static void main(String[] args) {
// 자동차 정보를 출력하는 동작을 가진 Utility클래스를 설계하시오.
int carSn = 11111;
String carName = "BMW828i";
int carPrice = 90000000;
String carOwner ="홍길동";
int carYear = 2015;
String carType = "G";
CarVO car = new CarVO();
car.carSn=carSn;
car.carName=carName;
car.carPrice=carPrice;
car.carOwner=carOwner;
car.carYear=carYear;
car.carType=carType;
CarUtility carUtility = new CarUtility();
carUtility.carPrint(car);
}
}
- CarUtility.java -
public class CarUtility {
public void carPrint(CarVO car) {
System.out.println(car.carSn+"\t"+car.carName+"\t"+car.carPrice+"\t"+car.carOwner+"\t"+car.carYear+"\t"+car.carType);
}
}
main메서드에서는 객체를 만들기만 하고 출력하는 기능은 CarUtility
클래스로 옮겨서 기능을 분리함.
-학습정리 & quiz-
1. Model
2. DTO(VO), DAO, Utility
3. DTO, VO
4. DAO
5. Create, Read, Update, Delete
객체지향 프로그래밍에서는 보안을 위해 객체 상호간의 접근을 제어할 필요가 있음.
객체의 상태정보(멤버변수)는 중요하므로 일반적으로 접근을 막아야 한다.
반대로 행위정보(멤버메서드)는 상호작요이 필요하기 때문에 일반적으로 접근을 허용한다.
접근 제한을 위해서는 접근제한자
를 이용한다.
접근제한자
public
: 모든 클래스에서 접근가능 (모든 클래스는 public, 모든 멤버변수는 public)
private
: 모든 패키지에서 접근불가 (자기자신만 접근가능, 모든 멤버변수는 private)
protected
: 상속관계에서 하위클래스에서 상위클래스로 접근가능
default
: 동일한 패키지에서만 접근가능 (생략가능)
멤버변수는 private
로 선언 후 멤버변수에 접근하는 멤버메서드를 만들어 메서드를 통해 데이터를 다루는 방법을 사용한다.
패키지 이름을 알아야 해당 클래스를 import해서 사용하므로 어떤 패키지의 클래스를 쓰는지는 알아둬야 한다.
-학습정리 & quiz-
1. public, default, protected, private
2. pakage
3. java.lang
4. 풀네임, import
5. java.lang.String, java.util.Scanner
6. import
클래스는 객체를 모델링하는 도구로, 모델링(설계)을 잘해야 좋은 프로그램을 만들 수 있다.
자신의 정보를 숨기고 자신의 동작, 기능, 연산만을 통해 접근을 허용하는 것.
클래스 외부에서 특정 정보로의 접근을 막는 것.
예제1
// 객체 모델링(설계)
public class PersonVO(){
public String name;
public int age;
}
// 객체 생성
PersonVO p = new Person();
// 객체 사용(접근)
p.name = "홍길동";
p.age = 1000;
=> 멤버변수(필드)를 public으로 선언 시 제한없이 접근이 가능하다.
예제2
// 객체 모델링(설계)
public class PersonVO(){
private String name;
private int age;
}
// 객체 생성
PersonVO p = new Person();
// 객체 사용(접근)
p.name = "홍길동"; // 접근불가
p.age = 1000; // 접근불가
=> 멤버변수(필드)를 private으로 선언 시 접근이 불가능하다.
외부에서 접근이 불가능한 멤버변수(필드)에 값을 넣거나 가져오기 위해 사용하는 메서드.
public class PersonVO {
private String name;
private int age;
private String phone;
// setter
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setPhone(String phone) {
this.phone = phone;
}
// getter
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getPhone() {
return phone;
}
}
PersonVO p = new PersonVO();
p.setName("홍길동");
setter
메서드에서 this
는 자기자신을 가리키기 때문에 this.멤버변수명 = 매개변수;
는 매개변수로 받아온 값을 자기 자신에게 넣는 것이 된다.
초기화: 객체를 생성함과 동시에 생성된 메서드에서 데이터를 넣는 과정
생성자를 통하면 객체를 초기화할 수 있다.
public class PersonVO {
private String name;
private int age;
private String phone;
// 생성자메서드로 초기화
public PersonVO(){
this.name = "홍길동";
this.age = 50;
this.phone = "010-1111-1111";
}
}
단, 위의 예제에서의 생성자메서드를 사용하면 모든 객체가 똑같은 값을 가지게 된다.
이때 개발자가 원하는 값으로 객체를 생성하기 위해서는 생성자를 오버로딩(Overloading)
하여 매개변수로 받아온 값으로 객체를 초기화하는 방법을 사용한다.
// 기본생성자
public PersonVO() {}
// 오버로딩한 생성자
public PersonVO(String name, int age, String phone){
this.name = name;
this.age = age;
this.phone = phone;
}
// 기본생성자를 통한 생성
PersonVO p = new PersonVO();
// 오버로딩한 생성자를 통한 생성
PersonVO p1 = new PersonVO("홍길동", 50, "010-1111-1111");
PersonVO p2 = new PersonVO("김둘리", 100, "010-1000-1000");
일반적으로 기본생성자는 오버로딩하지 않는다.
또한 생성자를 오버로딩 했을 경우 컴파일러가 기본생성자를 자동생성하지 않으므로 직접 만들어주어야 함.
객체가 가진 값을 문자열 형태로 넘겨주는 메서드.
public class PersonVO {
private String name;
private int age;
private String phone;
// 생성자, setter getter 생략
@Override
public String toString() {
return "PersonVO{" +
"name='" + name + '\'' +
", age=" + age +
", phone='" + phone + '\'' +
'}';
}
}
PersonVO p1 = new PersonVO("홍길동", 50, "010-1111-1111");
System.out.println(p1.toString());
// 결과: PersonVO{name='홍길동', age=50, phone='010-1111-1111'}
toString
도 setter
getter
메서드처럼 이클립스나 인텔리제이에서 우클릭 → generate로 자동생성 가능.
-학습정리 & quiz-
1. 정보은닉
2. setter
3. getter
4. 생성자 메서드(Constructor)
5. toString()
기본배열
float[] arr = new Float[4];
arr[0] = 10.66f;
arr[1] = 30.1f;
arr[2] = 98.2f;
arr[3] = 67.5f;
객체배열
Student[] std = new Student[4];
std[0] = new Student("홍길동", "컴공", 22, "hong@gogle.com");
std[1] = new Student("박지성", "전기", 30, "park@gogle.com");
std[2] = new Student("홍길동", "건축", 26, "kim@gogle.com");
std[3] = new Student("홍길동", "통신", 21, "lee@gogle.com");
객체배열 선언 후 new생성자를 통해 메모리에 생성하는 과정이 필요함.
1) JVM이 실행할 클래스를 찾음
2) static
키워드가 있는 멤버들을 정해진 메모리 위치(static zone)에 한번 자동으로 로딩함
=> main()메서드는 static이기때문에 메모리에 자동으로 로딩된다.
=> static
키워드가 있는 멤버는 클래스를 사용하는 시점에 딱 한 번만 메모리에 로딩되는 점이 중요
3) JVM이 static zone에서 main()메서드를 호출
4) 호출된 메서드를 Stack Area에 push한 후 동작을 시작함
=> Stack Area의 program count를 보면 현재 실행중인 프로그램을 확인할 수 있다.
메모리에 static메서드끼리 올라가고 none static메서드끼리 올라감. 둘의 영역이 다르다.
static
키워드가 있는 멤버는 클래스를 사용하는 시점에 딱 한 번만 메모리에 로딩된다.
즉, 자동으로 메모리오 로딩되므로 new
를 통해 객체를 생성해줄 필요가 없다.
예제1
- StaticAccess.java -
public class StaticAccess {
public static void main(String[] args) {
int a = 10;
int b = 20;
int sum = MyUtil.hap(a,b);
System.out.println("sum = " + sum);
// 결과: sum = 30
}
}
- MyUtil.java -
public class MyUtil {
public static int hap(int a, int b){
int hap = a+b;
return hap;
}
}
=> static메서드는 객체생성이 불필요함.
이때 불필요한 객체생성을 막기 위해 생성자를 private
로 지정할 수 있다.
예시로 System.
을 입력하면 나오는 모든 메서드는 static
메서드이며 Math
메서드는 생성자가 private로 지정되어 있다.
Math.max(10, 20);
처럼 객체생성없이 사용.
객체를 생성하여 메모리에 로딩시켜야 함.
=> new
라는 연산자를 이용하면 heap메모리에 객체를 생성하고, static메서드에서 heap메모리의 번지를 참고하여 none-static메서드를 사용한다.
예제2
public class NoneStaticTest {
public static void main(String[] args) {
int a = 10;
int b = 20;
NoneStaticTest st = new NoneStaticTest();
int result = st.sum(a,b);
System.out.println("result = " + result);
// 결과: result = 30
}
public int sum(int a, int b){
int hap = a + b;
return hap;
}
}
메모리의 영역 Method Area
, Stack Area
, Heap Area
세 개 모두 필요한 예제임. (그림은 ppt참고)
변수는 선언한 메서드 내에서만 사용할 수 있으며, 이를 지역변수(local variable)이라고 한다.
다른 메서드에서 같은 이름의 지역변수를 선언하더라도 두 변수는 서로 다른 변수이다. (메모리에 생성되는 공간이 다름)
메서드를 call하면 휘하의 지역변수도 같이 메모리에 공간이 생성되고, 메서드가 종료되면 메서드와 같이 메모리에서 삭제되므로 메서드와 지역변수는 생명주기가 같다.
Garbage collector
에 의해 메모리가 수집됨.Program Counter
에 의해 현재 실행중인 프로그램의 위치가 관리됨.셋 다 객체를 나타내는 용어이다.
Class : 객체를 모델링하는 도구
public class Person(){
private String name;
private int age;
}
Object : 클래스를 통해 선언되는 변수
Student st;
=> st
: 변수가 구체적인 실체를 가리키지 않을때에는 객체변수
라고 함
Instance : 객체생성에 의해 Heap메모리에 만들어진 객체
st = new Student();
=> st
는 구체적인 실체를 가리키는 상태이므로 인스턴스 변수
라고 함
-학습정리 & quiz-
1. static
2. Stack
3. 생성자를 private로 만듦
4. 인스턴스 Instance
5. ...모르겠다 (답: Method Area, Stack Area, Heap Area, Literal POOL
패키지명을 java.part3로 변경하고 아래에 java파일을 생성한 후 실행하니
Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.part3
에러가 발생했다.
자바가 기본으로 제공하는 패키지명이 java
이기때문에 패키지명이 같으면 오류가 발생한다.
fcjava.part3
로 패키지명을 변경하자 정상적으로 실행되었다.
예시 - java.util, java.io, java.lang 등