객체, 클래스
* 객체
* 사전적 의미로, 현실세계에 독립적으로 존재하는 모든 것들을 의미.
* 목적이 있고, 의미가 있는 독립적인 객체.
*
* 객체 지향 언어
* 객체를 지향하는 언어로, 객체를 중심으로 돌아가는 언어를 뜻함.
*
* 객체지향 프로그래밍
* 현실 세계에서 독립적인 존재(객체)들 간의 상호작용(행동,행위)을 만들어냄
* ex) '사람'이 '공기'를 '마신다.'
* => 프로그래밍을 통해 가상세계(코드)를 구현하는 과정임.
*
* 클래스
* 기존의 클래스 개념 : 비슷한 역할을 하는 코드들의 모임.(변수, 메소드를 묶은 단위)
* 객체지향 클래스 : 각 객체(부품)의 속성(정보 => 변수,메소드)을 담아낼 수 있는 그릇, 틀
*
* 객체를 통해 현실세계를 프로그램 코드로 구현하기 위해서는
* 1단계. 추상화
* 2단계. 캡슐화 를 필요로 함.
추상화
* 현실세계의 것을 코드로 구현하는 과정
* 1. 내가 만들고자 하는 프로그램에서 필요한 객체를 생각함.
* 2. 객체들이 가지고 있는 공통적 특성, 기능을 최대한 추출함.
* 3. 추출한 결과물을 가지고, 실질적인 목적에 맞게 필요한 속성과 불필요한 속성으로 나눔
* 4. 최종적으로 필요한 속성만을 가지고 자료형, 변수를 정의함
*
* 예시
* 1. 학생관리 프로그램 => 학생(객체) : 홍길동, 김갑생, 박말똥,...
* 2. 성별, 키, 몸무게, 성적, 이름, 나이, 주소, 발사이즈, 혈액형,...
* 3. 필요한 속성 : 이름, 나이, 성별
* 4. String name, int age, char gender
*
* 본격적인 프로그래밍
* 1. 변수만을 가지고 프로그래밍
* 객체를 하나 만들기 위해서 필요한 변수의 개수 : 9
* String name1 = "홍길동"; int age1 = 20; double height1 = 170.1;
* String name2 = "고영희"; int age2 = 21; double height2 = 168.0;
* String name3 = "박말똥"; int age3 = 25; double height3 = 185.3;
* => 만들기도 힘들고, 유지보수를 할 수 없음.
*
* 2. 배열을 가지고 프로그래밍
* 객체를 하나 만들기 위해서 필요한 배열의 개수 : 3
* String[] names = {"홍길동","고영희","박말똥",....}
* int[] ages = {20, 21, 25,....}
* double[] heights = {170.1, 168.0 185.3,....}
* => 인덱스의 번호만 잘 안다면, 유용하게 활용할 수 있음.
* => 다만, 인덱스에 변화가 생기면(전학간다던가) 순서가 어긋날 수 있음.(실수할 가능성이 높아짐)
* => 한번 정해진 배열의 크기는 변하지 않음.(정원초과시, 배열을 다시 만들고, 배열복사를 해야함.)
*
* 3. 구조체(클래스)를 가지고 프로그래밍
* 구조체 : 한번에 여러개의 자료형, 여러개의 값을 보관 가능한 개념.
* 각 객체들의 속성 정보들을 담아내는 그릇과도 같은 존재(틀)
* Java에서는 클래스(VO : Value Object)라고 함.
* Student st = new Student();
* student => String name, int age, double height
package com.kh.chap01_abstraction.model.vo;
public class Student {
public String name;
public int age;
public double height;
}
package com.kh.chap01_abstraction.run;
import com.kh.chap01_abstraction.model.vo.Student;
public class Run {
public static void main(String[] args) {
Student student = new Student();
student.name = "홍길동";
student.age = 20;
student.height = 170.4;
System.out.println(student);
System.out.println(student.name);
System.out.println(student.age);
System.out.println(student.height);
System.out.printf("\"%s\"님의 나이는 %d살이고, 키는 %.1fcm입니다."
,student.name,student.age,student.height);
Student kim = new Student();
kim.name = "김철수";
kim.age = 25;
kim.height= 175.3;
System.out.println(kim);
System.out.printf("\"%s\"님의 나이는 %d살이고, 키는 %.1fcm입니다."
,kim.name,kim.age,kim.height);
캡슐화
* 위의 시점까지 추상화를 완료한 상태임.
* 다만, 추상화만 진행할 경우 보안상의 이슈가 발생하기때문에
* 이를 방지하기 위해 정보를 은닉해줄 필요가 있음.
* 여기에 사용되는 개념이 접근제한자와 메소드임.
package com.kh.chap01_abstraction.model.vo;
public class Student {
private String name;
private int age;
private double height;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setHeight(double height) {
this.height = height;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public double getHeight() {
return height;
}
public String information() {
return name + "님의 나이는 " + age + " 살 이고, 키는 " + height + " cm입니다.";
}
}
package com.kh.chap02_encapsulation.run;
import com.kh.chap02_encapsulation.model.vo.Student;
public class Run {
public static void main(String[] args) {
Student hong = new Student();
hong.setName("홍길동");
hong.setAge(20);
hong.setHeight(172.6);
System.out.println(hong.getName());
System.out.println(hong.getAge());
System.out.println(hong.getHeight());
System.out.println(hong.information());
Student kim = new Student();
kim.setName("김영희");
kim.setAge(21);
kim.setHeight(169.4);
System.out.println(kim.information());
}
}
필드부
변수
[종류]
*-전역 변수 : 클래스 영역 안에 바로 선언하는 변수 => 클래스 내에서면 어디서든 사용 가능.
*-지역 변수 : 클래스 영역 안에 어떤 특정한구역(중괄호 안) => 메소드, 제어문(for문,if문 등)
*
* 1.전역변수
*
* - 멤버변수(필드, 인스턴스변수)
* 생성시점 : new연산자를 통해서 해당 객체가 생성되는 순간, 메모리 영역에 할당.
* 소멸시점 : 객체가 소멸할때(값에 null 대입 등), 같이 소멸(GC가 객체를 청소하는 시점)
*
* - 클래스변수(static변수, [예약어])
* => 곧바로 실행할 준비가 되어있는 애들.
* => 실행하기 전에 객체를 생성하는 단계(new)가 필요하지 않음.
* => Stack, Heap, Static으로 메모리 공간 중 하나임.
* => 여기서 Stack, Heap은 동적인 공간, static은 정적인 공간임.
* => 동적인 공간은 공간을 만들고 없애고,
* => 정직인 공간은 이미 공간이 채워져있고 이를 불러서 사용.
* 생성시점 : 프로그램 시작과 동시에 메모리 영역에 할당이 됨.
* 소멸시점 : 프로그램이 종료될때 삭제됨.
*
* 2. 지역변수(매개변수, 메소드 내의 변수)
* 생성시점 : 특정한 구역(중괄호 안)실행 시, 메모리 영역에 올라감.(기본자료형은 Stack영역에)
* 소멸시점 : 특정한 구역(중괄호 안)실행이 종료될 때 같이 소멸(메소드 종료, 혹은 반복문 종료 등)
package com.kh.chap04_field.model.vo;
public class FieldTest1{
private int global;
public void test( int num){
int local = 0;
System.out.println(global);
System.out.println(num);
System.out.println(local);
}
}
package com.kh.chap04_field.run;
import com.kh.chap04_field.model.vo.FieldTest1;
public class FieldRun {
public static void main(String[] args) {
FieldTest1 f1 = new FieldTest1();
f1.test(10);
f1 = null;
}
}
접근제한자
* 접근제한자는 필드, 생성자, 메소드 모두에서 사용함.
* 단, 클래스에서는 public과 default만 사용 가능
* (+) public : 어디서든(같은 패키지, 다른패키지) 접근 가능하도록 함.
* (#) protected : 같은 패키지면 무조건 가능.
* 상황에 따라서 다른 패키지에도 접근 가능.
* ("상속 구조"일 경우에 다른 패키지에 접근 가능 )
* (~) default : 오로지 같은 패키지일 경우에만 가능. 생략 시 자동으로 적용됨.
* (-) private : 오직 해당 클래스 내에서만 사용 가능.
*
* => 위에서부터 아래로 내려갈수록, 접근할 수 있는 범위가 좁아짐.
* => 앞에 붙은 기호(+,#,~,-)들은 클래스 다이어그램이라고 함.
package com.kh.chap04_field.model.vo;
public class FieldTest2 {
public String pub = "public";
protected String pro = "protected";
String df = "default";
private String pri = "private";
}
1. 같은 패키지
package com.kh.chap04_field.model.vo;
public class Test {
public static void main(String[] args) {
FieldTest2 f2 = new FieldTest2();
System.out.println(f2.pub);
System.out.println(f2.pro);
System.out.println(f2.df);
}
}
2. 다른 패키지
package com.kh.chap04_field.run;
import com.kh.chap04_field.model.vo.FieldTest2;
public class FieldRun {
public static void main(String[] args) {
FieldTest2 f2 = new FieldTest2();
System.out.println(f2.pub);
}
}
Static변수
Static변수
* Static변수는 [예약어]에 해당하는 자리에 static을 붙인 것임.
* 프로그램 시작과 동시에 static이라는 메모리 영역에 자동으로 생성함.
* 공유의 개념이며, 객체생성을 할 필요없이 바로 사용할 수 있음.
* 단, import를 통해 어느 클래스에 있는지는 명확하게 해주어야 함.
* 생성시점 : 프로그램이 시작과 동시에 static영역에 할당.
* 소멸시점 : 프로그램이 종료됨과 동시에 소멸
package com.kh.chap04_field.model.vo;
public class FieldTest3 {
public static String sta = "Static 변수";
public String str = "그냥 멤버변수";
public static void test() {
System.out.println("안녕");
}
}
package com.kh.chap04_field.run;
import com.kh.chap04_field.model.vo.FieldTest3;
public class FieldRun {
public static void main(String[] args) {
System.out.println(FieldTest3.sta);
FieldTest3.test();
}
}
상수필드
상수필드
* 변수에서 학습한 상수와 개념이 똑같음.
* 한번 지정된 값은 고정해서 사용하기 때문에,
* 무조건 처음에 선언과 동시에 초기화를 해주어야 함.
* 예약어와 final은 순서가 바뀌어도 됨.
* 필드명은 모두 대문자로 작성해줌
* [표현법] public static final 자료형 필드명 = 값;
package com.kh.chap04_field.model.vo;
public class FieldTest3 {
public static final int NUM = 1;
}
package com.kh.chap04_field.run;
import com.kh.chap04_field.model.vo.FieldTest3;
public class FieldRun {
public static void main(String[] args) {
System.out.println(FieldTest3.NUM);
}
}
생성자부
생성자
*이름이 클래스명과 같고, 리턴 자료형(반환형)이 없는 일종의 메소드.
*본래, 리턴자료형이 없으면 void를 쓰나, 생성자부에서는 아예 쓰지 않음.
*객체가 생성(new 클래스명();)할때, 호출되는 것이 기본생성자임.
*기본적으로 매개변수가 없는 기본형태의 생성자는 JVM이 만들어줌.
*
*[표현법]
*public 클래스명(매개변수=>생략가능){ 실행할 코드; }
*
*[목적]
*1. 객체를 생성하기 위함.
*2. 객체를 생성할 뿐만 아니라, 매개변수로 전달된 값을 곧바로 필드에 초기화함.
*(배열에서 선언과 동시에 초기화를 했던 것과 같다고 보면 됨.)
*
*[주의할 점]
*1. 생성자의 이름은 반드시 클래스명과 동일해야 함(대소문자 구분 확실히!)
*2. 반환형을 쓰면 안됨. => 반환형을 쓰면 메소드들이랑 구분이 안가기 때문임.
*3. 여러개 작성이 가능함.=> 단, 매개변수가 중복되지 않는 경우에만 중복작성이 가능.
*4. 매개변수가 있는 생성자를 명시적으로 작성하면, JVM이 기본생성자를 자동으로 만들어주지 않음!
*=> 기본생성자는 항상 만드는 습관을 들일 것!
*
package com.kh.chap05_constructor.model.vo;
public class User {
private String userId;
private String userPwd;
private String userName;
private int age;
private char gender;
public User() {
System.out.println("호출 확인");
}
public User() {}
public User(String userId, String userPwd, String userName) {
this.userId =userId;
this.userPwd = userPwd;
this.userName = userName;
}
public User(String userId, String userPwd, String userName,
int age, char gender) {
this(userId,userPwd,userName);
this.age = age;
this.gender = gender;
}
public void setUserId(String userId) {
this.userId = userId;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setAge(int age ) {
this.age = age;
}
public void setGender(char gender) {
this.gender = gender;
}
public String userId() {
return userId;
}
public String userPwd() {
return userPwd;
}
public String userName() {
return userName;
}
public int age() {
return age;
}
public char gender() {
return gender;
}
public String information() {
return "userId : " +userId + ", userPwd : "+userPwd+", userName : "+userName
+", age : "+age+", gender : "+gender;
}
}
package com.kh.chap05_constructor.run;
import com.kh.chap05_constructor.model.vo.User;
public class ConstructorRun {
public static void main(String[] args) {
User u1 = new User();
System.out.println(u1.information());
u1.setUserId("user01");
u1.setUserPwd("pass01");
u1.setUserName("홍길동");
u1.setAge(20);
u1.setGender('남');
System.out.println(u1.information());
User u2 = new User("user02","pass02","김말똥");
System.out.println(u2.information());
u2.setAge(15);
u2.setGender('남');
System.out.println(u2.information());
User u3 = new User("user03","pass03","동동이",20,'남');
System.out.println(u3.information());
}
}
메소드부
메소드(매개변수, 반환형)
* [표현법]
* 접근제한자[예약어] 반환형 메소드명(매개변수=> 생략 가능){
*
* 실행할 코드;
*
* return 반환할 값; => 생략 가능 : 반환형이 void일 경우만
* }
* 메소드를 정의한 다음, 얼마든지 호출이 가능함.
*
* 경우의 수를 만들어서 메소드 테스트
* 1. 매개변수X, 반환값X (늘 만들던 케이스)
* 2. 매개변수X, 반환값O
* 3. 매개변수O, 반환값X
* 4. 매개변수O, 반환값O
* => 반환값이 있으면(return), 결과값을 메소드를 호출한 곳으로 가서 사용할 수 있음.
* => 반환값이 없으면(void), 결과값이 없기 때문에 메소드 내에서만 값을 사용할 수 있음.
* => 따라서, return시에는 호출된 메소드에서 Sysout을 해줌.
* void시에는 메소드 내에서 Sysout을 해줌.
* => 다만, return시에는 메소드내에서 sysout을 해줘도 결과가 출력됨.
package com.kh.chap06_method.controller;
public class MethodTest1 {
public void method1() {
System.out.println("매개변수와 반환값이 둘다 없는 메소드입니다.");
int sum =0;
for(int i=1; i<=10; i++) {
sum=sum+i;
}
System.out.println("총합 : "+sum);
}
public int method2() {
System.out.println("매개변수가 없고 반환값은 있는 메소드입니다.");
return (int)((Math.random()*100)+1);
}
public void method3(int num1, int num2) {
System.out.println("매개변수가 있고 반환값이 없는 메소드입니다.");
int min=0;
int max=0;
if(num1 > num2) {
min = num2;
max = num1;
}else {
min = num1;
max = num2;
}
System.out.println("최대값 : "+max+"\n최소값 : "+min);
}
public int method4(int a, int b) {
System.out.println("매개변수가 있고 반환값도 있는 메소드입니다.");
return a*b;
}
}
package com.kh.chap06_method.run;
import com.kh.chap06_method.controller.MethodTest1;
public class MethodRun {
public static void main(String[] args) {
System.out.println("------------MethodTest1 클래스------------");
MethodTest1 m1 = new MethodTest1();
m1.method1();
System.out.println("--------------------------------");
System.out.println("랜덤값 : "+m1.method2());
System.out.println("--------------------------------");
m1.method3(1,10);
System.out.println("--------------------------------");
System.out.println(m1.method4(1, 10));
static 메소드
* 메소드의 경우, 호출시 new 구문으로 객체를 생성할 필요 없음
* 위와 마찬가지로 매개변수, 반환형을 가지고 작성해봄.
package com.kh.chap06_method.controller;
public class MethodTest2 {
public static void method1() {
System.out.println("매개변수도 없고, 반환형도 없는 static 메소드");
}
public static String method2() {
return "매개변수는 없지만, 반환값은 있는 static 메소드";
}
public static void method3(String name, int age) {
System.out.printf("%d살의 %s님 환영합니다.\n",age,name);
}
public static int method4(int num1, int num2, char op) {
int result = 0;
switch(op) {
case '+' : result = num1 + num2; break;
case '-' : result = num1 - num2; break;
case '*' : result = num1 * num2; break;
case '/' : result = num1 / num2; break;
case '%' : result = num1 % num2; break;
default : result = -99999;
}
return result;
}
}
package com.kh.chap06_method.run;
import com.kh.chap06_method.controller.MethodTest2;
public class MethodRun {
public static void main(String[] args) {
System.out.println("------------MethodTest2 클래스------------");
MethodTest2.method1();
System.out.println("---------------------------------");
System.out.println(MethodTest2.method2());
System.out.println("---------------------------------");
MethodTest2.method3("홍길동", 20);
System.out.println("---------------------------------");
System.out.println(MethodTest2.method4(10, 6, '*'));
}
}
메소드 오버로딩
* 한 클래스 내에 같은 메소드명으로, 여러 메소드를 정의할 수 있는 방법.
* 즉, 메소드의 이름이 중복되도 허용함.
*
* 오버로딩 규칙
* 1. 메소드명은 동일해야함.
* 2. 매개변수의 자료형의 개수, 순서를 다르게 작성해야 함.
* 3. 메소드의 접근제한자, 예약어, 반환형, 매개변수명은 오버로딩에 영향을 주지 않음.
/*
*오버로딩이 잘 된 예시
*System.out.println : 매개변수의 개수가 같더라도 종류가 다른 예시
*System.out.printf : 매개변수의 개수가 대놓고 다른 예시
*이전에 했던 "생성자" 예시
*/
public class OverloadingTest {
public void test() {
System.out.println(0);
System.out.println('1');
System.out.println(1.1);
System.out.println("하이");
System.out.println(true);
}
public void test(int a) {}
public void test(int a, String s) {}
public void test(String s, int a) { }
public void test(int a, int b) { }
public void test(int a, int b, String s) {}
}