6장 제가 조건을 좀 따져요
if문
if-else 구문은 보통 두가지 이상의 값을 비교하거나, 단순히 true, false 여부만 확인하고자 할 때 많이 사용
1. if 구문
if(boolean값) boolean 값이 true일 때 처리문장; // 소괄호 안의 값이 true일 경우 처리문장을 실행
2. if-else 구문
if(조건) 처리문장1; // 조건이 true이면 처리문장 1을
else 처리문장2; // 조건이 false면 처리문장 2를 실행
3. if-elseif 구문
int point = 85;
if(point > 90){ // 90점 초과일 경우
System.out.println("A");
} else if(point > 80){ // 80점 초과 90점 이하일 경우
System.out.println("B");
} else if(point > 70){ // 70점 초과 80점 이하일 경우
System.out.println("C");
} else{ // 70점 초과가 아닌 모든 경우
System.out.println("F");
}
4. if의 조건이 여러 개
if(age > 25 && isMarried){ // age가 25 초과이면서 isMarried가 true
...
}
if(age > 25 || isMarried){ // age가 25 초과이거나 isMarried가 true
...
}
&&: 두 조건이 모두 true여야 true
|| : 두 조건 중 하나만 true여도 true
*&&일 때 처음 조건이 false이면 다음 조건들은 점검하지 않고 false
*||일 때 처음 조건이 true이면 다음 조건들을 점검하지 않고 true
5. ? : 연산자
String result = point>90 ? "A" : point>80 ? "B" : point>70 ? "C" : "F";
System.out.println(result);
조건이 true일 때 ? 뒤에 작업을, false일 때 : 뒤에 작업을 수행
switch문
하나의 값이 여러 범위에 걸쳐서 비교되어야 할 때는 하나의 값으로 분기하여 비교하는 switch구문을 사용하는 것이 좋다
switch(비교대상변수){
case 점검값1:
처리문장1;
...
break;
case 점검값2:
처리문장2;
...
break;
...
default: // 앞에 있는 조건에 맞지 않는 경우
기본처리문장;
...
break;
}
*비교대상변수는 long을 제외한 정수형, Enum, String, 참조 자료형(Character, Byte, Short, Integer만)만 사용 가능
*switch문장에서는 조건을 통과하면 그 다음에 break가 올때까지 어떤 case가 오든지 상관 안하고 실행하기 때문에 case에 대한 처리가 끝나면 break;를 붙여주어야 한다
while문
while(boolean조건){
처리문장;
...
}
조건 값이 true일 경우에만 중괄호 안에 있는 내용들이 수행되고
중괄호가 끝나면 다시 위로 올라가 boolean 조건을 확인한 후 true이면 안의 내용을 수행
*while문에서 break 사용
int loop = 0;
while(loop < 12){
loop++;
System.out.println(loop);
if(loop==6) break; // loop가 6이면 현재 수행중인 중괄호에서 빠져 나간다
}
*while문에서 continue 사용
int loop = 0;
while(loop < 12){
loop++;
if(loop==6) continue; // loop가 6이면 그 뒤에 있는 문장은 건너 뛰고 다시 조건문으로
System.out.println(loop);
}
단, 무한 루프를 조심하기
do-while문
do{
처리문장;
...
} while(boolean 조건);
*적어도 한 번은 반복문장이 실행되는 while문
for문
for(초기화; 종료조건; 조건값증가){
반복문장
}
- 초기화: 변수를 초기화
- 종료조건: boolean 조건, true이면 for 루프 내의 반복 문장이 수행되고 그렇지 않으면 for 문 종료
- 반복문장이 종료되면 조건 값 증가가 수행
- 종료조건이 맞는 지 다시 확인 후 true일 경우 반복문장을 다시 수행
- 종료조건이 false일 경우 for 루프는 끝
label
두 개 이상의 for나 while 루프가 있을 때 사용
for(int level=2; level<10; level++){
for(int unit=1; unit<10; unit++){
if(unit==4) break;
System.out.println(level + " * " + unit + " = " + level*unit + " ");
}
System.out.println();
}
startLabel:
for(int level=2; level<10; level++){
for(int unit=1; unit<10; unit++){
if(unit==4) continue startLabel;
System.out.println(level + " * " + unit + " = " + level*unit + " ");
}
System.out.println();
}
- unit이 4일 때 break; 이면 안 쪽 for문만 벗어남
- unit이 4일 때 label을 사용하면 안 쪽 for문을 벗어나고 바깥 쪽 for문의 시작점으로 이동
7장 여러 데이터를 하나에 넣을 수는 없을까요?
배열
한 가지 타입에 대해서 하나의 변수에 여러 개의 값을 넣을 수 있는 자료구조 중 하나
*자료구조: 데이터를 저장하기 위한 구조
ex) List, Queue, Map, LinkedList 등
배열 선언
int [] lottoNumbers = new int[7]; // 7이라는 배열 크기를 지정
int lootoNumbers[] = new int[7];
int [] lottoNumbers = {5, 12, 23, 25, 38, 41, 2};
/*
1. 중괄호를 사용하여 초기화를 할 때는 반드시 한번에 변수 선언 및 초기화를 해야 한다
2. 보통은 배열에 들어가는 값이 계속 바뀔 수 있으므로 절대 변하지 않는 값을 지정할때 사용한다
*/
- int: 기본 자료형
- lottoNumbers는 new 예약어를 사용했기 때문에 int를 배열로 만든 참조 자료형
- 배열도 참조 자료형
- 배열의 위치는 0부터 시작 → 0~6까지의 7개 공간
lottoNumbers[7] = 9;
// Exception 발생
Exception in thread "main" java.lang.ArrayIndexOUtOfBoundsException: 7
0~6까지의 index를 가지기 때문에 존재하지 않는 7번째 자리에 값을 할당하려고 하면 예외가 발생한다
배열의 기본 값
기본 자료형 배열의 기본값은 각 자료형의 기본값과 동일
byte, short, int, long float, double char boolean
byte, short, int, long | float, double | char | boolean | |
기본값 | 0 | 0.0 | \u0000 | false |
참조 자료형의 기본 값은 new로 초기화하지 않으면 null
→ 참조 자료형 배열의 각각의 값은 반드시 각각의 값을 초기화해야 null이 되지 않음
String [] strings = new String[2];
System.out.println("strings=" + new String[0]);
// 결과
strings=[Ljava.lang.String;@1540e19d]
- [L : “[”는 해당 객체가 배열이라는 의미, “L”은 해당 배열은 참조자료형이라는 의미
- java.lang.String; : 해당 배열이 어떤 타입의 배열인지 (String 타입)
- @1540e19d: 해당 배열의 고유 번호
*기본 자료형의 객체를 출력하면 해당 타입을 대표하는 문자가 출력됨
byteArray = [B@14ae5a5]
intArray = [I@6d6f6e28]
...
boolean | byte | char | double | float | int | long | short |
Z | b | C | D | F | I | J | S |
2차원 배열
배열의 배열
2차원 배열 선언
int [][]twoDim;
twoDim = new int[2][3];
// twoDim[0] = int 배열
// twoDim[0][0] = int 값
twoDim0 | twoDim0 | twoDim0 |
twoDim1 | twoDim1 | twoDim1 |
// 선언 가능
twoDim = new int[2][3];
twoDim = new int[2][];
// 선언 불가능
twoDim = new int[][];
twoDim = new int[][2];
배열의 길이
int[] oneDim = new int[3];
int[][] twoDim = new int[4][2];
System.out.println(oneDim.length);
System.out.println(twoDim.length);
System.out.println(twoDim[0].length);
// 결과
3
4
2
- .length: 1차원의 경우 int 타입으로 된 배열 크기를 리턴
- 2차원의 경우 1차원의 크기를 리턴
- 2차원 배열의 크기를 알고 싶다면 각 1차원 배열에 .length를 붙여야 함
*.length와 같이 점을 찍어서 기능을 호출하거나 계산을 할 때는 참조 자료형만 가능
for 루프
JDK 5부터는 Collection이라는 자료 구조를 처리할 때 for 루프를 보다 쉽게 사용 가능
for(타입이름 임시변수명 : 반복대상객체){
...
}
예제
int [][]twoDim = {{1,2,3}, {4,5,6}};
for(int[] dimArray : twoDim){ // twoDim의 1차원 값은 배열이므로 int[] dimArray
for(int data : dimArray){
System.out.println(data);
}
}
8장 참조 자료형에 대해서 더 자세히 알아봅시다
- 참조 자료형: new를 사용해서 객체를 생성
- new 없이도 객체를 생성할 수 있는 참조 자료형은 오직 String
기본 생성자
자바는 생성자를 만들지 않아도 자동으로 만들어지는 기본 생성자가 존재
public class ReferenceDefault{
public static void main(String[] args){
ReferenceDefault reference = new ReferenceDefault(); // ReferenceDefault(): 생성자
}
}
아무런 매개 변수가 없는 ReferenceDefault()라는 생성자는 다른 생성자가 없을 경우 기본으로 컴파일 할 때 생성됨
public ReferenceString() {} // 기본 생성자 작성
public ReferenceString(String arg){ } // String을 매개변수로 받는 생성자
public static void main(String args[]){
ReferenceString reference = new ReferenceString();
}
*메소드와 생성자의 차이: 생성자는 리턴 타입이 없고 클래스 이름으로 생성한다
다른 생성자가 없을 경우 기본 생성자가 컴파일할 때 생성되므로 다른 생성자가 있으면 자동으로 만들어지지 않음
→ 매개변수가 없는 생성자를 사용하고 싶으면 기본 생성자를 작성해 컴파일하면 됨
// 인스턴스 변수
String instanceVariable;
// 생성자
public ReferenceString() {}
public ReferenceString(String arg) {}
// 메소드
public static void main(String args[]){
...
}
public String getString(){
return instanceVariable;
}
DTO (Data Transfer Object)
- 어떤 속성을 갖는 클래스를 만들고, 그 데이터를 다른 서버로 전달하기 위한 목적
- VO(Value Object): DTO와 형태는 동일하지만, 데이터를 담아 두기 위한 목적
public class MemberDTO{
public String name;
public String phone;
public String email;
// 생성자: 아무 정보도 모를 때
public MemberDTO(){ }
// 생성자: 이름만 알 때
public MemberDTO(String name){
this.name = name;
}
// 생성자: 이름, 전화번호만 알 때
public MemberDTO(String name, String phone){
this.name = name;
this.phone = phone;
}
// 생성자: 모든 정보를 알 때
public MemberDTO(String name, String phone, String email){
this.name = name;
this.phone = phone;
this.email = email;
}
}
// MemberDTO를 리턴 타입으로 선언하고 객체를 리턴 가능
public MemberDTO getMemberDTO(){
MemberDTO dto = new MemberDTO();
...
return dto;
}
- 자바의 생성자는 매개 변수 개수의 제한은 없고, 몇 개를 만들어도 상관 없다
- 필요한 생성자만 만드는 게 좋다
this
객체의 변수와 매개 변수를 구분하기 위한 this 예약어
public class MemberDTO{
public String name;
public String phone;
public String email;
// 생성자: 이름만 알 때
public MemberDTO(String name){
this.name = name;
}
}
- 인스턴스 변수인 name과 매개 변수인 name을 구분하기 위해 this를 사용
- this.name: 객체의 name (인스턴스 변수인 name)을 의미
메소드 overloading
- 메소드 이름은 같지만 매개 변수가 다를 때 다른 메소드로 인식
ex) 매개 변수의 개수가 같아도 타입의 순서가 다르면 다른 메소드처럼 인식
- 매개 변수의 타입이 같고 변수 이름이 같으면 같은 메소드로 인식
→ “같은 역할을 하는 메소드는 같은 메소드 이름을 가져야 한다”
메소드 return
- 메소드 종료 조건
- 메소드의 모든 문장이 실행되었을 때
- return 문장에 도달했을 때
- 예외가 발생(throw)했을 때
- 자바에서는 모든 타입을 한 개만 리턴 타입으로 넘길 수 있다
- 메소드 이름 앞에 변수의 타입을 지정하고, return이라는 예약어를 사용하여 return
public class ReferenceReturn{
public static void main(String args[]){
ReferenceReturn reference = new ReferenceReturn();
System.out.println(reference.intReturn());
}
public int intReturn(){
int returnInt = 0;
return returnInt;
}
// 결과
0
- 여러 개를 넘겨주고 싶다면?
→ DTO 사용 - 리턴 타입이 void인 메소드에서 더이상 실행하고 싶지 않다면?
}... if(flag) return; // flag가 true이면 메소드 수행을 종료 ...
- public void wantToStopInTheMiddel(boolean flag){
static 메소드 vs 일반 메소드
- static 메소드: 객체를 생성하지 않아도 메소드를 호출할 수 있는 메소드
- 리턴 타입 앞에 static 명시
- static 메소드는 클래스 변수만 사용 가능 (static이 붙어있지 않은 인스턴스 변수는 사용 불가능)
static 블록
static {
// 딱 한번만 수행되는 코드
}
- 객체가 생성되기 전에 한 번만 호출되고, 그 이후에는 호출 불가능
- 클래스 내에 선언되어야 하며 메소드 내에서는 선언 불가
- 인스턴스 변수나 클래스 변수와 같이 어떤 메소드나 생성자에 속해있을 수 없음
- static 블록은 여러개를 선언 가능하지만 선언된 순서대로 블록들이 호출되므로 유의
- static 블록은 기본 생성자가 호출되기 전에 먼저 호출되므로 클래스를 초기화할 때 꼭 수행되어야 하는 작업이 있을 경우 유용
- static 블록 안에서는 static한 것들만 호출 가능
Pass by value: 값만 전달한다
기본 자료형은 무조건 Pass by Value로 데이터를 전달한다
public class ReferencePass{
public static void main(String args[]){
ReferencePass reference = new ReferencePass();
reference.callPassByValue();
}
public void callPassByValue(){
int a=10;
System.out.println("a: " + a);
passByValue(a);
System.out.println("a: " + a);
}
public void passByValue(int a){
a = 20;
System.out.println("passByValue a: " + a);
}
}
// 결과
a: 10
passByValue a: 20
a: 10
- passByValue를 호출하기 전과 후에 데이터가 변경되지 않는다
Pass by reference: 객체에 대한 참조가 넘어간다
참조 자료형은 Pass by Reference로 데이터를 전달한다
public class ReferencePass{
public static void main(String args[]){
ReferencePass reference = new ReferencePass();
reference.callPassByReference();
}
public void callPassByReference(){
String b="z";
MemberDTO member = new MemberDTO("Jiyoon");
System.out.println("b: " + b);
System.out.println("name: " + member.name);
passByReference(b, member);
System.out.println("b: " + b);
System.out.println("name: " + member.name);
}
public void passByReference(String b, MemberDTO member){
b = "b"; // b = new String("z");
member.name = "Babo";
System.out.println("passByReference b: " + b);
System.out.println("passByReference name: " + member.name);
}
}
// 결과
z
Jiyoon
b
Babo
z
Babo
- b = “b”; 는 new를 사용하여 객체를 생성한 것 이므로 passByReference 호출 전 후의 데이터가 변경되지 않음
- member는 다른 객체로 처리한 것이 아니라 매개 변수로 받은 값을 수정했기 때문에 메소드 호출 후 데이터가 변경됨 (참조 자료형이라서)
타입…변수명
매개 변수가 지정되어 있지 않은 임의 개수의 매개변수를 넘겨주기 위해 사용
public void calculateNumbers(int...numbers){ }
ex) printf()
printf(String format, Object... args)
9장 자바를 배우면 패키지와 접근 제어자는 꼭 알아야 해요
패키지 package
클래스들을 구분 짓는 폴더
패키지 선언문
package 패키지명;
- 소스의 가장 첫 줄에 있어야만 한다
- 소스 하나에는 하나만 있어야 한다
- 패키지명은 java로 시작할 수 없다
- 패키지 이름은 모두 소문지로 지정해야 한다
- 자바의 예약어를 사용할 수 없다
import
자바에서는 같은 패키지에 있는 클래스들과 java.lang 패키지에 있는 클래스들만 접근 가능
다른 패키지에 있는 클래스에 접근하려면?
import 패키지명.클래스명;
static한 변수(클래스 변수)와 static 메소드를 사용하려면?
import static 패키지명.클래스명.메소드명;
import static 패키지명.클래스명.클래스변수;
*import 하지 않아도 되는 패키지
- java.lang 패키지 ex) Stirng, System
- 같은 패키지
접근 제어자 Access modifier
- public : 누구나 접근 가능
- protected : 같은 패키지 내에 있거나 상속받은 경우에만 접근 가능
- package-private(접근제어자 없음) : 같은 패키지 내에 있을 때만 접근 가능
- private : 해당 클래스 내에서만 접근 가능
접근 제어자 사용
- 메소드
- 인스턴스 변수
- 클래스 변수
- 클래스 선언문
*public으로 선언된 클래스가 소스 내에 있다면, 그 소스 파일의 이름은 public인 클래스 이름과 동일해야 한다
10장 자바는 상속이라는 것이 있어요
extends
public class Child extends Parent{ }
// Parent 클래스에 선언되어 있는 public 및 protected로 선언되어 있는 모든 변수와 메소드를 사용가능
extends 클래스명 → 클래스를 상속받는다
Child → Parent
상속
- 부모 클래스에서는 기본 생성자를 만들어 놓는 것 이외에는 상속을 위해서 아무런 작업을 할 필요는 없다
- 자식 클래스는 클래스 선언시 extends 다음에 부모 클래스 이름을 적어준다
- 자식 클래스의 생성자가 호출되면, 자동으로 부모 클래스의 매개 변수 없는 생성자가 실행된다
- 자식 클래스에서는 부모 클래스에 있는 public, protected로 선언된 모든 인스턴스 및 클래스 변수와 메소드를 사용할 수 있다
- 자바는 다중 상속이 불가능하다
부모 클래스에 기본 생성자가 없다면?
- 부모 클래스에 “매개 변수가 없는” 기본 생성자를 만든다
- 자식 클래스에서 부모 클래스의 생성자를 명시적으로 지정하는 super()를 사용한다
super(); // 부모 클래스의 생성자를 호출
- 부모 클래스에 매개 변수가 있는 생성자만 있을 경우에는 super()를 이용해 부모 생성자를 꼭 호출해야 함
- 자식 클래스의 생성자에서 super()를 명시적으로 지정하지 않으면, 컴파일시 자동으로 super()가 추가됨
- super()는 자식 클래스의 생성자에서 가장 첫줄에 선언되어야 한다
메소드 overriding
자식 클래스에서 부모 클래스에 있는 메소드와 동일하게 선언하는 것
접근 제어자, 리턴 타입, 메소드 이름, 매개 변수 타입 및 개수가 모두 동일해야 함
public class Parent{
public Parent(){ }
public void printName(){
System.out.println("Parent");
}
}
public class Child extends Parent{
public Child(){ }
public void printName(){
System.out.println("Child");
}
}
public class InheritanceOverriding{
public static void main(String[] args){
Child child = new Child();
child.printName();
}
}
// 결과
Child
- 부모 클래스에 선언되어 있는 메소드와 동일하게 선언되어 있는 메소드를 자식 클래스에 선언하면 자식 클래스의 메소드만 실행된다
- 부모 클래스에 있는 메소드는 자식 클래스에서 리턴 타입을 마음대로 바꿀 수 없다
- 부모 클래스에 있는 메소드는 자식 클래스에서 접근 제어자를 축소되는 방향으로 바꿀 수 없다
ex) 부모 클래스에서 public으로 선언한 것을 자식 클래스에서 private으로 선언할 수 없음
부모 클래스에서 private으로 선언한 것은 자식 클래스에서 모든 접근 제어자로 선언 가능
Overloading vs Overriding
- Overloading: 확장 (메소드의 매개 변수들을 확장)
- Overriding: 덮어쓰기 (부모 클래스가 가지고 있는 메소드를 자식 클래스가 재정의)
참조 자료형의 형 변환
- 자식 클래스인 Child에서는 부모 클래스인 Parent에 있는 메소드와 변수들을 사용 가능
- 부모 클래스인 Parent에서는 자식 클래스인 Child에 있는 모든 메소드와 벼수들을 사용 불가능
- 자식 클래스의 타입을 부모 클래스의 타입으로 형 변환: 자동
Parent parent = new Parent();
Child child = new Child();
Parent parent2 = child; // 정상
Child child2 = parent; // error 발생
Child child2 = (Child)parent; // 예외 발생
Child child2 = (Child)parent2; // 정상
- parent2: Parent 클래스의 객체인 것처럼 보이지만 Child 클래스의 객체
- parent2를 Child 클래스로 형 변환은 가능 (명시적 형 변환)
instanceof 객체의 타입 확인
if(객체 instanceof 클래스(타입){ } // 객체가 해당 클래스타입인지 확인
*instanceof를 사용하여 타입을 점검할 때는 가장 하위에 있는 자식 타입부터 확인
→ 부모 타입도 true를 반환하기 때문에
다형성 Polymorphism
형 변환을 하더라도, 실제 호출되는 것은 원래 객체에 있는 메소드가 호출된다
'STUDY > Java' 카테고리의 다른 글
<자바의 신> 16장 클래스 안에 클래스가 들어갈 수도 있구나 (0) | 2023.12.09 |
---|---|
<자바의 신> 11장 매번 만들기 귀찮은데 누가 만들어 놓은 거 쓸 수 없나요? (0) | 2023.12.09 |
<자바의 신> 1장 프로그래밍이란 무엇인가? (0) | 2023.12.09 |
아파치 톰캣(Apache-Tomcat) 설치 (0) | 2021.11.05 |
[JAVA] Stream 스트림 (0) | 2021.11.05 |