티스토리 뷰
1. 생성자
- 생성자 오버로딩 : 매개변수의 타입, 개수, 순서가 다른 생성자를 여러 개 선언
- 오버로딩에서 순서를 파악할 때 변수의 이름으로 판단하는 것이 아니라, 타입으로 판단하는 것이다.
- 다른 생성자 호출 [ this ( ) ] // Car2.java : 중복코드를 줄이기 위해서 다른 생성자를 호출한다.
- Car2(String model){ -this() 문법을 통해, 다른 생성자를 호출하는 것도 가능하다!!
this(model,null); // 생성자2 호출
// 모든 생성자를 생성자3 호출하는 것이 아니라 바로 밑의 생성자를 호출하는 것이 좋다.
} // 생성자1 - 생성자2 호출
Car2(String model, String color){
this(model, color,0);
} //생성자2 - 생성자3 호출
Car2(String model, String color, int maxSpeed){
this.model = model;
this.color = color;
this.maxSpeed = maxSpeed;
- }// 생성자3
2. 메소드
- 객체의 동장( 기능 )
- 호출해서 실행할 수 있는 중괄호 { } 블록을 필수적으로 사용한다.
- 메소드를 호출하면 중괄호 { } 블록 내에 있는 모든 코드들이 일괄적으로 실행된다.
- 메소드 선언 : 리턴타입 메소드이름 ( [ 매개변수 선언], . . .) { }
- 이러한 형식을 메소드 시그니쳐(Method Signature)라고 부른다.
- 리턴타입 : 메소드가 리턴하는 결과 타입 표시 ( ex. void )
- Void는 메소드가 리턴하는 값이 없다고 하는 타입이다.
- 메소드 이름 : main처럼 메소드의 이름을 말하는 것이다.
- 메소드의 이름은 자바 식별자 규칙에 맞게 작성하게 된다.
- 메소드 리턴 타입 : 메소드가 실행될 후의 리턴하는 값의 타입
- 메소드는 리턴 값이 있을 수도 있고, 없을 수도 있다.
- Return 문 : 메소드 실행을 중지하도, 리턴값을 지정하는 역할을 한다.
- 리턴값의 경우 리턴타입이 int라고 해서 무조건 int가 와야 하는 것이 아니라 형변환이 가능하다면 다른 것이 와도 괜찮다.
- 메소드 호출할 때, 외부에서는 new연산자를 사용한 후에 Car.run();이래야 하지만, 내부에서 사용할 때에는 run();으로 사용이 가능하다.
- 메소드 오버로딩 : 클래스 내 같은 이름의 메소드를 여러 개 선언하는 것이다.
- 오버로딩의 조건 : 매개변수의 타입, 개수, 순서가 달라야 한다.
-
- System.out.println이 대표적인 예로, ()안에 들어가는 것에 따라서 같은 sysout이더라도 실행 메소드가 달라진다.
3. 요약 및 인스턴스와 정적 멤버 // Sample80 참고!
- 1. 클래스의 구성멤버 : (1) 필드 (2) 생성자 (3) 메소드
- 2. 필드와 메소드의 유형이 다시 2가지로 각각 구분된다.
- (1) 필드의 2가지 유형 :
- 가. 인스턴스( = 객체 ) 필드 -> 인스턴스 안에서만 생성되는 필드!
- Ex. public class Person {
u String name;
u Int age;
- } // end class
- 클래스에서 찍어낸 객체마다 가지고 있는 필드와 메소드를 의미한다.
- 이때 필드에는 객체의 데이터가 들어가 있고 메소드에는 주소가 들어가 있다.
- 인스턴스 멤버인 인스턴스 필드와 메소드는 객체에 소속된 멤버이기에 객체가 없이는 사용이 불가능하다.
- 사람마다 다 다른 나이와 모습을 가지고 있는 것과 비슷.
- 나. 정적(static) 필드 -> 인스턴스와 상관이 없는 필드
- -> 정적 필드는 클래스(clazz 객체)에 소속된 필드이다.
- Ex. public class Person {
u static String name;
u static int age;
- } // end class
- 객체(인스턴스)와 상관이 없는 필드로 static을 붙어야 한다.
- 이 클래스로부터 생성하는 모든 인스턴스(객체)에 공용(공유)으로 사용되는 필드와 메소드
- Public class Calculator { // 원의 넓이를 구하는 계산기
u Static double PI = 3.14159 ; // 파이
u Void areaTriangle() {
u Return Calculator.PI * radius * radius;
u } //
- } // end class
- 원의 넓이를 구하기 위해서는 원주율 PI값이 공통적으로 필요하기 때문에 앞에 static을 붙여 Static double PI 정적 필드로 만들었다.
- 활용할 때에는 “Calculator.PI”처럼 클래스명.을 붙여서 사용을 하게 된다.
- 매개변수만으로도, 또는 매개변수가 없더라도 가능한 것도 static으로 구분한다.
- (2) 메소드의 2가지 유형 : 가. 인스턴스(= 객체) 메소드 나. 정적(static) 메소드
- 메소드 영역에 있는 객체의 타입은 “java.lang.class”파일이다. -> ‘clazz’ 객체
- 메소드 영역에는 클래스 파일이 생성되게 되는데, 정적 필드/메소드
- 객체의 멤버는 위에 이미 언급했 듯이, 인스턴스 멤버(필드, 메소드)와 정적멤버(필드, 메소드)로 구분되는데, 특히 메소드에서 아래와 같은 규칙이 있다. (****)
- 가. 인스턴스 메소드 블록 내에서는 아래 멤버를 사용이 가능하다.
- -> [ 인스턴스 멤버를 사용 가능 ]
- A. 인스턴스 필드 사용가능
- B. 인스턴스 메소드 사용가능
- C. 정적 필드 사용가능
- D. 정적 메소드 사용 가능
- 나. 정적 메소드 블록 내에서는, 아래 멤버만이 사용 가능하다.
- A. 정적 필드
- B. 정적 메소드
- 인스턴스 멤버(필드, 메소드)는 사용이 불가능하다!!!!
4. 인스턴스 멤버와 this
- This : 객체(인스턴스) 자신의 주소를 가지고 있는 키워드이다.
- 객체 내부에서 인스턴스 멤버임을 명확히 하기 위해 “this.”를 사용하게 된다.
01. 메소드 생성 및 호출
public class Calculator { // 메소드 생성
// void - 값을 되돌려주지 않아도 괜찮음
void powerOn() {
System.out.println("전원을 킵니다.");
} // powerOn
int plus(int x, int y) { // plus를 기동시키기 위해서는 2개의 값이 필요하다고 하는 것이다.
int result = x + y;
return result; // return : 값을 되돌려준다.
} // plus
double divide ( int x, int y) {
double result = (double) x / (double) y; // 분자와 분모를 모두 실수타입으로 강제형변환 시켰다.
// 분자나 분모 둘 중 하나만 (double)이라고 해도 나머지는 자동으로 double로 타입이 맞춰진다.
return result;
} // divide
void powerOff() {
System.out.println("전원을 끕니다.");
} // powerOff
} // end class
import java.util.Arrays;
public class CalculatorExample {
public static void main (String[] args) { // 메소드 호출(****) - 사용관계
// A란 클래스 안에서 B내의 클래스를 호출해서 사용하는 것이 사용관계라고 한다.
System.out.println("args : " + Arrays.toString(args)); // args : []가 출력된다.
Calculator mycalc = new Calculator(); // 전자계산기 호출
mycalc.powerOn(); // 메소드 호출
int result1 = mycalc.plus(5, 6); // 메소드 호출
System.out.println("result1 : " + result1);
byte x = 10;
byte y = 4;
double result2 = mycalc.divide(x, y); // 메소드 호출
System.out.println("result2 : " + result2);
mycalc.powerOff();
} // main
} // end class
02. 메소드 - . . . 가변인자
import java.util.Arrays;
public class Computuer {
int sum1 (int[] values) { // 나를 호출하려면 배열을 줘!!
int sum = 0;
// for(int i = 0; i<values.length; i++) {
//
// sum += values[i]; // 배열의 원소를 모두 합친다.
//
// } //for
for( int number : values ) {
sum = sum + number;
} // enhanced for
return sum; // (****)
// return의 기능
// 1. 무조건 자신을 만나는 순간 해당 메소드의 실행을 종료시킨다.
// 2. 값을 되돌려줘야 할때, return 뒤에 변수, 순수한 리터럴 또는 연산식, 또다른 메소드를 호출시킬 수 있다.
// 단 하나의 값을 생성해야 한다.
} // sum1
int sum2(int ... values) { // ...는 가변인자( = 배열)를 만들때 사용한다. (**)
// ...는 타입 오른쪽에 작성하게 된다.
// ( ) 내에서는 ...를 배열로 인식하게 된다. (**)
// 가변인자와 다른 매개변수가 같이 있어야 될때에는 무조건 가장 뒤에 있어야 하는데,
// 이는 가변인자가 무조건 다 받아들이기에 그 뒤에 다른 매개변수가 오면 차례가 오지 않기 때문이다.
System.out.println("values : " + Arrays.toString(values));
int sum = 0;
// for(int i=0; i<values.length; i++) {
//
// sum += values[i];
//
// } // for
for (int number : values) {
sum = sum + number;
} // enhanced for
return sum;
} // sum2
} // end class
public class ComputuerEample {
public static void main(String ... args) {
System.out.println("args : " + args);
Computuer myCom = new Computuer();
int [] values1 = {1,2,3}; // 6 // values 변수에 배열의 주소를 저장해서 이를 통해 선언해준 것이다.
int result1 = myCom.sum1(values1); // 메소드 호출 : 매개변수는 배열
System.out.println("result1 : " + result1);
int result2 = myCom.sum1(new int[] { 1,2,3,4 }); // 새로운 배열을 생성(***) - 바로 배열을 생성하려고 하다보니 new를 사용한 것이다.
System.out.println("result2 : " + result2); // 10
myCom.sum2(); // 호출 메소드가 리턴해주는 값을 사용할 곳이 없어서, Lvalue 값을 구성하지 않는다.
int result3 = myCom.sum2(1,2,3); // 메소드 호출 : 매개변수는 ... 가변인자
System.out.println("result3 : " + result3);
int result4 = myCom.sum2(1,2,3,4,5);
System.out.println("result4 : " + result4);
} // main
} // end class
03. 메소드의 응용
public class Car3 {
int gas; // 필드
// 생성자
// 메소드
void setGas(int gas) { // 연료주입
this.gas = gas;
} // gas
boolean isLeftGas() {
if(gas ==0) {
System.out.println("gas가 없습니다.");
return false;
} // if
System.out.println("gas가 있습니다.");
return true;
} // isLeftGas
void run() { // 달려라
while(true) { // 무한루프를 만들면, 반드시 먼저 탈출조건을 만들어라!!
if(gas>0) {
System.out.println("달립니다. (gas 잔량 : " + gas + " )");
gas -=1;
} else {
System.out.println("멈춥니다. (gas 잔량 : " + gas + ")");
return;
} // if else
} // while
} // run
} // end class
public class Car3Example { // 실행 클래스
public static void main(String[] args) { // 메소드의 응용
Car3 myCar = new Car3(); // 1.인스턴스(객체) 생성 (****)
myCar.setGas(5); // 2. Car3의 setGas() 메소드 호출
boolean gasState = myCar.isLeftGas(); // 3. Car3dml isLeftGas() 메소드 호출
if(gasState) {
System.out.println("출발합니다.");
myCar.run(); // 4. Car3의 run() 메소드 호출 // 0이 될때까지 달려라
} // if
if(myCar.isLeftGas()) { // 5. Car3의 isLeftGas() 메소드 호출
System.out.println("gas를 주입할 필요가 없습니다.");
} else {
System.out.println("gas를 주입하세요.");
} // else if
// 출력 결과
// gas가 있습니다.
// 출발합니다.
// 달립니다. (gas 잔량 : 5 )
// 달립니다. (gas 잔량 : 4 )
// 달립니다. (gas 잔량 : 3 )
// 달립니다. (gas 잔량 : 2 )
// 달립니다. (gas 잔량 : 1 )
// 멈춥니다. (gas 잔량 : 0)
// gas가 없습니다.
// gas를 주입하세요
} // main
} // end class
04. 메소드 오버로딩
public class TTT01 {
String name = "cho";
static int age = 23;
void method1() {
System.out.println("method1() invoked.");
System.out.println("name : " + this.name);
// 이렇게 변수의 이름이 같을 수 있는데, 이때 this를 활용하여 this.name이 필드 값으로 있는 name(cho)임을 알 수 있다.
System.out.println("age : " + TTT01.age);
// 같은 클래스여도 static이 붙어있으면 앞에 클래스.을 붙여준다.
String name = "am";
method2(); // 다른 메소드인 메소드2 호출
// this.method2(); // 이 방법이 정석적인 사용방법이다.
} // method1
void method2() {
System.out.println("method2() invoked.");
this.method3();
// method3(); // 다른 메소드인 메소드 3 호출
} // method2
void method3() {
System.out.println("method3() invoked.");
} // method3
// 메소드 오버로딩
void method () {;;}
void method (String name) {;;}
void method (String name, int age) {;;}
// int method (String name, int age) {;;} // 오류가 뜨게 되는데,
// 그 이유는 int로 시작하였기에 { }안에 int타입을 반환해주는 리턴값이 필요하기 때문이다.
// 즉 리턴값은 메소드 오버로딩의 고려대상이 아니다.
void method (int age, String name) {;;}
// void method (int weight, String name) {;;} // <----- 이 경우에 충돌이 생기게 된다.
// 그 이유는 오버로딩의 경우 순서를 따질 때, 변수의 이름은 따지지 않고 타입만으로 판단하기 때문이다.
// 오버로딩은 타입, 개수, 순서 중 1개라도 달라야 한다.
} // end class
public class TTT01Example {
public static void main (String[] args) {
TTT01 ttt = new TTT01(); // 객체 생성
ttt.method1(); // 메소드 1 호출
// 실행결과
// method1() invoked.
// method2() invoked.
// method3() invoked.
// 메소드 1만 호출하였는데, 출력해보자 1,2,3이 모두 실행되었다는 출력문이 나왓다는 것을 볼 수 있다.
// 이는 메소드 1이 메소드 2를, 메소드2가 메소드3을 호출시켰기 때문이다.
} // main
} // end class
05. 메소드 오버로딩의 응용
public class Calculator01 { // 메소드 오버로딩 응용
String color; // 인스턴스
double price; // 인스턴스
// 여기에 static을 붙이게 된다면 모든 계산기의 가격과 색은 모두 같다는 것이 되어버린다.
// 1. 정사각형의 넓이
static double areaRectangle(double width) { // 외부의 도움이 필요없으면 static붙이는 것이 좋다.
Math.random(); // MAth.도 외부의 도움이 필요없기에 static이 붙여진다.
return width * width;
}// areRectanglle
// 2. 직사각형의 넓이
static double areaRectangle(double width, double height) {
return width * height;
} // areaRectangle
// 3. 덧셈 구하기 // 덧셈을 하는데 다른 도움이 필요 없고 매개변수만이 필요하기에 static을 붙인다.(****)
static int add ( int number1, int number2) {
return number1 + number2;
} // add
} // end class
public class Calculator01Example {
public static void main(String... args) { // [ ] 대신 ...도 가능하다.
Calculator01 myCalcu = new Calculator01(); // 1. 인스턴스 생성
// 정사각형의 넓이 구하기
double result1 = myCalcu.areaRectangle(10); // 2. 메소드 호출
// 직사각형의 넓이 구하기
double result2 = myCalcu.areaRectangle(10, 20); // 3. 메소드 호출
// 결과 출력
System.out.println("result1 : " + result1); // result1 : 100.0가 출력
System.out.println("result2 : " + result2); // result2 : 200.0가 출력
} // main
} // end class
06. 인스턴스 멤버와 정적 멤버
public class Sample80 {
String name; // 인스턴스 멤버
int age; // 인스턴스 멤버
static double weight; // 정적 필드
static double height; // 정적 필드
void instanceMethod () {
System.out.println("instanceMethod() invoked");
// 1. 인스턴스 필드를 사용해 보자!
System.out.println("1.name : " + name); // 가능
System.out.println("2. age : " + age); // 가능
// 인스턴스 메소드 블록 내에서는 인스턴스 필드의 사용은 아무런 문제가 없다.
instanceMethod2(); // 가능
// 2. 인스턴스 메소드 블록 내에서 인스턴스 메소드의 사용은 아무런 문제가 없다.
// 3. 정적 필드의 사용
System.out.println("3. weight : " + weight);
// 인스턴스 메소드 블록 내에서 정적 필드의 사용이 가능하다.
// 4. 정적 메소드의 사용
staticMethod();
// 인스턴스 메소드 블록 내에서 정적 메소드의 사용이 가능하다.
// 결론 정리 (******) :
// 대전제1 : 인그턴스 메소드 블록 내에서는 인트턴스 멤버 + 정적 멤버 모두 사용이 가능하다!!
// 대전제2 : 정적 메소드 블록 내에서는 정적 멤버만 사용이 가능하다!!
} // 인스턴스 메소드
void instanceMethod2() {;;};
static void staticMethod() {
System.out.println("staticMethod() invoked");
}// 정적 메소드
public static void main (String[] args) { // 정적 메소드이다!!
// System.out.println("1. weight : " + weight); //0.0 출력
// -> 정적 필드는 사용이 가능하구나!!
// staticMethod(); // staticMethod() invoked가 출력
// -> 정적 메소드 또한 사용이 가능하구나!!
// 결론 : 정적 메소드 블록 내에서, 정적멤버(필드 + 메소드) 사용은 아무런 문제가 없다!!!
// System.out.println("2. name" + name); // 인스턴스 필드를 사용하려고 하자 컴파일 오류가 뜬다.
// instanceMethod(); // 인스턴스 메소드 또한 사용이 불가능하다!
// 결론 : 정적 메소드 블록 내에서, 인스턴스멤버(필드 + 메소드)는 사용이 불가능하다!!
// =======================================================================================================
Sample80 obj = new Sample80(); // (*****) 객체 생성
// 인스턴스 멤버
System.out.println("1. name : " + obj.name); // 1. name : null로 잘 출력이 된다.
System.out.println("2. age : " + obj.age); // 2. age : 0로 출력이 잘 된다.
// 정적 멤버
System.out.println("3. weight : " + obj.weight); // 3. weight : 0.0로 출력은 제대로 되지만 붉은 줄이 그어진다.
System.out.println("4. height : " + obj.height); // 4. height : 0.0로 출력은 제대로 되지만 붉은 줄이 그어진다.
// The static field Sample80.weight should be accessed in a static way로 컴파일 오류가 뜨게 되는데
// 이를 해석하자면 정적 멤버는 정적으로 사용하라는 문구이다.
// 대전제3 : 정적멤버는 인스턴스(객체)의 소속이 아니라, clazz의 멤버이기 때문에
// 인스턴스의 참조(주소)를 가지는 참조변수를 사용하는 것은 바람직하지 않다!
// 정적 멤버의 사용방법 : "클래스명.정적멤버" 형식으로 사용해라!! (*****)
// 수정!
System.out.println("3. weight : " + Sample80.weight);
System.out.println("4. height : " + Sample80.height);
Sample80.staticMethod(); // 모두 오류 없이 잘 출력이 되는 것을 볼 수 있다.
// 정적 메소드 또한 대전제3과 마찬가지로 "클래스명.정적멤버" 형식으로 사용해라!! (*****)
//
// 인스턴스 멤버는 인스턴스 멤버 답게 인스턴스의 주소를 가지고 있는 new로 객체를 생성한 후에
// " 참조변수.인스턴스(정적)멤버 "로 사용해라!! (*****)
// Sample80.name; // 컴파일 오류가 발생하게 된다.
// Sample80.age; // 컴파일 오류가 발생하게 된다.
} // main
} // end class
07. 과제 05
import java.util.Arrays;
public class Bubble {
public static void main(String[] args) { // 협조자 : 구글님
int [] arr = new int [10]; // 배열에 10개의 원소 공간 미리 확보
int number = 0; // epoch
for(int i = 0; i<arr.length; i++ ) {
arr[i] = (int)(Math.random()*100) +1;
} //for문 - 1부터 100까지의 난수 배정
System.out.println("난수는 " + Arrays.toString(arr) + "입니다.");
for(int i = 0; i<arr.length; i++) {
for (int j = 0; j<arr.length-1; j++) { //epoch 몇 회전
if(arr[j] < arr[j+1]) { // 만약 j번째가 j+1번째 보다 값이 크다면
// int temp = arr[j+1]; // temp에 j+1번째 값을 넣는다.
// arr[j+1] = arr[j]; // j+1번째 자리에 j의 값을 넣는다.
// arr[j] = temp; // j번재에 temp에 저장되어 있던 j+1값을 넣는다.
//
// number++;
// 이용 : A => (A+B) - A = A -A + B = B
// 이용 : B => (A+B) - B = A + B - B = A
int sum = arr[j] + arr[j+1];
int 차이 = arr[j] - arr[j+1];
arr[j+1] = (sum + 차이) / 2;
arr[j] = (sum-차이) / 2;
number++;
} // if
} // inner for - j<arr.length-1하는 이유는 마지막 비교하는 수가 8번째에서 9번째이기 때문이다.
// 9번째에서 10번째가 되면 바운더리를 넘어가버리게 된다.
} //outer for // 배열에서 하나씩 값을 빼온다.
System.out.println("정렬된 난수는 " + Arrays.toString(arr) + "입니다.");
System.out.println("epoch : " + number);
} // main class
} // end class
'KH 정보교육원 [ Java ]' 카테고리의 다른 글
KH 12일차 - 접근제한자 및 어노테이션 [ + 1차 시험 후기 ] (0) | 2022.03.14 |
---|---|
KH 11일차 - 정적 초기화 블록과 상수 + 간단한 10일 후기 (0) | 2022.03.11 |
KH 09일차 - 클래스와 필드 (0) | 2022.03.09 |
KH 08일차 - 배열과 열거 (0) | 2022.03.07 |
KH 07일차 - 참조타입 (0) | 2022.03.04 |