Java - 객체

kojam9041·2022년 3월 18일
0

KH정보교육원 - JAVA

목록 보기
8/12

객체, 클래스

 * 객체
 * 사전적 의미로, 현실세계에 독립적으로 존재하는 모든 것들을 의미.
 * 목적이 있고, 의미가 있는 독립적인 객체.
 *
 * 객체 지향 언어 
 * 객체를 지향하는 언어로, 객체를 중심으로 돌아가는 언어를 뜻함.
 * 
 * 객체지향 프로그래밍
 * 현실 세계에서 독립적인 존재(객체)들 간의 상호작용(행동,행위)을 만들어냄
 * 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) {
//	클래스라는 개념을 가지고 프로그래밍을 할 것!
		
//	1. Student 클래스 만들기
//	2. Student 클래스의 객체 생성(new)
//	자료형 변수 = new 자료형();
//	배열과 비슷하나, 배열은 같은 자료형, 객체는 다른 자료형을 담을 수 있음.	

//	Stack           Heap
//                  0123
//	student ------> name  age  height
//	0123            null   0    0.0

	Student student = new Student();
//	그동안은 메소드를 호출할 때, 객체명.메소드명(); 으로 호출하였음.
//	필드의 이름을 불러와서 거기에 담긴 값을 뽑아오고 싶음.=>객체명.필드명
		
//	3. 필요한 값을 필드에 담기.
	student.name = "홍길동";
	student.age = 20;
	student.height = 170.4;
//	해당 student라는 객체의 각 필드에 직접적으로 접근해서 값을 대입.
		
//	4. 값이 제대로 담겨있는지 출력해보기
		
//	Stack           Heap
//                  0123
//	student ----->  name  age  height
//	0123            홍길동  20   170.4
//	 
	System.out.println(student); // com.kh.chap01_abstraction.model.vo.Student@6d06d69c
//	String을 제외하고는 참조형 변수는 실제값이 아닌, 주소값이 나온다고 했었음.		
		
	System.out.println(student.name);	// 홍길동
	System.out.println(student.age);	// 20
	System.out.println(student.height);	// 170.4
//	해당 student라는 객체의 각 필드에 직접적으로 접근해서 값을 꺼내옴.
//	여기서 점(.)을 '직접 접근연산자'라고 함.
		
//	ooo님의 나이는 xxx살이고, 키는 xxxcm입니다. 
	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); // com.kh.chap01_abstraction.model.vo.Student@677327b6
	System.out.printf("\"%s\"님의 나이는 %d살이고, 키는 %.1fcm입니다."
					  ,kim.name,kim.age,kim.height);
//	kim = student;
//	이렇게 작성하면 얕은 복사로, kim을 수정 시 student도 수정됨.
	/* 
     * 다만, 추상화만 진행할 경우, 직접 값을 조회하거나 대입하여 변경할 수 있기 때문에,
     * 보안의 3요소를 해칠 수 있음.
	 * => 보안의 3요소 : 기밀성, 무결성, 가용성
     * => 조회(기밀성 훼손), 값 대입(무결성훼손(원본훼손))
	 *
     */     

캡슐화

* 위의 시점까지 추상화를 완료한 상태임.
* 다만, 추상화만 진행할 경우 보안상의 이슈가 발생하기때문에 
* 이를 방지하기 위해 정보를 은닉해줄 필요가 있음.
* 여기에 사용되는 개념이 접근제한자와 메소드임.

package com.kh.chap01_abstraction.model.vo;
//  클래스는 필드부, 생성자부, 메소드부로 나뉜다.
//  학생들을 추상화해서 만든 클래스	
	public class Student {
//	[필드부]
//	필드 : 클래스 안의 변수(값 1개를 담는 공간) => 자료형 변수명;
//		  메소드 안의 변수는 "지역변수", 클래스 안의 변수는 "전역변수"라고 함.
//	접근제한자 자료형 필드명;
//	접근제한자 : 이 필드에 접근할 수 있는 범위를 제한할 수 있는 키워드
//	(public> protected> default> private)
//	클래스 영역 안에서 필드를 선언할 때 반드시 접근제한자를 써주어야 함.
//	생략할 경우에는 자동적으로 default로 잡힘
// 1. 필드의 접근제한자를 public에서 private로  
   private String name;		
   private int age;
   private double height;
   
// [생성자부]

// [메소드부]
// 2. 필드의 값에 간접적으로 접근이 가능하도록 getter/ setter메소드 작성
	/* 각 기능들을 구현하는 부분
	 *
	 * ↓ 매개변수(재료)
	 * 접근제한자 void(또는 반환할 결과의 '자료형') 메소드명(매개변수 => 생략가능){
	 *          => 결과를 보여주지 않는 대신 자료형이라도 보여주겠다는 뜻.
	 *         	=> void : 반환할 결과값이 없다는 뜻. 
	 *         	=> return :  호출된 명령으로 값을 반환한다는 의미임.
	 * 	}
	 * ↓ 결과값
	 * 
	 */
// 데이터를 기록 및 수정하는 기능의 메소드 : setter메소드
// => 실행 내용이 필드에 값을 대입하는 구문 형식으로 작성
// => 필드에 값을 변경하지 못하게 하려면, setter메소드를 작성하지 않으면 됨.
// => 이 메소드는 필드에 접근 가능하도록 하기 위해 public을 사용함.
	
// 이름값을 기록 및 수정할 수 있는 기능의 메소드(name이라는 필드에 값을 대입하는 용도)
   public void setName(String name) { 
					 // 매개변수는 for문의 초기식과 같음.
					 // 매개변수(지역변수)가 필드변수(전역변수)보다 우선순위가 높음.
			this.name = name;
			// String name은 메소드의 변수이고
			// this.name은 필드의 변수임.
			// => this는 현재의 필드(클래스)를 가리킴.
			// this를 빼게 되면, name=name;으로 매개변수로만 코드를 구성하게됨.
			// => 오류는 뜨지 않지만, 매개변수로 매개변수를 수정하겠다고 하여 메소드가 쓸모없게됨.
			// this.name = name;로 하여 필드변수 = 매개변수;로 하여 우선순위를 차등함
			// 이는, 메소드의 변수로 필드의 변수를 수정하겠다는 뜻임.
	}
    
//	나이값을 기록 및 수정할 수 있는 기능의 메소드(age라는 필드에 값을 대입하는 용도)
	public void setAge(int age) {
		this.age = age;
	}
    
//	키값을 기록 및 수정할 수 있는 기능의 메소드(height라는 필드에 값을 대입하는 용도)
	public void setHeight(double height) {
		this.height = height;
	}
        
//	데이터를 반환해주는 기능의 메소드 : getter메소드
// 	name이라는 필드에 담긴 값을 돌려주는 용도의 메소드

//	이름값을 반환해주는 기능의 메소드
	public String getName() {
			 		 // 결과값을 return으로 돌려보내 결과물을 반환해야하므로
			 		 // void가 아닌 반환형을 씀.
			return name;
			// 반환할 내용 => return 내용물;
			// 값을 변경하려는 것도 아니고,
			// 메소드 내에 매개변수가 존재하지 않기 때문에
			// 굳이 this를 붙이지 않음.
	}
    
//	나이값을 반환해주는 기능의 메소드
	public int getAge() {
			return age;
	}
//		키값을 반환해주는 기능의 메소드
	public double getHeight() {
			return height;
	}
//	이처럼, 캡슐화는 getter, setter메소드들을 만들어주는 것을 의미함.
//	필드마다 꼭 1개씩은 만들어주어야 함.

//  한큐에, 현재 필드에 담겨있는 모든 값들을 하나의 문자열로 합쳐 내보내는 메소드
	public String information() {
		// return name, age, height; (X) => return구문시 작성된 결과값은 한개뿐이어야 함.
		// 따라서, 꼼수로 자료형을 String으로 하고, 한줄로 모든 내용을 문자열로 취급해버림.
		return name + "님의 나이는 " + age + " 살 이고, 키는 " + height + " cm입니다.";
	}
}

package com.kh.chap02_encapsulation.run;
import com.kh.chap02_encapsulation.model.vo.Student;

public class Run {
	/*
	 * 캡슐화의 단계
	 * 1) 각 필드에 접근제한자로 private를 붙여서 숨기기.
	 * 2) setter / getter 메소드 만들기
	 * 3) 정보 출력 메소드 만들기
	 * =>매번 정보 출력시 출력문을 작성하기 귀찮으니, information을 만듬.
	 */

	public static void main(String[] args) {
//		1.학생 정보를 담을 객체를 만들기(객체화, 인스턴스화)
		Student hong = new Student();	//import할 시 클래스의 정확한 위치 기입!
//		name=null, age=0, height=0.0(기본값)

		/*
		2.초기화 혹은 값 대입 
		hong.name="홍길동";
		hong.age=20;
		hong.height=172.6;
		캡슐화(private)로 인해 보이지 않게 되어 접근 할 수 없음.
		*/
        
//		3. 간접적으로 접근하기
//		getter, setter를 통해 값의 대입,값의 출력을 메소드 호출로 진행함.
//		필드에 직접 값을 대입하는 것이 아닌, 
//		메소드 내에서 필드를 바탕으로 연산작용을 하여, 그 결과를 보여주는 것임.
//		객체명.메소드명();
		
		hong.setName("홍길동");
		hong.setAge(20);
		hong.setHeight(172.6);
		
//		4. 잘 담겨있나 조회.
//		System.out.println(hong.name);
//		System.out.println(hong.age);
//		System.out.println(hong.height);
//		기존의 방법(캡슐화 전)으로는 실행되지 않음.
		
		System.out.println(hong.getName());
		System.out.println(hong.getAge());
		System.out.println(hong.getHeight());
//		잘실행되는 것을 볼 수 있음.
		
//		xxx님의 나이는 xx살이고, 키는 xxxcm입니다. 
//		System.out.printf("%s 님의 나이는 %d살이고, 키는 %.1fcm입니다.",
//				hong.getName(),hong.getAge(),hong.getHeight());
		System.out.println(hong.information());
		
		
//		김영희 학생이라는 객체를 만들어보세요
//		객체명 : kim
//		나이 : 21, 키 : 169.4
		Student kim = new Student();
		
		kim.setName("김영희");
		kim.setAge(21);
		kim.setHeight(169.4);
		
//		System.out.printf("%s 님의 나이는 %d살이고, 키는 %.1fcm입니다.",
//				kim.getName(),kim.getAge(),kim.getHeight());		
		
		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; /*지역변수*/
        // 기본자료형과 String은 값을 대입하거나 초기화해주는 습관을 들일 것.
        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) {
   	//  =====1. FieldTest1 클래스 =====
    	FieldTest1 f1 = new FieldTest1(); 
    //  객체 생성 : 필드변수 사용 가능 
    //  int global = 0;
    
    	f1.test(10);
    //  메소드 사용 : 매개변수, 지역변수 사용 가능 
    // 	int num = 10;
    //  int local = 0;
    
    //  System.out.println(num)
    //  System.out.println(local)
    //  메소드가 void형이기 때문에, 메소드가 실행과 동시에 종료되어 매개변수, 지역변수 사용 불가
    
    	f1 = null;
    //  참조하는 연결고리가 끊어짐.
    //  이 시점부터 f1의 행방을 알 수 없기 때문에, 필드변수 사용 불가
        
    }
}

접근제한자

* 접근제한자는 필드, 생성자, 메소드 모두에서 사용함.
* 단, 클래스에서는 public과 default만 사용 가능
* (+) public : 어디서든(같은 패키지, 다른패키지) 접근 가능하도록 함.
* (#) protected : 같은 패키지면 무조건 가능.
* 				  상황에 따라서 다른 패키지에도 접근 가능. 
* 				  ("상속 구조"일 경우에 다른 패키지에 접근 가능 )
* (~) default : 오로지 같은 패키지일 경우에만 가능. 생략 시 자동으로 적용됨.
* (-) private : 오직 해당 클래스 내에서만 사용 가능.
* 
* => 위에서부터 아래로 내려갈수록, 접근할 수 있는 범위가 좁아짐.
* => 앞에 붙은 기호(+,#,~,-)들은 클래스 다이어그램이라고 함.

package com.kh.chap04_field.model.vo;
public class FieldTest2 {

	public String pub = "public";
	protected String pro = "protected";
	/*default*/ 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();
        // => 같은 패키지 안에 있어, import 필요 없음.
        System.out.println(f2.pub);	// 같은 패키지, 다른 패키지 모두 가능
        System.out.println(f2.pro); // 같은 패키지 가능, 다른 패키지 불가(상속시 가능)
        System.out.println(f2.df); // 같은 패키지에만 가능, 다른패키지 불가
        // System.out.println(f2.pri); // 다른 클래스여서 불가.
    }

}

2. 다른 패키지
package com.kh.chap04_field.run;
import com.kh.chap04_field.model.vo.FieldTest2;


public class FieldRun {

	public static void main(String[] args) {
		// =====2. FieldTest2 클래스 =====	
		FieldTest2 f2 = new FieldTest2();
		System.out.println(f2.pub); // 어디서든 직접접근 가능.
		
		// not visible
		// System.out.println(f2.pro);  같은 패키지O, 다른패키지X(상속시 O)
		// System.out.println(f2.df);  같은 패키지O, 다른패키지X
		// System.out.println(f2.pri);  같은 클래스O
		//캡슐화에서 활용했었음.	
    }
}

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("안녕");
	}
    // static은 메소드에도 붙일 수 있음.
}

package com.kh.chap04_field.run;
import com.kh.chap04_field.model.vo.FieldTest3;

public class FieldRun {

	public static void main(String[] args) {
   	// =====3. FieldTes3 클래스 =====
	System.out.println(FieldTest3.sta); 
    // Static변수(클래스 변수), 객체생성 필요없음.

	// System.out.println(FieldTest3.str);
    // 일반 필드 변수
	// [오류메세지]
	// Cannot make a static reference to the non-static field FieldTest3.str
	// str은 static영역에 속해있지 않아, 객체생성을 해주어야 함.
    
	FieldTest3.test();
	//	변수 이외에도 메소드도 static을 이용하여 다음과 같이 호출할 수 있음.
	//	static의 가장 대표적인 예 => Math
    }
}

상수필드

상수필드
* 변수에서 학습한 상수와 개념이 똑같음.
* 한번 지정된 값은 고정해서 사용하기 때문에, 
* 무조건 처음에 선언과 동시에 초기화를 해주어야 함.
* 예약어와 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) {
    // FieldTest3.NUM=100;
	// Math.PI = 100;
    // [오류메세지]
	// The final field FieldTest3.NUM cannot be assigned
	// 상수는 다른값으로 변경할 수 없음.
    
    System.out.println(FieldTest3.NUM); // 1
	}
}

생성자부

생성자

 *이름이 클래스명과 같고, 리턴 자료형(반환형)이 없는 일종의 메소드.
 *본래, 리턴자료형이 없으면 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(/*매개변수*/) {
//	기본 생성자 : 매개변수가 없는 생성자.
//	=> 단지, 객체를 생성하기 위한 목적으로만 사용
//	=> new연산자를 사용하여 Heap영역에 메모리 할당.
//	기본생성자를 생략해도 오류가 나지 않음
//	=> JVM이 자동으로 기본생성자를 만들어 주기 때문에.
//	=> 단, 매개변수가 있는 생성자가 주기적으로 작성되어 있는 경우,
//	=> 기본 생성자를 JVM이 자동으로 만들어 주지 않음.
//	=> 이 경우에 의해, 항상 기본생성자를 만드는 습관을 들이도록!
		System.out.println("호출 확인");
	}
	
	
	public User() {}
//	[오류메세지]
//	Duplicate method User() in type User
//	생성자명은 중복될 수 없음.
	
	
	public User(String userId, String userPwd, String userName) {
//	매개변수가 다르면 생성자명을 똑같이 해도 됨.
		
		this.userId =userId;
		this.userPwd = userPwd;
		this.userName = userName;
//		setter메소드 vs 매개변수 생성자
//		생성자를 기준으로 작성하고서, 이후에 일부 필드 값만 한두개 바뀌는 상황이 생긴다면
//		setter메소드를 사용하는 것이 더 유리하기 때문에 사용함.	
	}
    
	public User(String userId, String userPwd, String userName, 
			int age, char gender) {
//	모든 필드에 대하여, 매개변수를 갖고있는 생성자
//	=> 필드가 5개이면, 매개변수도 5개임.
//	=> 객체를 생성하고, 그 순간 내가 원하는 값으로 초기화까지 시킴.
//  => 얘도 기본생성자처럼 항상 만드는 습관을 들이면 좋음(기본생성자와 달리 필수는 아님)
		
		/*
		this.userId = userId;
		this.userPwd = userPwd;
		this.userName = userName;
		*/
		this(userId,userPwd,userName);
//		중복되는 내용은 이렇게 써도 됨.
//		중복되는, 초기화 하는 내용의 생성자가 이미 존재할 경우, this생성자 사용
//		this생성자 :같은 클래스 내에 다른 생성자를 호출하는 구문.
//		this생성자는 항상 가장 윗줄에 있어야 함.
		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) {
//		기본생성자 호출 테스트
//		구문 : new로 객체를 생성하는 구문
//		클래스명 객체명 = new 생성자명();
		User u1 = new User();
//		기본 생성자 주석 처리시, 오류가 뜸
//		[오류메세지]
//		The constructor User() is undefined
//		
		
		System.out.println(u1.information());
//		JVM에 의해 기본값이 담김.(null,0,0.0,'') => 여기까지가 기본생성자의 역할
		
		u1.setUserId("user01");
		u1.setUserPwd("pass01");
		u1.setUserName("홍길동");
		u1.setAge(20);
		u1.setGender('남');
		
		System.out.println(u1.information());
		
//		매개변수가 userId,userPwd,userName인 생성자 호출 테스트
		User u2 = new User("user02","pass02","김말똥"); // 괄호안에 매개변수를 생략하면 기본생성자의 결과가 출력됨.
		System.out.println(u2.information());
//		userId, userPwd, userName의 필드는 객체생성과 동시에
//		내가 원하는 값으로 채워지고, 이외의 값은 기본값으로 채워짐.
		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 {
// 	1. 매개변수X, 반환값X (항상 만들어왔음)
	public void method1() {
		System.out.println("매개변수와 반환값이 둘다 없는 메소드입니다.");
		// 1부터 10까지의 합계를 구하여 출력하는 기능
		int sum =0;
		for(int i=1; i<=10; i++) {
			sum=sum+i;
		}
		System.out.println("총합 : "+sum);
//		return; void메소드의 경우에는 생략되어있음.(JVM이 자동으로 생성해줌.)
	}
    
	// 2. 매개변수X, 반환값O 
	// [오류메세지]
	// This method must return a result of type int
	public int method2() {
		System.out.println("매개변수가 없고 반환값은 있는 메소드입니다.");
		// 1에서부터 100까지 숫자 중 랜덤값을 발생시켜 반환시켜주는 메소드
		/*
        int random = (int)((Math.random()*100)+1);
		return random;
        */
		return (int)((Math.random()*100)+1);
	}
	
	// 3. 매개변수O, 반환값X
	public void method3(int num1, int num2) {
		System.out.println("매개변수가 있고 반환값이 없는 메소드입니다.");
		// num1과 num2를 비교해서 결과를 출력하는 메소드
		// 최소값 : xx
		// 최대값 : xx
		int min=0; // 두 수 중 작은 값을 넣을 용도의 변수
		int max=0; // 두 수 중 큰 값을 넣을 용도의 변수
			if(num1 > num2) {
				min = num2;
				max = num1;
			}else {
				min = num1;
				max = num2;
			}
		System.out.println("최대값 : "+max+"\n최소값 : "+min);
	}
    
	// 4. 매개변수O, 반환값O
	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 클래스------------"); 
//		1번. 매개변수X, 반환값X (void)
		MethodTest1 m1 = new MethodTest1();
		m1.method1(); 
		
		System.out.println("--------------------------------");
//		2번. 매개변수X, 반환값O (return)
//		m1.method2();	// sysout을 하지 않으면 결과값이 보이지 않음.
		/*
		int random = m1.method2();	
		System.out.println("랜덤값 : "+random);
        */
		System.out.println("랜덤값 : "+m1.method2());
		
		System.out.println("--------------------------------");
//		3번. 매개변수O, 반환값X (void)
		m1.method3(1,10); // 순서, 개수, 자료형이 맞아 떨어져야 함.
		
		System.out.println("--------------------------------");
//		4번. 매개변수O, 반환값O (return)
		System.out.println(m1.method4(1, 10)); // sysout을 하지 않으면 결과값이 보이지 않음.
		
		/*
		 * 반환형이 있고, 없고의 차이
		 * 1. 반환형이 있는 경우(return) - 2,4번
		 * => 돌려줄 결과값이 있으니, 메소드를 호출하는 곳에서 반환형에 맞는 변수를 선언하여 결과를 대입.
		 * 2. 반환형이 없는 경우(void) - 1,3번
		 * => 돌려줄 결과값이 없으니, 메소드 내에서 결과를 출력하는 형태로 이용.
		 * 
		 */     

static 메소드

* 메소드의 경우, 호출시 new 구문으로 객체를 생성할 필요 없음
* 위와 마찬가지로 매개변수, 반환형을 가지고 작성해봄.

package com.kh.chap06_method.controller;

public class MethodTest2 {
	
//	1. 매개변수X, 반환형X
	public static void method1() {
		System.out.println("매개변수도 없고, 반환형도 없는 static 메소드");
	}
//	2. 매개변수X, 반환형O
	public static String method2() {
		return "매개변수는 없지만, 반환값은 있는 static 메소드";
	}
//	3. 매개변수O, 반환형X    
	public static void method3(String name, int age) {
		System.out.printf("%d살의 %s님 환영합니다.\n",age,name);
	}
//	4. 매개변수O, 반환형O    
	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 "계산하기 싫은데?"; 
//		오류 : 반환형과 return의 자료형이 일치해야 함.
		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 클래스------------"); 
        // 1. 매개변수X, 반환형X (void)
		MethodTest2.method1(); // static은 import해주어야 함.
		
        // 2. 매개변수X, 반환형O (return)
		System.out.println("---------------------------------");
        /*
		String str = MethodTest2.method2();
		System.out.println(str);
        */
		System.out.println(MethodTest2.method2());
		
        // 3. 매개변수O, 반환형X (void)
		System.out.println("---------------------------------");
		MethodTest2.method3("홍길동", 20);
		
        // 4. 매개변수O, 반환형O (return)
		System.out.println("---------------------------------");
		System.out.println(MethodTest2.method4(10, 6, '*'));
		
		/*
		 * static 메소드의 경우에는 new문으로 객체를 생성할 필요가 없음.
		 * static이 붙은 클래스 변수와 마찬가지로 
         * 메소드 또한 프로그램 실행 시, 메모리의 static영역(정적)에 할당됨.
		 */
	}
} 

메소드 오버로딩

 * 한 클래스 내에 같은 메소드명으로, 여러 메소드를 정의할 수 있는 방법.
 * 즉, 메소드의 이름이 중복되도 허용함.
 * 
 * 오버로딩 규칙
 * 1. 메소드명은 동일해야함.
 * 2. 매개변수의 자료형의 개수, 순서를 다르게 작성해야 함.
 * 3. 메소드의 접근제한자, 예약어, 반환형, 매개변수명은 오버로딩에 영향을 주지 않음.
/*
 *오버로딩이 잘 된 예시
 *System.out.println : 매개변수의 개수가 같더라도 종류가 다른 예시
 *System.out.printf : 매개변수의 개수가 대놓고 다른 예시
 *이전에 했던 "생성자" 예시 
 */

public class OverloadingTest {

public void test() {
		// System.println()
		// 괄호 안의 내용물은 매개변수임.
		System.out.println(0);	// int
		System.out.println('1');	// char
		System.out.println(1.1);	// double
		System.out.println("하이"); 	// String
 		System.out.println(true);	// boolean
 		// => 메소드의 매개변수의 개수는 같으나, 매개변수의 종류가 다른 오버로딩
	}
    
	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 c, int d){ }*/
    // 매개변수의 종류, 개수, 순서가 같음 
    // => 오버로딩이 적용 안됨.
	// => 매개변수명은 영향을 주지 않음.
	// => 매개변수의 자료형의 개수와 순서가 다르게 작성되어야 함.
    
	public void test(int a, int b, String s) {}
    // 매개변수의 종류와 개수, 순서가 달라, 오버로딩이 적용됨.
    
	/*public int test(int a, int b, String s) {}*/
   	// 매개변수의 종류, 개수, 순서가 같음 
    // => 오버로딩이 적용 안됨.
	// => 반환형이 영향을 주지 않음.
    // => 오로지 매개변수의 종류, 개수, 순서만 오버로딩에 영향을 줌.
    
    /*private void test(int a, int b, String s) {}*/
    // 매개변수의 종류, 개수, 순서가 같음 
    // => 오버로딩이 적용 안됨.
	// =>접근제한자가 영향을 주지 않음. 		
}

0개의 댓글