* 비정형인자(=가변인자 , Variable Arguments)
- 메서드 파라미터 갯수가 정해져 있지 않을 때 다양한 갯수의 파라미터를 모두 전달받을 수 있는 인자.
- 메서드 정의 시 매개변수 데이터타입과 변수명 사이에 ... 기호를 붙여서 표기
- 전달되는 모든데이터는 해당 변수명으로 된 "배열"로 관리디며 0개 이상의 파라미터를 전달할 수 있음
- 메서드 정의 시 가변 인자 타입으로 매개변수를 선언하면 갯수 제한 업이 0개부터 무한대의 파라미터를 한꺼번에 전달 받을 수 있다.
- 가변인자 사용시 주의사항!! 가변인자는 꼭 마지막 파라미터로 사용되어야 한다.
가변인자는 단 한번만 사용가능. 둘중에 하나만 선택해서 사용하여야 한다.( = 마지막 파라미터로 사용되어야 한다는 사유에 포함됨.)
class VariableArguments {
public void print(int... nums) {
System.out.println("print(int...nums) 호출됨.");
for(int i = 0; i < nums.length; i++) {
Systehttp://m.out.print(nums[i] + " ");
}
}
// public void print(int...nums, String... str) { // 가변인자는 여러개 사용할 수 없다.
// public void print(int...nums, String str) { // 가변인자는 이 메서드의 마지막 파라미터로 사용되어야 한다.
public void print(String str, int...nums) { // (O)
// 복수개의 매개변수 선언 시 가변 인자가 마지막에 사용되면 오류가 발생하지 않음.
------------
// ... 메인메서드 안에서 호출하기
VariableArguments va = new VariableArguments();
va.print(1,2,3,4,5,6);
va.print(1,2,3,4,5,6,1,2,3,4,5,6,1,2,3,4,5,6,1,2,3,4,5,6);
//va.print(1,2,"abc");// 타입에러.
va.print(arr); // 배열 전달 가능.
va.print(); // 심지어 파라미터 없이도 메서드 호출 가능
Q. 오늘의 문제
package method;
/*
계산기 (Calculator) 클래스 정의
덧셈, 뺄셈, 곱셈, 나눗셈 기능을 모두 calc() 메서드로 처리
=> 첫번째 파라미터는 연산자(기호, char타입 opr)를 전달하고
두번째 파라미터부터 피연산자(숫자, int 타입 numX)을 전달하고 2개이상 전달하여
연산자에 따라 각각의 연산을 누적하여 결과 출력
*/
class Calculator2 {
// 부호없이 결과(total)만 나오는 메서드
public void calc (char opr, int... nums) {
int total = nums[0];
for(int i = 1; i < nums.length; i++) {
switch (opr) {
case '+': total += nums[i]; break;
case '-': total -= nums[i]; break;
case '*': total *= nums[i]; break;
case '/': total /= nums[i]; break;
}
}
makeStr(opr, nums);
System.out.println(total);
} // calc() 메서드 끝
// 부호 붙이는 메서드
public void makeStr(char opr, int... nums) {
String str = nums[0] + "";
for(int i = 1; i < nums.length; i++) {
str += " " + opr + " " + nums[i];
}
System.out.print(str + " = " );
}
/*
int total = nums[0];
System.out.print(total);
// System.out.print(nums[0]);
// String buho = nums[0] + "";
for(int i = 1; i < nums.length; i++) {
System.out.print(" " + opr + " " + nums[i]);
switch (opr) {
case '+':
// buho += " + " + nums[i];
total += nums[i];
break;
case '-':
// buho += " - " + nums[i] ;
total -= nums[i];
break;
case '*':
// buho += " * " + nums[i] ;
total *= nums[i];
break;
case '/':
// buho += " / " + nums[i] ;
total /= nums[i];
break;
default:
break;
}
}
System.out.println(" = "+total);
*/
/*
if(opr == '+') {
for(int i = 1; i < nums.length; i++) {
buho += " + " + nums[i];
total += nums[i];
}
System.out.println(buho+" = "+total);
} else if (opr == '-') {
for(int i = 1; i < nums.length; i++) {
buho += " - " + nums[i] ;
total -= nums[i];
}
System.out.println(buho+" = "+total);
} else if (opr == '*') {
for(int i = 1; i < nums.length; i++) {
buho += " * " + nums[i] ;
total *= nums[i];
}
System.out.println(buho+" = "+total);
} else if (opr == '/') {
for(int i = 1; i < nums.length; i++) {
buho += " / " + nums[i] ;
total /= nums[i];
System.out.println(buho+" = "+total);
}
}
-------------
class Calculator2 {
public void calc (char opr, int... nums) {
int total = 0;
if(opr == '+') {
String buho = " + ";
for(int i = 0; i < nums.length; i++) {
total += nums[i];
if(i == nums.length-1) {
buho = " = " + total;
}
System.out.print(nums[i] + buho);
}
System.out.println();
} else if (opr == '-') {
String buho = " - ";
for(int i = 0; i < nums.length; i++) {
if(i == 0) {
total = nums[0];
} else {
total -= nums[i];
}
if(i == nums.length-1) {
buho = " = " + total;
}
System.out.print(nums[i] + buho);
}
System.out.println();
} else if (opr == '*') {
total = 1;
String buho = " * ";
for(int i = 0; i < nums.length; i++) {
total *= nums[i];
if(i == nums.length-1) {
buho = " = " + total;
}
System.out.print(nums[i] + buho);
}
System.out.println();
} else if (opr == '/') {
}
}
}
*/
}
public class Test2 {
public static void main(String[] args) {
Calculator2 cal = new Calculator2();
// cal.makeStr('+', 10 , 20, 30);
cal.calc('+', 10, 20, 30); // 10 + 20 + 30 = 60
/* 메서드 나누기 전
Calculator2 cal = new Calculator2();
cal.calc('+', 10, 20); // 10 + 20 = 30
cal.calc('+', 10, 20, 30, 40); // 10 + 20 + 30 + 40 = 100
cal.calc('-', 100, 10);
cal.calc('-', 100, 10, 20);
cal.calc('-', 100, 10, 20, 30);
cal.calc('*', 1, 2);
cal.calc('*', 1, 2, 3);
*/
}
}
*기본형 (Primitive Type) 변수와 참조형 (Reference Type) 변수의 차이
- 기본형 변수는 실제값(리터럴)을 저장하며,
참조형 변수는 실제값이 저장된 인스턴스의 주소값(참조값 = 레퍼런스)을 저장
- 기본형 변수와 참조형변수의 값을 복사(전달)할 때 차이점
1. 기본형 변수의 값을 복사할 경우
- 변수에 저장된 실제 값을 복사(전달) = Pass by value
- 실제 값을 복사하게 되면 원본 값과 동일한 값이 별도로 생성되어 전달되므로 복사된 값을 변경하더라도 원본 값과 상관없기 때문에 원본 값은 변경되지 않는다.
2. 참조형 변수의 값을 복사할 경우
- 변수에 저장된 인스턴스 주소값을 복사(전달) = Pass by reference
- 주소 값을 복사하게 되면 원본 값에 저장된 주소와 동일한 주소가 전달되므로 실제 인스턴스 하나를 함꼐 공유하게 된다. 따라서 한쪽에서 인스턴스에 접근하여 저장된 값을 변경할 경우 동일한 주소값을 참조하는 쪽에도 영향을 받게 된다.
=> 즉, 한쪽에서 값을 변경하면 다른쪽의 값도 함꼐 변경된 효과를 갖는다.
public class Ex1 {
public static void main(String[] args) {
int x = 10;
int y = x;
System.out.println(x+y);
y = 99;
System.out.println(x+y);
//=> 기본형 변수 y의 값을 변경하더라도 원본데이터 기본형 변수 x의 값은 변경되지 않음.
Num n = new Num();
n.x = 10;
n.y = n.x;
n.y = 99;
System.out.println(n.x + n.y); // 클래스라도 안에 기본데이터 타입이니까 결과는 위와 같다.
// => Num 클래스의 인스턴스 내에 있는 기본형 변수 Y의 값을 변경하더라도 원본 데이터 기본형 변수 x의 값은 변경되지 않음.
System.out.println("-------------------------------------------");
Num n2 = new Num();
n2.x = 10;
n2.y = 10;
Num n3 = n2; // Num 타입 참조형 변수 n3에 참조형 변수 n2 의 값 복사(=주소값 복사)
// => 참조형 변수 n2가 가리키는 인스턴스 주소값을 n3에 복사(전달) 했으므로 n2와 n3가 가리키는 (참조하는)인스턴스가 동일함.
System.out.println(n2.x + n2.y);
System.out.println(n3.x + n3.y);
// 참조형변수 n3의 인스턴스 내의 변수 y값을 99로 변경
n3.y = 99; // 복사된 참조변수 값(인스턴스주소)에 접근하여 인스턴스 변수값 변경 //new 는 한번만 해서 사람이 한명이다. 그래서 n2.y && n3.y = 99
System.out.println(n2.x + n2.y);
System.out.println(n3.x + n3.y);
// => n2, n3 모두 하나의 인스턴스를 참조하고 있으므로 한쪽에서 인스턴스 내의 변수 값으 변경하면 다른쪽의 인스턴스도 동일하므로 똑같이 변경된 사항이 적용됨.
System.out.println("-------------------------------------------");
PassValue pv = new PassValue();
int xNum = 10;
System.out.println("메서드 호출 전 x: " + xNum);
pv.changeValue(xNum);
System.out.println("메서드 호출 후 x: " + xNum);
System.out.println("-------------------------------------------");
Num num = new Num();
num.x = 10;
System.out.println("메서드 호출 전 x: " + num.x);
pv.changeReferenceValu(num);
System.out.println("메서드 호출 후 x: " + num.x);
}
}
class PassValue {
public void changeReferenceValu(Num num) {
System.out.println("메서드 변경 전 x: " + num.x);
num.x=999;
System.out.println("메서드 변경 후 x: " + num.x);
}
public void changeValue (int x) {
System.out.println("메서드 변경 전 x: " + x);
x=999;
System.out.println("메서드 변경 후 x: " + x);
}
}
class Num {
int x;
int y;
}
* 패키지(Package)
- 윈도우에서의 폴더(Folder), 리눅스에서의 디렉토리(Directory)에 해당하는 개념
- 자바에서 클래스 파일들을 모아놓는 공간(물리적으로 폴더와 동일)
=> 서로다른 패키지에는 같은 이름의 클래스가 각각 존재할 수 있다. (=중복가능)
(단, 하나의 패키지에는 같은 이름의 클래스가 중복될 수 없다.)
- 자바에서 패키지를 생성하면, 실제 물리적인 폴더가 생성됨.
(만약, 패키지 생성 생략시, 물리적 폴더가 없는 default package가 생성됨.)
- 특정 클래스 파일은 하나의 패키지에만 소속되어야 함.
- 원칙적으로 클래스에 접근하는 방법은 패키지명과 클래스 명을 동시에 지정하여 접근
=> '패키지명.클래스명' 형태로 지정
=> 만약, 패키지에 계층구조로 이루어져 있을 경우에는 '상위패키지명.하위패키지명.클래스명' 형태로 지정
=> 단, java.lang 패키지는 기본적으로 포함되는 유일한 패키지 이므로 java.lang 패키지 내의 클래스는 클래스명만으로 접근가능
- 실제 폴더 구조처럼 상위, 하위로 구분하여 패키지를 작성하며 이때, 패키지의 이름이 중복될 수 있으므로 도메인네임을 사용하여 패키지명을 지정
google.co.kr => kr.co.google.
naver.co.kr => kr.co.naver
=> 단, 도메인 네임을 역순으로 지정하여 포괄적인 이름이 상위패키지명이 되도록 함.
* package문 (키워드)
- 특정클래스 파일의 처번째 라인에 해당 클래스가 소속된 패키지를 명시하는데 사용
=> 주석을 제외한 소스코드에서 가장 먼저 실행되어야하는 코드(맨윗줄에 위치) - import문도 패키지문 밑에 있어야 함.
- 실제 클래스 파일이 위치한 패키지와 지정된 위치가 다를 경우 오류 발생.
- 클래스 파일 내에서 단 한번만 사용가능
- default package에 위치한 클래스는 실제 패키지가 없으므로 package문 생략함.
'자바스프링웹공부(2024) > 자바' 카테고리의 다른 글
2024.09.09.조건문 반복문 연습 (0) | 2024.09.09 |
---|---|
2024.09.05.import, static (1) | 2024.09.08 |
2024.08.27. 생성자, this (0) | 2024.08.27 |
2024.08.26.클래스, 인스턴스 (0) | 2024.08.26 |
2024.08.12. 메서드 (0) | 2024.08.17 |