1. static
- static변수와 static메소드는 정적필드와 정적메소드라고 부른다. (클래스변수, 클래스메소드)
- 정적필드와 정적메소드는 객체(인스턴스)에 소속된 멤버가 아니라 클래스에 고정된 멤버
1-1. 정적변수, 정적메소드
- Sample 클래스 - 정적변수, 정적메소드가 포함되어 있는 클래스로 객체 생성하기
- 설계도 로딩
- 작성한 Samlple.class 설계도(소스파일)를 클래스 영역에 로딩(컴파일)
- Sample.class 설계도 안에는 멤버변수, 멤버메소드, 정적변수, 정적메소드가 다 있었어 - 정적변수, 정적메소드 할당
- 클래스 영역에는 정적 변수, 정적 메소드 영역이 있어
- 수행문에 클래스이름이 등장하는 순간, 클래스 영역 내의 정적변수/메소드 영역에 Sample 전용의 공간이 만들어져
( 선언할 때 X, 메모리가 로딩될 때 O ) ---> ( 선언한 곳은 아직 소스파일이니까 )
( 객체 생성하든 안하든 메모리에 로딩이 되면 바로 만들어짐 )
- 이 안에 정적변수b, 정적메소드test3, test4 (설계도가 아니라 실제 사용한 상태로 만들어져)가 들어가고
- Sample.class설계도 안에 있는 정적변수, 정적메소드는 없어져 - 객체 생성
- Sample sample1 = new Sample();
- 객체영역에는 Sample객체 3개가 만들어지고 참조변수가 각각의 주소값을 가지고 있음
- 이 Sample객체마다 안에는 멤버변수, 멤버메소드가 들어가 있음
( 정적변수, 정적메소드는 이 객체에 포함이 안되어 있음 -> 정적변수,메소드 영역에 들어가있음 )
* 멤버변수 a는 객체마다 생성이 되지만, 정적변수 b는 메모리에 로딩되는 순간 딱 한번만 생성됨
1-2. 정적변수, 정적메소드의 사용
- SampleApp 클래스(실행클래스) - 정적변수, 정적메소드 사용하기
public class SampleApp {
public static void main(String[] args) {
// 클래스변수(정적변수)의 사용 ( 클래스를 통해 클래스변수에 접근 (클래스 내에 있으니까) )
Sample.b = 100; // 객체 생성없이 사용 가능
// 수행문에서 Sample클래스 이름이 나오는 순간, Sample영역이 메모리에 로딩
// 정적변수/정적메소드는 사용가능 상태가 됨
// Sample 클래스 안에 가야 b가 있다 => 클래스에 고정
// 객체 생성
Sample sample1 = new Sample( ); // 위에서 Sample 설계도가 로딩되었기 때문에 다시 로딩되지 않는다.
Sample sample2 = new Sample( );
Sample sample3 = new Sample( );
// 멤버변수의 사용 ( 참조변수를 통해 멤버변수에 접근 )
sample1.a = 10; // 멤버변수, 멤버메소드는 객체 생성 후 사용
sample2.a = 10; // 참조변수를 통해 사용
sample3.a = 10;
// 멤버메소드 실행
sample1.test1( );
// 정적메소드 실행
Sample.test3( ); // 객체 생성없이 사용가능
// 클래스이름.변수 / 클래스이름.메소드( ) 로 사용
}
}
public void test1( ) {
s.o.p(a); s.o.p(Sample.b); // 멤버변수 사용가능, 클래스변수 사용가능
test2( ); Sample.test3(); Sample.test4(); // 멤버메소드, 클래스메소드 사용가능
}
=> 멤버 메소드의 블록에서는 멤버변수/ 클래스변수/ 멤버메소드 / 클래스메소드 모두 사용가능
public static void test1( ) {
s.o.p(a);// 멤버변수 사용불가
s.o.p(Sample.b); // 클래스변수 사용가능
test2( );// 멤버메소드 사용불가
Sample.test3(); // 클래스메소드 사용가능
}
=> 정적 메소드의 블록에서는 정적변수, 정적메소드만 사용가능 (객체 생성 전이니까)
( ∵ 정적변수,메소드가 먼저 생기고, 그 다음에 객체 생성을 통해서 멤버변수,메소드가 생겨
정적메소드가 사용가능한 시점은 아직 객체가 생성되기 전이니까 멤버변수, 멤버메소드에 접근할 수가 없어 )
1-3. 정적변수, 정적메소드의 생성과정
- main메소드가 왜 static이어야 하는가?
- main 메소드를 객체생성 없이 바로 사용하기 위해서 static 이 붙는 것
- Hello.main( ); : Hello클래스의 정적변수/메소드 영역에 있는 main메소드 실행
1-4. 정적 메소드의 사용 이유
1) 정적변수 (static 변수)
- 인스턴스변수 a와 정적변수 b의 가장 큰 차이점
a : 객체마다 생성
b : 딱 한번 생성 - 정적변수의 사용 이유
- 원의 둘레 공식 = 2 * pi * r
- 여러개의 객체를 통해서 여러개의 원을 만들건데, 원이 아무리 다양해도 pi는 항상 똑같은 값
-> 객체의 고유한 속성이 될 수 없어 -> 객체마다 갖고있을 필요가 없어 -> 그럴때 정적변수 (상수)
-> static final double PI = 3.14;
∴ 원주율값은 변하지 않는 값이므로 정적변수로 정의, 정적변수는 대부분 상수, 상수는 변수명을 전부 대문자 - 정적변수 : 상수를 정의할 때 사용
- 상수 정의하기 (정적변수)
public class FileUpload {
static final String USER_IMAGE_SAVE_DIRECTORY = "resources/images/user"; // 이미지는 항상 여기에 저장
static final int IMAGE_SIZE = 100*800; // 파일크기는 항상 고정
} - final 키워드 -> 값이 한번 할당되고나서는 그 값이 수정되지 않게 할 때, 정적변수가 아닌 곳에도 붙임
정적변수 -> 보통 static final
public class Circle {
private double x;
private double y;
private double r;
public static final double PI = 3.14; // 정적변수, 상수 정의하기. 상수는 public static final이다.
public Circle(double x, double y, double r) { // 객체생성하면서 초기화하는 생성자
this.x = x;
this.y = y;
this.r = r;
}
public double round() {
return 2*Circle.PI*r;
}
public double area() {
/*
* - PI는 Circle 클래스의 정적변수
* Circle.Pi로 사용
* - pow(double a, double b)는 Math클래스의 정적메소드
* Math.pow(r,2)로 사용
*/
return Circle.PI*Math.pow(r, 2); // Math안에는 전부 정적변수, 정적메소드
}
public void display() {
System.out.println("x좌표: "+x);
System.out.println("y좌표: "+y);
System.out.println("둘레길이: "+round());
System.out.println("원의 넓이: "+area());
}
}
public class CircleApp {
public static void main(String[] args) {
Circle c1 = new Circle(10, 10, 5);
Circle c2 = new Circle(0, 0, 7);
c1.display();
c2.display();
}
}
x좌표: 10.0
y좌표: 10.0
둘레길이: 31.400000000000002
원의 넓이: 78.5
x좌표: 0.0
y좌표: 0.0
둘레길이: 43.96
원의 넓이: 153.86
* static 변수, 메소드는 클래스단위로 생기는것 !
public class Circle {
public static final double PI = 3.14;
public Circle(double x, double y, double r) { ~~ } }
public class SampleApp {
int x; // 멤버변수
static int y=2000; // 정적변수
public void test1() { ~~ } }
2) 정적메소드 (static 메소드)
* 인스턴스메소드: 객체 안에서 속성(멤버변수)과 상호작용하며 사용 가능
* 정적메소드 : - 객체의 속성(멤버변수)과 상호작용없이(객체 생성할 필요 X) 직접 값을 전달받아서 수행
- 여러 클래스에서 광범위하게 사용가능
- 인스턴스 메소드, 정적 메소드 내에서 변수들의 사용 가능 여부
public class SampleApp {
int x; // 멤버변수
static int y=2000; // 정적변수
public void test1() {
System.out.println(x);
System.out.println(SampleApp.y);
System.out.println(y); // SampleApp내부에서는 클래스이름을 생략해도 정젹변수, 정적메소드를 사용할 수 있다. 비추천.
}
public static void main(String[] args) {
// System.out.println(x); // 컴파일 오류, 정적메소드에서 인스턴스변수에 접근할 수 없다.
System.out.println(SampleApp.y); // 정적메소드에서 정적변수 사용 가능
SampleApp app = new SampleApp();
app.x = 100; // 인스턴스변수는 객체 생성 후, 참조변수를 통해서 접근 가능
System.out.println(app.x);
}
}
- 정적메소드의 사용 예시
import java.text.DecimalFormat;
public class NumberUtils {
/**
* 숫자를 3자리마다 ,가 포함된 문자열로 반환
* @param number 숫자
* @return ,가 포함된 문자열
*/
public static String numberToStringWithComma(long number) {
DecimalFormat format = new DecimalFormat("#,###");
return format.format(number);
}
/**
* 문자열 "10,000,000"을 정수 10000000로 반환
* @param str
* @return
*/
public static int stringToInt(String str) {
}
public static long stringToLong(String str) {
}
public static double stringToDouble(String str) {
}
}
public class NumberUtilsApp {
public static void main(String[] args) {
int amount = 100000000;
System.out.println("입금액: " + NumberUtils.numberToStringWithComma(amount));
}
}
1-5. 변수의 종류
< 멤버변수, 인스턴스변수, 프로퍼티, 속성 >
- 접근제한자를 붙일 수 있다.
- 객체 생성 이후에 사용 가능
- 생성된 객체 내부에 존재
- 객체가 존재하는 동안 계속 유지
- 모든 생성자, 모든 멤버 메소드에서 사용가능 (정적메소드x)
public class Account {
private String no;
private String owner;
private int password;
private long balance;
< 정적변수, 클래스변수 >
- 접근제한자를 붙일 수 있다.
- 클래스가 로딩되면 즉시 사용가능
- 클래스 로딩 후 사용가능해진 정적 변수는 프로그램이 종료될 때까지 유지
- 모든 생성자, 모든 멤버 메소드, 모든 정적 메소드에서 사용가능
public class Account {
public static final double DESPOSITE_RATE = 0.031;
< 매개변수 >
- 메소드 실행시 인자로 전달된 값을 저장하는 변수
- 접근제한자, static을 붙일 수 없다.
- 매개변수에 저장된 값을 메소드 블록에서 사용가능
- 메소드 종료되면 즉시 사라짐
public void expire(String date, int amount) {
int amount = (int) (balance*DEPOSITE_RATE) + balance;
System.out.println("예상 예지금액: " + amount);
}
}
< 지역변수 >
- 메소드 안에서 정의된 변수
- 접근제한자, static을 붙일 수 없다.
- 변수가 선언된 다음 행부터 사용가능
- 그 변수가 선언된 블록이 닫히거나, 메소드가 종료되면 즉시 사라짐
public void expire(String date, int amount) {
int amount = (int) (balance*DEPOSITE_RATE) + balance;
System.out.println("예상 예지금액: " + amount);
}
}
2. 상속
2-1. 클래스와 클래스의 관계
has a 관계
- A has a B : A 클래스가 B 클래스를 포함(의존)하는 관계
( ex. Car has a Engine : 자동차는 엔진을 포함하고 있다. 자동차는 엔진없이는 굴러갈 수 없다. (의존관계)
Book has a review : 책은 리뷰를 포함하고 있다. (포함관계) )
is a 관계
- A is a B : A 클래스가 B 클래스의 종류 중 하나.
( ex. Iphone is a SmartPhone : 아이폰도 스마트폰이다.
GalaxyFlip is a SmartPhone : 갤럭시플립도 스마트폰이다. )
- B 클래스가 동일한 A 클래스들은 비슷한 특징, 기능을 가짐. (제네시스와 모닝)
- B 클래스는 상위 클래스, A 클래스는 하위 클래스(구체적)
- A 클래스는 B 클래스로부터 공통속성과 공통기능을 상속받고, 자신의 고유속성과 고유기능을 구현 (상속관계)
-> 하위클래스를 빨리 만들 수 있음
-공통속성,기능을 갖고있으면 같은 타입이라고 봄 = 같은 타입의 변수 안에 담을 수 있다
Iphone p1 = new Iphone(); // Iphone객체는 Iphone타입이고, SmartPhone타입이다.
Galaxy p2 = new Galaxy(); // Galaxy객체는 Galaxy타입이고, SmartPhone타입이다.
SmartPhone p3 = new Iphone(); // Iphone객체를 SmartPhone타입의 참조변수로 참조할 수 있다.
SmartPhone p4 = new Galaxy(); // Galaxy객체를 SmartPhone타입의 참조변수로 참조할 수 있다.
- 기존 클래스(상위클래스)를 상속받아서 새로운 클래스(하위클래스) 작성할 때는 extends 키워드를 사용
extends(확장) : 상속은 상위 클래스를 확장시켜서 하위 클래스틀 만드는 것
- 자식한테 상속이 안되는 것
1) 은닉화된 코드
2) 생성자
2-2. 상속 활용 예시
- 설계도
- Phone 객체
/**
* 전화기를 표현하는 클래스
* @author wnnns
*
*/
public class Phone {
//은닉화된 멤버변수
private String number;
/**
* 전화번호 반환
* @return 전화번호
*/
public String getNumber() {
return number;
}
/**
* 전화번호를 전달받아서 멤버변수 number에 대입
* @param number
*/
public void setNumber(String number) {
this.number=number;
}
/**
* 전화하기 기능 실행
*/
public void tel() {
System.out.println("["+number+"] 전화하기 기능 실행");
}
/**
* 문자하기 기능 실행
*/
public void sms() {
System.out.println("["+number+"] 문자하기 기능 실행");
}
}
- SmartPhone 객체
/**
* 스마트폰을 표현하는 클래스
* <p> Phone클래스가 부모클래스
* @author wnnns
*
*/
public class SmartPhone extends Phone {
private String email;
private String ip;
/**
* 이메일 반환
* @return 이메일
*/
public String getEmail() {
return email;
}
/**
* 이메일을 전달받아서 멤버변수 email에 대입
* @param email 이메일 주소
*/
public void setEmail(String email) {
this.email = email;
}
/**
* ip주소 반환
* @return ip주소
*/
public String getIp() {
return ip;
}
/**
* ip주소를 전달받아서 멤버변수 ip에 대입
* @param ip ip주소
*/
public void setIp(String ip) {
this.ip = ip;
}
/**
* 이메일 보내기 기능 실행
*/
public void sendEmail() {
System.out.println("["+email+"] 이메일 보내기 기능 실행");
}
/**
* 인터넷 기능 실행
*/
public void internet() {
System.out.println("["+ip+"] 인터넷 기능 실행");
}
}
- PhoneApp1 객체 (실행)
public class PhoneApp1 {
public static void main(String[] args) {
System.out.println("### Phone객체 생성해서 사용하기");
Phone p1 = new Phone();
p1.setNumber("010-1111-1111");
p1.tel();
p1.sms();
System.out.println("### SmartPhone객체 생성해서 사용하기");
SmartPhone p2 = new SmartPhone();
p2.setNumber("010-2222-2222"); // Phone 클래스로부터 상속받은 기능
p2.setEmail("hong@gmail.com"); // SmartPhone 클래스에 정의된 기능
p2.setIp("192.168.10.100"); // SmartPhone 클래스에 정의된 기능
p2.tel(); // Phone 클래스로부터 상속받은 기능
p2.sms(); // Phone 클래스로부터 상속받은 기능
p2.sendEmail(); // SmartPhone 클래스에 정의된 기능
p2.internet(); // SmartPhone 클래스에 정의된 기능
}
}
### Phone객체 생성해서 사용하기
[010-1111-1111] 전화하기 기능 실행
[010-1111-1111] 문자하기 기능 실행
### SmartPhone객체 생성해서 사용하기
[010-2222-2222] 전화하기 기능 실행
[010-2222-2222] 문자하기 기능 실행
[hong@gmail.com] 이메일 보내기 기능 실행
[192.168.10.100] 인터넷 기능 실행
- Iphone 객체
/**
* 아이폰을 표현하는 클래스
* <p>SmartPhone클래스가 부모 클래스
* @author wnnns
*
*/
public class Iphone extends SmartPhone{
/**
* 전달받은 금액만큼을 애플페이로 결제
* @param amount 결제금액
*/
public void applePay(int amount) {
System.out.println("["+amount+"] 금액을 애플페이로 결제");
}
/**
* 페이스아이디로 잠금 해제
*/
public void faceId() {
System.out.println("페이스아이디 기능 실행해서 잠금 해제");
}
}
- Galaxy 객체
**
* 갤럭시를 표현하는 클래스
* <p>SmartPhone클래스가 부모 클래스
* @author wnnns
*
*/
public class Galaxy extends SmartPhone {
/**
* 전달받은 금액만큼을 삼성페이로 결제
* @param amount 결제금액
*/
public void samsungPay(int amount) {
System.out.println("["+amount+"] 금액을 삼성페이로 결제");
}
/**
* 전달받은 키워드로 검색
* @param keyword 키워드
*/
public void bixby(String keyword) {
System.out.println("빅스비로 ["+keyword+"] 검색어를 검색");
}
}
- PhoneApp2 객체 (실행)
public class PhoneApp2 {
public static void main(String[] args) {
System.out.println("### Iphone 객체를 생성해서 기능 사용하기");
Iphone p1 = new Iphone();
p1.setNumber("010-1111-1111"); // Phone 클래스로부터 상속받은 기능
p1.setEmail("kang@gmail.com"); // SmartPhone 클래스로부터 상속받은 기능
p1.setIp("192.168.10.101"); // SmartPhone 클래스로부터 상속받은 기능
p1.tel(); // Phone 클래스로부터 상속받은 기능
p1.sms(); // Phone 클래스로부터 상속받은 기능
p1.sendEmail(); // SmartPhone 클래스로부터 상속받은 기능
p1.internet(); // SmartPhone 클래스로부터 상속받은 기능
p1.applePay(10000); // Iphone 클래스에 정의된 기능
p1.faceId(); // Iphone 클래스에 정의된 기능
System.out.println();
System.out.println("### Galaxy 객체를 생성해서 기능 사용하기");
Galaxy p2 = new Galaxy();
p2.setNumber("010-1111-2222"); // Phone 클래스로부터 상속받은 기능
p2.setEmail("kim@gmail.com"); // SmartPhone 클래스로부터 상속받은 기능
p2.setIp("192.168.10.101"); // SmartPhone 클래스로부터 상속받은 기능
p2.tel(); // Phone 클래스로부터 상속받은 기능
p2.sms(); // Phone 클래스로부터 상속받은 기능
p2.sendEmail(); // SmartPhone 클래스로부터 상속받은 기능
p2.internet(); // SmartPhone 클래스로부터 상속받은 기능
p2.samsungPay(250000); // Galaxy 클래스에 정의된 기능
p2.bixby("아이폰14"); // Galaxy 클래스에 정의된 기능
}
}
<< Iphone 객체 생성해서 사용하기
[010-3333-3333] 전화하기 기능
[010-3333-3333] 문자하기 기능
[kim@naver.com] 이메일 보내기 기능
[192.168.10.100] 인터넷 기능
[50000] 금액을 애플페이로 결제
페이스아이디로 잠금 해제
<< Galaxy 객체 생성해서 사용하기
[010-4444-4444] 전화하기 기능
[010-4444-4444] 문자하기 기능
[bang@naver.com] 이메일 보내기 기능
[192.168.10.100] 인터넷 기능
[10000] 금액을 삼성페이로 결제
빅스비로 [삼성] 검색
2-3. 상속관계인 객체의 생성 및 활용
* 상속받는 객체(부모클래스)가 저렇게 내부에 만들어지는건 아니고, 부모클래스로부터 확장돼서 자식클래스가 생성된다
* 상속받는 Phone객체는 한 객체를 공유하는게 아니라, 매번 새로 만들어짐 !!
(Phone객체마다 갖고있는 변수number의 값이 달라)
* 객체를 만들 때 부모객체를 항상 고려
< 실제 메모리상의 부모객체와 자식객체 연결관계 (내부에 있는게 아니라 원래 이런 모습) >
* Phone객체에는 변수,메소드랑 this, super도 있음
this(); : 자기 자신을 가리키는 주소값
super(); : 부모를 가리키는 주소값
Object : 모든 객체의 부모 객체
- p변수가 가리키는 Iphone 객채로 가서 찾아 -> 없네?
-> super가 가리키는 부모객체 SmartPhone 객체로 가서 찾아 -> 없네?
-> super가 가리키는 부모객체 Phone 객체로 가서 찾아 -> 없네?
-> super가 가리키는 부모객체 Object 객체로 가서 찾아
-> 최상위 부모객체인 Object에서도 검색되지 않으면 컴파일 오류
2-4. 클래스의 단일 상속
- 단일 상속만 허용 (부모객체를 하나만 가질 수 있음)
- 자신의 상위 클래스는 오직 하나만 허용
'수업내용 > Java' 카테고리의 다른 글
[2022.09.22.목] 강제 형변환, 메소드 재정의와 다형성 (0) | 2022.09.22 |
---|---|
[2022.09.21.수] 생성자 메소드, 클래스형변환 (0) | 2022.09.21 |
[2022.09.19.월] 클래스의 역할 분담 (0) | 2022.09.20 |
[2022.09.17.토] 숙제1 (0) | 2022.09.18 |
[2022.09.16.금] 생성자, this (0) | 2022.09.17 |