접근제어자: public / protected / default / private | |||
static | 클래스 초기화 블럭{} | 메서드 | 멤버변수 |
final | 클래스: 조상이 될 수 없는 제일 마지막 | 메서드: 오버라이딩x, 재정의x | 멤버변수, 지역변수: 상수 |
abstract | 클래스: 추상클래스 선언 | 메서드: 추상메서드이다 |
static (정적 제한자)
- 변수, 메서드에 적용되는 자바의 키워드 (생성자에는 사용 X)
- 해당 클래스의 객체 없이도 참조 가능
static 붙으면 (new를 안 붙여도) 메모리에 알아서 생성해서 만들어줌 → 직접 1개 만들어줌(이건 고정) - 인스턴스 변수 = 멤버변수를 안쓸 때 붙음
- static { } (static 메서드, 정적 초기화자) 안에는 static 변수만 사용, static 메서드만 호출 가능
즉 static 블록에서 non-static 멤버를 객체 생성 없이 직접 참조할 수 없음 - static 제한자는 this를 가질 수 없음 (지정된 변수와 메서드를 객체와 무관하게 만들어주기 때문)
- non-static 메서드로 재정의(Overriding) 될 수 없음
method override도 static의 개념으로 들어가야함 / 따로 따로 별개다 - 대표적인 static 메서드는 애플리케이션의 main() 메서드입니다. / 어떤 클래스에 있던지 상관 x
static initializer (정적 초기화자)
- static에 단순히 블록({ })을 사용한 경우
- static 변수를 초기화하는 역할, 클래스가 로딩될 때 main() 메서드가 있더라도 그보다 앞서 딱 한 번 실행
- 일반변수를 사용하지 않고, 범용성있게 사용할 메서드는 static을 붙이면 좋음
[암기 필수] static이 갖는 의미
1. static멤버는 객체 생성 없이 클래스명.이름 으로 참조 가능하다
2. static변수는 객체간 값의 공유의 의미
3. static메서드는 같은 static멤버만 참조가능하다. 클래스명.이름 으로 참조
static 변수
- class에서 값을 공유하는 변수가 됨 ex) 계산기의 pi
- 객체 1000개를 만들어도 a값은 같음 - (객체 생성 없이) 클래스 이름만으로 참조가 가능
static 메서드
- 클래스의 객체 생성 없이도 참조가 가능
- 주의해야 할 사항
static 메서드에서는 static 메서드를 바로 사용 가능 (끼리끼리 논다)
static 메서드 안에서는 non-static(일반) 멤버를 객체 생성 없이 직접 참조할 수 없음
static 메서드 호출했어도 객체가 생성되었다는 보장이 없으므로 객체 생성없이 일반 멤버 변수 사용 불가
static initializer (정적 초기화자) - 쓸일 없음
- static {
반드시 한번만 실행되어야 할 로직
} - 딱 1번 사용
Singleton Design Pattern (싱글톤 패턴) - 수정
자동으로 해 줌
- 어떤 클래스의 객체는 오직 하나임을 보장, 이 객체에 접근할 수 있는 전역적인 접촉점을 제공하는 패턴
- 클래스 객체를 유일하게 하나만 생성하여 모든 곳에서 하나의 객체에 접근하게 하여, 전역의 개념으로 객체 사용 가능
- 객체의 생성을 제한하기 위해 사용 (자바를 이용한 프로그래밍에서 사용됨)
final
- 클래스, 메서드, 변수에 적용, abstract와 동시에 사용될 수 없음
- final 클래스: 상속 X = 서브클래스를 가질 수 없음
- final 메서드: 재정의(overriding) X
- final 변수: 값을 변경 X
- 접근제어자 다음에 위치
final 클래스
- 클래스 선언 시 final을 사용하면 그 클래스는 상속 불가능
- 자식 클래스를 가질 수 없고, 오직 외부에서 객체 생성을 통해서만 사용 가능
- 대표 예시 - String 클래스 / 사용자가 임의로 String 클래스를 상속받아 메서드를 재정의하는 것을 방지
final 메서드
- 자식 클래스에서 부모 클래스의 메서드를 재정의(오버라이딩)하지 못하게 함
- 클래스에 final 붙지 않는 한 상속은 가능 = 자식 클래스에서 final 메서드의 참조는 가능
- 자식 클래스에서 반드시 부모의 메서드를 기능의 변경없이 사용하도록 강요할 경우에 final 메서드를 선언
final 변수
- 값을 할당하면 그 값을 변경할 수 없음
- 선언시에 초기화 or 생성자를 통하여 초기화해야 함
static final (상수)
- 상수(constant): 불변의 값을 저장하는 필드
- 객체마다 저장할 필요가 없는 공용성 有
여러가지 값으로 초기화될 수 없기 때문에 static과 final 제한자를 동시에 붙여 선언합 - 상수 이름은 모두 대문자로 작성하는 것이 관례입니다. 연결된 단어라면 (_)로 단어들을 연결
ex) public static final long VERSION = 1L
final은 변수의 값이 변하지 않고
static은 새로운 메모리에 할당하지 않고 한 메모리에 계속 재사용하겠다
(public/private) static final TYPE NAME = VALUE;
TYPE: 변수의 타입
NAME: 보통 대문자와 _로 구성
VALUE: 상수 값
참고로 변수는 final로 선언되면 값을 바꿀수없지만, 객체의 경우 다른 객체를 가리킬수 없는거지 값은 바뀔수 있음
예를 들어
public static final Point ORIGIN = new Point(0,0);
public static void main(String[] args){
ORIGIN.x = 3;
}
이경우 ORIGIN.x=3은 정상적으로 동작해서 point의 값을 (3,0)이 됨 - 출처: #ashcode
abstract (추상)
↔ final
abstract 클래스
- 메서드들의 이름을 통일한 목적
- new 키워드 사용 불가 = 객체 못 만듦
- 상속을 통해서만 자식 클래스로 구체화 = 다형성 사용
- 일반클래스와 마찬가지로 멤버변수, 생성자, 메서드를 선언
- new를 사용하여 직접 생성자를 호출할 수는 없지만,
자식 객체가 생성될 때 super()를 호출하여 추상 클래스 객체를 생성하므로 추상 클래스도 생성자가 반드시 필요
abstract 메서드 = { }가 없는 메서드
- 반드시 추상 클래스가 있어야 함, 반드시 그 안에서만 선언
- 자식클래스가 반드시 실행 내용을 채우도록 강요 (= 오버라이딩을 하도록 하는 경우)하고 싶은 메서드가 있을 때 선언
- 자식클래스에서 반드시 추상메서드를 재정의하여 실행 내용을 작성해야 함
abstract가 갖는 의미
1. 굳이 abstract클래스로 설계할 필요는 없다 → 많이 보이지 않는다
2. 많은 클래스는 abstract클래스로 정의 되어있음을 알아둬야 한다 → 인식할 수 있으면 ok
3. 자식 클래스로 생성해서 부모클래스(추상클래스)에 저장하는 점에 익숙해지자
예제
day09.abs.good
추상화된 메서드 확인 후 자식클래스에서 완성하기
main
package day09.abs.good;
public class MainClass {
public static void main(String[] args) {
// 1. 추상클래스는 객체 생성이 안됩니다.
// 반드시 자식으로 구체화합니다.
// Store s = new SeoulStore(); // 자식으로 생성해서 추상클래스 타입에 저장해도 결과는 똑같음
Store s = new BusanStore(); // new SeoulStore();
s.apple();
s.melon();
s.orange();
System.out.println(s.getName()); // 상속받은
}
}
-----------------결과------------------
추상클래스 생성자 호출
부산사과 500원
부산멜론 600원
부산오렌지 700원
호식이네
Quiz13
Shape에 연결된 Circle, Rect 이용하여 추상메서드 완성하고 넓이 구하기
Shape / 부모클래스 / 추상클래스 + 추상메서드
package quiz13;
public abstract class Shape { // 부모클래스
private String name;
public Shape(String name) { // 생성자 필수
this.name = name;
}
//오버라이딩을 강제화 한다면 추상메서드로 선언
public abstract double getArea();
//오버라이딩을 강제화 하지않는다면 일반메서드로 선언
public String getName() {
return "도형이름:" + name;
}
}
Circle / 자식클래스 / 추상메서드 완성하기
package quiz13;
public class Circle extends Shape {
private static final int PI = 0;
//원은 생성될 때 이름과, 반지름의 길이를 받도록 처리하고,
//getArea()는 원의 넓이를 계산하도록 오버라이딩 처리
//main에서 확인
private int radius;
public Circle(String name, int radius) {
super(name);
this.radius = radius;
}
public double getArea() {
return radius * radius * Math.PI; // Math.PI - 파이값
}
}
Rect / 자식클래스 / 추상메서드 완성하기
package quiz13;
public class Rect extends Shape{
//사각형은 생성될 때 이름과, 변의 길이를 받도록 처리하고,
//getArea()는 사각형의 넓이를 계산하도록 오버라이딩 처리
//main에서 확인
private int side;
public Rect(String name, int side) {
super(name);
this.side = side;
}
public double getArea() {
return side * side;
}
}
main
package quiz13;
public class MainClass {
public static void main(String[] args) {
Shape s = new Circle("동그라미", 10);
System.out.println(s.getName()); // 상속
System.out.println(s.getArea()); // 오버라이딩
Shape s1 = new Rect("네모", 10);
System.out.println(s1.getName());
System.out.println(s1.getArea());
}
}
Quiz14
부모클래스 Unit을 만들고 추상메서드를 선언해라
Unit / 부모클래스 / 추상메서드
- 멤버변수 정해줄 때 int x = 0; 이렇게 하지 말고, int x만 쓰면 기본값인 0이 저장됨
- int hp는 자식클래스에 모두 있으나 값이 다르니까 여기에서 매개변수를 넣게 생성하고, this.hp = hp로 저장
자식클래스에서 꺼낼때는 super() 부모생성자 빌려오는 키워드 사용해서 매개변수 넣어주면 됨
package quiz14;
public abstract class Unit { // 부모클래스
public int x; // 기본값 = 0
public int y;
public int hp;
public Unit() {}
public Unit(int hp) { // 생성자(각각 다름)
this.hp = hp;
}
public abstract void location(); // 추상메서드
public abstract void move(int x, int y);
public abstract void stop();
}
Marine / 자식클래스 / 추상메서드 완성하기 / 본인의 static변수 가지고 있음
- attack, armor의 경우 객체마다 같은 값을 갖도록 하려면 static으로 선언해줌
static area에 위치하게 되며 같은 값을 공유하게 됨
메인에서 호출시 sysout하고, 클래스명.이름(Marine.attak / Marine.armor)으로 호출하면 됨
package quiz14;
public class Marine extends Unit {
public static int attack = 6; // 객체마다 같은 값을 갖도록 static
public static int armor =0; // static멤버 가져올 때 클래스명.이름
public Marine() { // hp 생성자 부모한테 상속받아서 super()로 빌려쓰기
super(40);
}
public void location() {
System.out.println("현재 위치: " + x + ", " + y);
}
public void move(int x, int y) {
this.x = x;
this.y = y;
System.out.println("움직인 위치: " + x + ", " + y);
}
public void stop() {
System.out.println("정지");
}
}
tank / 자식클래스 / 추상메서드 완성하기 / 본인의 changeMode 메서드 있음
- 특별한 기능으로 mode 변경을 해줌
단순히 끄고, 켜는 기능이라 boolean타입으로 진행
if(mode) { mdoe = false} else { mode = true};
조건 = mode가 true이면 false 넣어주고, false이면 true 넣어줌
package quiz14;
public class tank extends Unit{
private boolean mode;
public tank() {
super(100);
}
public void location() {
System.out.println("현재 위치: " + x + ", " + y);
}
public void move(int x, int y) {
this.x = x;
this.y = y;
System.out.println("움직인 위치: " + x + ", " + y);
}
public void stop() {
System.out.println("정지");
}
// 특별한 기능 - mode 변경 (true → false, false → true)
public void changeMode() {
if(mode) {
mode = false;
} else {
mode = true;
}
System.out.println("공격모드 변경");
}
}
DropShip / 자식클래스 / 추상메서드 완성하기
package quiz14;
public class DropShip extends Unit {
public DropShip() { // 안에 int hp 생략가능
super(150);
}
public void location() {
System.out.println("현재 위치: " + x + ", " + y);
}
public void move(int x, int y) {
this.x = x;
this.y = y;
System.out.println("움직인 위치: " + x + ", " + y);
}
public void stop() {
System.out.println("정지");
}
}
mian
package quiz14;
public class MainClass {
public static void main(String[] args) {
// Marine m = new Marine();
// m.move(10,20);
// m.location(); 아래와 같음
// System.out.println( Marine.armor); static 변수 불러올 때
// System.out.println( Marine.attack);
Unit u = new Marine();
u.location();
u.move(10, 20);
u.stop();
Unit u1 = new tank();
tank t = new tank();
u1.location();
u1.move(10, 30);
u1.stop();
t.changeMode();
Unit u2 = new DropShip();
u2.location();
u2.move(10, 40);
u2.stop();
}
}
오늘 하루
기억에 남는 부분
- static 정적 제한자는 인스턴스 변수 = 멤버변수를 안 쓸 때 붙인다는 점
- static은 객체 없이도 참조 가능하고, 이걸 붙이면 메모리가 알아서 1개 생성해줌! class 밖에 어딘가에 생성
어려운 부분
- final이 한번만 저장되는 것은 알겠는데 어디에 써야 좋을지 모르겠고, static final도 완벽하게 이해는 못함
- static을 어디에 붙여야 할지 대략적으로만 알고, 아직 익숙하지 않음
- singletone design pattern : 그냥 잘 모르겠어요^^..
- 정적초기화 (잘 안 쓴다고는 하는데 실행할 때 딱 한번 호출된다고 하면 되나?) 기억에 잘 안남을 듯
문제 해결 부분
- quiz13: abstract 사용하는 이유와 사용방법을 알고 문제를 품, but 거기에 집중한 결과 기본 메서드는 사용할 생각을 안했음
'프로그래밍 언어 > Java' 카테고리의 다른 글
[Java] 예외 처리 (try ~ catch ~ finally), throws & throw (0) | 2022.10.17 |
---|---|
[Java] interface (0) | 2022.10.14 |
[Java] 키워드 this & super, 접근제한자(public, private) (0) | 2022.10.07 |
[Java] overriding(재정의), overloading(중복) (0) | 2022.10.07 |
[Java] Garbage Collecting, package(패키지), 데이터타입, 객체지향 프로그래밍 기술(상속, 은닉, 다형성) (0) | 2022.10.06 |