2022.11.17-3 JAVA 클래스 3
6. 클래스
6.9 인스턴스 멤버
필드와 메소드는 선언 방법에 따라 인스턴스 멤버와 정적 멤버로 분류할수 있다.
인스턴스 멤버로 선언되면 객체 생성후 사용할수잇고 정적멤버로 선언되면 객체 생성없이도 사용할 수 있다.
인스턴스 멤버 : 객체에 소속된 멤버(객체를 생성해야함 사용할 수 있는멤버)
정적멤버 : 클래스에 고정된 멤버 객체 없이도 사용할 수 있는 멤버
지금까지 위에서 객체에 선언한 필드와 메소드가 인스턴스 멤버이다.
외부 클래스에서 사용하기 위해서는 car객체를 먼저 생성하고 참조변수로 접근해서 사용해야한다.
메소드는 코드의 덩어리 이므로 객체마다 저장한다면 중복 저장으로 인해 메모리 효율이 떨어진다.
따라서 메소드 코드는 메소드 영역에 두되 공유해서 사용하고 이때 객체 없이는 사용하지 못하도록 제한을 건것임.
this키워드
객체 내부에서는 인스턴스 멤버에 접근하기 위해 this를 사용할 수 잇다. 우리가 자신을 '나'라고 하듯이 객체는 자신을 'this'라고 표현한다.
생성자와 메소드의 매개변수 명이 인스턴스 멤버인 필드명과 동일한 경우 인스턴스 필드임을 강조하고자할때 this를 사용한다.
6.10 정적멤버
자바는 클래스 로더를 이용해서 클래스를 메소드영역에 저장하고 사용한다. 정적멤버란 메소드 영역의 클래스레 고정적으로 위치하는 멤버를 말한다.
정적멤버는 객체를 생성할 필요없이 클래스를 통해 바로 사용이 가능하다.
필드와 메소드는 모두 정적멤버가 될 수잇다. 정적 필드와 정적 메소드로 선언하려면 static 키워드를 추가하면된다.
6.10.1 정적 멤버 선언
정적 필드 선언
static 타입 필드 [=초기값];
대부분의 값은 객체에 소속되는데 예를들어 파이나 korean클래스의 국적 등 바뀌지 않은거 객체마다 작성하는것은 비효율적임.
정적메소드 선언
static 리턴타입 메소드(매개변수){}
String color; // 계산기별로 색이 다를 수 있음.
static double pi = 3.14159; // 계산기에서 사용하는 파이값은 동일하다.
void setColor(String color) {this.color = color}; // 인스턴스 멤버를 사용하면 인스턴스 메소드로 작성해야함.
static int plus(int x, int y) { return x + y}; // 인스턴스멤버 사용하나도 안함. 그러면 static붙이는게 좋다.
static double pi = 3.14159;
static int plus(int x, int y)
{
return x + y;
}
static int minus(int x, int y)
{
return x - y;
} //실제 실행
double result1 = 10* 10 * Calculator.pi;
int result2 = Calculator.plus(10, 5);
int result3 = Calculator.minus(10, 5);
System.out.println("result1: " + result1);
System.out.println("result2: " + result2);
System.out.println("result3: " + result3);
//정적변수인데 참조타입으로 불러오면 이클립스는 경고표시를 냄.
//Calculator myCalcu = new Calculator();
//double result4 = 10* 10* myCalcu.pi;
6.10.2 정적블록
정적 필드 선언과 동시에 초기값을 주는 것이 일반적이나 복잡한 초기화 작업이 필요하다면 정적블록을 이용해야한다.
필드인데 계산작업을 하고나서 계산작업결과를 초기값으로 넣고 싶을때 정적블록 사용.
static { ... } 클ㄹ래스가 메모리로 로딩될때 자동으로 실행된다. 메소드영역에 바이트코드가 저장될때
왜있어야하냐? 인스턴스 필드는 인스턴스할때나 생성자에서 값을 줌.
그러나 정적필드는 생성자를 사용하지 못함. 그래서 정적블록이 필요하다.
static String company = "MyCompany";
static String model = "LCD";
static String info;
static{
info = company + "-" + model; // 여기는 단순하지만 매우 복잡한게 필요하게되면 필요함.
} //바이트코드될때 이미 계산이 실행되어 저장 .이를 실행하면됨.
System.out.pirntln(Television_info); //MyCompnay-LCD6.10.3 인스턴스 멤버 사용불가
정적 메소드와 정적블로드는 객체가 없어도 실행된다는 특징때문에 인스턴스 필드나 인스턴스 메소드를 사요하루 수없다.또한 객체 자신의 참조인 this도 사용할 수 없다.
정적 메소드와 정적블록에서 인스턴스 멤버를 사용하고 싶다면 객체를 먼저 생성하고 참보변수로 접근해야한다.
main()메소드에서 실행할때 인스턴스 멤버를 사용하기 위해 객체를 생성하고 불러오는 것이 이것때문이다.
6.11 final 필드와 상수
인스턴스 필드와 정적 필드는 언제든지 값을 변경할 수 있다. 그러나 경우에 따라서는 값을 변경하는 것을 막고 읽기만 허용해야할때가 있다.
이때 final필드와 상수를 선언해서 사용한다.
6.11.1 final 필드 선언
final 필드는 초기값이 저장되면 이것이 최종적인 값이 되어 프로그램 실행도중에 수정할 수 없게된다.
final 타입 필드 [= 초기값];
final필드에 초기값을 줄수있는 방법은 다음 두가지 뿐이다. 1. 필드선언시에 초기값대입 2. 생성자에서 초기값 대입
고정된 값이라면 필드선언시에 주는 것이 제일간단하다.
하지만 복잡한 초기화 코드가 필요하거나 객체 생성시에 외부에서 전달된 값으로 초기화한다면 생성자에서 해야한다.
//인스턴스 final 필드선언
final String nation = "대한민국";
final String ssn;
//인스턴스 필드 선언
String name;
//생성자 선언
public Korean(String ssn, String name)
{
this.ssn = ssn;
this.name = name;
}// 객체생성 시 주민등록번호와 이름 전달
Korean k1 = new Korean("123456-1234567","감자바");
//필드값읽기
System.out.println(k1.nation);
System.out.println(k1.ssn);
System.out.println(k1.name);
//final필드는 값을 변경할 수 없음.
//k1.nation = "USA"
//k1.ssn = "123-12-134";
//비final필드는 값 변경가능
k1.name = "김자바";6.11.2 상수선언
우리주변에는 불변의 값이 있다. 불변의 값은 수학에서 사용되는 원주율 파이나 지구의 무게 및 둘레등이 해당된다.
이런 불변의 값을 저장하는 필드를 자바에서는 상수라고 한다.
상수는 객체마다 저장할 필요가 없고 여러개의 값을 가져도 안되기때문에 static 이면서 final인 특성을 가져야한다.
static final 타입 상수 [= 초기값];
복잡한 초기화가 필요한 경우 정적블록안에서 초기화할 수도 있다.
static final double PI = 3.14159;
또한 상수는 정적필드이므로 클래스명.상수로 호출할수잇다.
// 상수 선언및 초기화
static final double EARTH_RADIUS = 6400;
// 상수 선언
static final double EARTH_SURFACE_AREA;
//정적블록에서 상수 초기화
static {
EARTH_SURFACE_AREA = 4 * Math.PI(자바에서 제공하는 상수) * EARTH_RADIUS * EARTH_RADIUS
} // 상수읽기
System.out.println("지구의 반지름:" + Earth.EARTH_RADIUS + "km"); //6400.0km
System.out.println("지구의 표면적:" + Earth.EARTH_SURFACE_AREA + "km^2"); //5.147185403641517E8km^26.12 패키지
자바의 패키지는 단순히 디렉토리만을 의미하지 앟는다. 패키지는 클래스의 일부분이며 클래스를 식별하는 용도로 사용된다.
예를들어 현재 작성하는 패키지는 ch06.sec12.패키지이름 인거임.
클래스명만으로는 구분할 수 없어서 패키지이름으로 구분하는것. 클래스를 식별하기위해 사용
회사 도메인 역순으로 만든다. mycompany.com 이면 com.mycompany.클래스
패키지는 상위 패키지와 하위패키지를 도트(.)으로 구분한다.
패키지에 속한 바이트 코드 파일(~.class)는 따로 떼어내서 다른 디렉토리로 이동할 수 없다.
예를들어 Car클래스가 com.mycompany패키지에 소속되어있다면
다른디렉토리에 Car.class를 옮겨 거장할 경우 car클래스를 사용할 수 없게된다.
6.12.1 패키지 선언
package 상위패키지.하위패키지; 항상 소스파일 최상단에 위치해야한다.
패키지 이름은 모두 소문자로 작성하는 것이 관례이고 중복ㅈ되지않도록 회사 도메인이름의 역순으로 작성하고 마지막에는 프로젝트 이름을 붙여주는 것이 일반적임.
소스파일(java)가 저장되면 이클립스는 자동으로 컴파일해서 bin디렉토리에 패키지 디렉토리와 함께 바이트코드파일(class)를 생성한다.
만약 패키지 선언이 없다면 default package에 포함시킨다. 프로젝트는 패키지 없이 클래스를 만드는 경우가 드물다.
6.12.2 import문
현재 개발중인 패키지에서 다른 패키지에 있는 libray클래스를 가져와서 쓰고싶다. 다른패키지에서 어떤거를 쓸거냐?
package com.mycompany
improt com.hankook.Tire;
public class Car {
//필드선언시 com.hankook.Tire 클래스를 사용 이 패키지에 없는 걸르 가져와서쓰고싶음.
Tire tire = new Tire();
}
Scanner사용할때 java.util.Scanner로 사용햇던것 이랑 같다.만약 동일한 패키지에 포함된 다수의 클래스를 사용해야한다면 클래스 이름을 생략하고 *을 사용할수있다.
import com.hankook.*; hankook 바로 밑에있는 클래스만 사용가능
import com.hankook.project.*; 하위패키지에 있는 클래스를 쓰고싶으면 하위패키지까지 표현해줘야한다.
만약 두가지를 불러와서 사용하는데 같은 클래스가 있다면
import com.hankook.*;
import com.kumho.*;
com.hankook.Tire tire = new com.hankook.Tire();으로 사용해야함.
ch06.sec12.hankook.Tire tire1 = new ch06.sec12.hankook.Tire();
//참고안하고 불러오면 ctrl shift o 하면 자동적으로 import써짐
ch06.sec12.kumho.Tire tire2 = new ch06.sec12.kumho.Tire(); // 충돌하지 않게 이름 붙여줌. 이러면 import도 필요없음.
SnowTire tire3 = new SnowTire();
AllSeasonTire tire4 = new AllSeasonTire(); // 다 안쓰고 컨트롤 스페이스 누르면 알아서 improt생김확인문제
문제 13번 + 14번
13번 Member클래스를 모델링 회원의 데이터로는 이름 아이디 패스워드 나이가 있음.
14번 13번 문제에서 작성한 Member클래스에 생성자를 추가 하려고한다. 다음과 같이 name필드와 id필드를 외부에서 받은 값으로 초기화하도록 생성자 선언
public class Member {
String name;
String id;
String password;
int age;
public Member (String name, String id)
{
this.name = name;
this.id = id;
}
}문제 15번
login() 메소드를 호출할때는 매개값으로 id와 password를 제공하고 logout()메소드는 id는 매개값으로 제공하려고 한다. 다음 조건과 예제 코드를 보고 MemberService클래스에서 login(), logout()메소드를 선언해보세요.
1.login() 메소드는 매개값 id가 "hong" 매개값 password가 "1235"일경우에 true로 리턴
2.logout() 메소드는 id + "님이 로그아웃되었습니다"가 출력되도록할것
public class MemberService {
boolean login(String id, String password)
{
if(id.equals("hong") && password.equals("12345") )
{
System.out.println("로그인 되었습니다.");
return true;
}
else
{
return false;
}
}
void logout(String id)
{
System.out.println(님이 로그아웃 되었습니다.");
}문제 16번
println()메소드는 매개값을 콘솔에 출력합니다. println()메소드의 매개값으로는 int boolean double String 타입값을 줄수 있습니다.
Printer클래스의 println()메소드를 오버로딩하여 선언하기.
public class Printer {
void println(int value)
{
System.out.println(value);
}
void println(boolean value)
{
System.out.println(value);
}
void println(double value)
{
System.out.println(value);
}
void println(String value)
{
System.out.println(value);
}
}문제 17번
16번 문제에서 printer객체를 생성하고 println()메소드를 호출했습니다.
객체를 생성하지 않고도 호출할수 있도록 클래스 수정
public class Printer {
static void println(int value)
{
System.out.println(value);
}
static void println(boolean value)
{
System.out.println(value);
}
static void println(double value)
{
System.out.println(value);
}
static void println(String value)
{
System.out.println(value);
}2022.11.17 리뷰
클래스로 넘어오면서 매우 많은게 생겨나고 있다.
객체의 필드 생성자 메소드 등 이해는 되겠지만
너무 많은 명령어들이 나오니 정신이 혼미해진다.
복습이 더 중요한 것 같아서 6.13 6.14 6.15는 내일로 미루도록 하겠다.
중요한 것은 꺾이지 않는 마음이지만 마음이 꺾일 것 같다.