클래스 멤버 변수 vs 인스턴스(객체) 멤버 변수
public class Person {
//클래스 멤버 변수
static String org = "jiwon";
//인스턴스 멤버 변수
String name;
int age;
boolean isHungry;
void eat() {
System.out.println("냠냠");
isHungry = false;
}
void work() {
System.out.println("열심히..");
isHungry = true;
}
}
public class PersonTest {
public static void main(String[] args) {
//지금 11줄에서 객체를 만드는 과정이 있기 전에 클래스 멤버 변수를 수정한 것임
//
Person.org = "asdf";
// TODO Auto-generated method stub
Person p = new Person();
//이게 지금 같은 패키지 안에 있으니까 다른 파일이어도 이렇게 참조가 가능한건가?
p.name = "이지원";
p.age = 26;
p.isHungry = true;
p.eat();
p.work();
//클래스 멤버 변수는 객체의 것이 아니라 클래스의 것이니까 Person.org로 접근하는 것이 옳다
System.out.println(p.org);
System.out.println(Person.org);
}
}
JAVA 문법
[modifier] class Class이름 [extends SuperClass implement Interface, interface...]{
[modifier] type memberVariable[=초기값]
[modifier] Class이름([argumentList]){초기화;}
[modifier] returnType memberMethod(argumenList){
localVariable;
구현;
객체지향의 특징
1. Abstraction(추상화)
복잡한 현실세계를 사용자 요구에 맞게 단순화 시키는 것
요구사항만 뽑아서 똑같은 대상이라도 요구사항에 따라 다르게 정의 가능
● Class : Object의 template(Type) - attribute(variable), operation(method)
● Instanciate : Class type의 new 생성자()를 이용해 메모리 공간 확보하여 데이터 활용 기회 제공
● Object : Class Type에 의해 instance화 된 유일한 변수
object.memberVariable = 값;
object.memberMethod()
* 더 자세히 보기
** 추상클래스(Abstract Class)
1. 추상메소드를 하나이상 가진 클래스.
2. 형식
접근제어자 abstract class ClassName {
변수;(instance변수, class변수)
메소드
- 구현메소드
접근제어자 RT mN([args]) {
logic
}
- 추상메소드
접근제어자 abstract RT mN([args]);
}
ex)
public void xxx(){} >> 추상메소드 X
public abstract void xxx(); >> 추상메소드 O
3. 추상클래스는 자신의 생성자를 이용하여 객체 생성 불가능. >> A a = new A(); >> X
4. 추상클래스는 하위 클래스를 제어하기 위해 사용. (B extends A)
>> 추상클래스를 상속받는 하위 클래스는 반드시 추상 메소드를 override해야한다.
5. 추상클래스의 객체 생성
5-1. 하위클래스를 참조(다형성)
A a = new B();
Calendar cal = new GregorianCalendar();
5-2. 자신의 객체를 return하는 static method 사용
Calendar cal = Calendar.getInstance();
5-3. 외부 클래스 사용.
Runtime rt = Runtime.getRuntime();
Process p = rt.exec("");
5-4. 자신의 생성자로 객체 생성.(dynamic 객체 생성)
A a = new A(){
추상메소드 override
};
2. Encapsulation(은닉화)
구현은 감추고 사용법 제공
사용자 - 사용법만 알면 구현 변경시에도 재사용
public class member {
private String id;
private String pw;
private int age;
//getter
public String getId() {
return id;
}
public String getPw() {
return pw;
}
public int getAge() {
return age;
}
//setter
public void setId(String id) {
this.id = id;
}
public void setPw(String pw) {
this.pw = pw;
}
public void setAge(int age) {
this.age = age;
}
}
위의 예제는 일반적으로 회원관리시 회원정보를 캡슐화하여 회원정보를 은닉하여 보안을 높이는 효과가 있다.
member 클래스의 모든 변수는 private으로 접근제어자 선언을 해놓았기 때문에 member 클래스 내부에서만 접근이 하다.
==> 지금 이 자체로 보안성 강화
접근을 위해 setter와 getter 라는 장치를 만들어 내부에서 접근가능하다.
==> 근데 set,get 행동을 한다는거 자체가 보안을 높이는 행동이라고 볼 수 있을까?
==> 애초에 변수에게 접근을 해버리면 무슨일을 할지 모르지만 set,get 정도의 기능을 개발자가 풀어준 것임!
Access Modifier(접근제한자)
접근제한자 | 같은 Class | 같은 package | 상속관계 다른package |
다른 package |
private | O | X | X | X |
default(생략) | O | O | X | X |
protected | O | O | O | X |
public | O | O | O | O |
Usage Modifier
Class | Member Variable | Member Method | |
static | X (Nested Class예외) | Class이름.varialbe | Class이름.method() |
final | 상속금지 | 값 변경 금지(상수) | Overried 금지 |
abstract | 객체생성 금지 | X | 구현 금지( |
static
Class Load시 단 한번 초기화
Class Load => static 초기화 => main 호출 => non_static new 할때마다 초기화
즉, main에서 new로 따로 만들지 않아도 사용 가능하다는 점
public class StaticTest {
public static void main(String[] args) {
System.out.println("main method called...");
}
static {
System.out.println("static block called...");
}
}
main도 똑같이 static 붙었는데 왜 저거 먼저 실행 되지 않을까?
=> static이라고 설정했다는 것 자체가 main이 실행되기 전에 먼저 초기화 시켜놓자라는 의미로 쓰이는 것이기 때문에
main보다 먼저 실행되는게 맞음
static이 있다고 바로 메모리에 적재 되는건 아님
그 클래스가 호출되야 불러지는 것
참조 | 피참조 | 같은 클래스(객체 없이 참조) | 다른 클래스(객체 생성 참조) |
static | static | O | Class이름.member |
non-static | X (객체생성 참조) | O | |
non-static | static | O | Class이름.member |
non-static | O | O |
public class StaticTest {
public static void main(String[] args) {
StaticClass sc = new StaticClass();
sc.nonStaticM();//static->nonstatic
sc.staticM(); //static 참조는 객체없이 클래스 이름으로 참조 가능
StaticClass.staticM();//static->static
System.out.println("main method called...");
}
//다른 클래스
public void nonStaticM() {
StaticClass sc = new StaticClass();
sc.nonStaticM(); //nonstatic->nonstatic
StaticClass.staticM(); //nonstatic->static
}
//Class load -> static 초기화 -> main호출
//-> nonstatic new 할때마다 초기화
static {//main도 static 써있는데?
System.out.println("static block called...");
}
}
class StaticClass{
//같은 클래스 참조 : 기본 - 객체생성하지 않고 참조
public int nonStaticV = 10;
public static int staticV=10;
public int nonStaticM() {
//nonstatic -> nonstatic 참조
//return nonstaticV
return staticV; //nonstatic -> static 참조
}
public static int staticM() {
//static -> static 참조
//return staticV;
//return nonStaticV; //static -> nonstatic 참조(Error)
return new StaticClass().nonStaticV;
//이런식으로 써야됨, 얘 입장에서 보면 지금 새로 new를 해서 만든게 아니기때문에 구현자체에서 new를 만들어서 return해줘야됨
}
}
static -> nonstatic일 때 return new StaticClass().nonStaticV;
생각해보면 당연한 말임
why?)
그냥 인스턴스 멤버변수는 클래스가 new해야 nonstatic애들이 만들어지는데 new하지도 않았는데 nonstatic을 쓰려고 하니 니까 문제가 생기는게 맞음
final
변경될 수 없는, 상수
abstract
이거 쓰는 이유가 뭐임? => Type, Frame만 제공하려고!
abstract class를 선언했으면 그 안에 있는 Method도 모두 abstract해야됨
ex) Animal이 Dog, Pig 2개를 자식클래스를 가지고 있는데 Animal은 굳이 객체생성을 가능하게끔 안해도 됨
그냥 Type만, Frame만 제공하려고 쓰지않나? ==> 이럴 때 abstract 쓰는 것임
* Interface
극단적으로 동일한 목적 하에 동일한 기능을 수행하게끔 강제하는 것
자바의 다형성을 극대화하여 개발코드 수정을 줄이고 프로그램 유지보수성을 높이기 위해
프로그램이 끝나도 Standard(기준)을 유지하고 싶을 때 사용
API자체를 구현할 때 Interface 이거 써서 하겠지??? API 개발하고 계속 쓰니깡
Example
교수님이 학생들에게 논문을 쓰라고 했다.
A학생은 PPT로 논문을 11일날 제출했다.
B학생은 EXCEL 2016 로 논문을 12일날 제출했다.
C학생은 EXCEL 2019 로 자기만의 색깔을 입혀 표 형식으로 12일날 제출했다.
D학생은 메모장에 '논문'을 쓰고 교수님이 말해준 당일 바로 제출했다.
응?? 논문을 쓰라고 지시했지만, 결과물이 너무 개성이 넘친다....이건 평가할 수 없을 것 같다.
왜 이런일이 일어날까?
가이드 라인 또는 어떠한 규격이 없기 때문에 발생하는 문제이다.
따라서 교수는 다시 명확한 가이드라인 있는 논문을 쓰라고 지시해야한다. 아래처럼...
[interface]
학생들에게 2019.12.12일 18:00까지 홈페이지 본인 교수 홈페이지 제출란을 통해 논문을 제출해야하고
논문 파일 형식은 .PPT이며 10Page 안에 작성을 해야하고
논문 주제는 '블록체인을 활용한 공인인증서' 이다.
public class InterfaceTest {
public static void main(String args[]) {
//Interface o = new Interface(); cannot instanticate
}
}
//interface : public static final variable
// publicabstract method
//객체 생성금지 - 표준사용법 정의 구현한 자식객체로 객체 생성
interface Interface{
int FINAL_V=100; //public static final int FINAL_V=100;
void fun(); //public void fun();
}
//interface->interface : extends
interface Interface2 extends Interface{
void fun2();
}
interface Interface3{
void fun3();
}
//일반class : 상속받은 interface abstract method override
// class -> interface상속 : implements
//다중상속은 안되지만 다중 implements는 가능
class InterfaceImp1 implements Interface2, Interface3{
@Override
public void fun() {
}
//Interface2를 implements해도 Interface2는 Interface가 부모클래스니까
//부모클래스의 fun()도 오버라이딩 해줘야됨
@Override
public void fun2() {
}
@Override
public void fun3() {
}
}
* 생성자
객체를 생성시(new) 초기화를 시키기 위한 용도
this : 참조 변수로써 객체 자신을 가리킴
(In 상속)자식의 생성자를 호출하게 되면 부모의 생성자 먼저 호출하게 된다.
public Super() {
System.out.println("Super Constuctor");
}
public Super(int superVariable) {
this.superVariable = superVariable;
}
처음에 생성자를 생성하지 않으면 묵시적으로 아무것도 없는 생성자가 생성되긴한다.
하지만 2번째처럼 파라미터가 있는 생성자를 만들게 되면 Super()처럼 default 생성자는 만들어지지 않는데
이를 따로 만들지 않으면 "파라미터 없는 객체를 생성하려고 하면 만들지 않겠다" 라는 의미가 되어버리기 때문에
따로 필요에 따라 만들어야됨
(In 상속) 자식클래스에서 default생성자로 초기화하려고 했는데 부모클래스에 default생성자가 없으면 오류
this : 자기 클래스 참조변수
super : 상위 클래스 참조변수
//아래의 2가지는 생성자의 첫줄에서만 호출 가능.
this() : 자기 클래스 생성자 호출
super() : 상위 클래스 생성자 호출
3. Inheritance(상속)
부모클래스(SuperClass)로 부터 변수와 메소드 상속
즉, 자식클래스는 부모클래스의 변수와 메소드 사용가능
생성자는 상속에서 제외 : 호출(묵시적 - super(), 명시적-첫라인 super(args))
다중 상속 지원x
모든 클래스의 상위 클래스가 Object 클래스
public class FinalTest {
public static void main(String[] args) {
Super superObject = new Super();
//superObject.FINAL_V = 20; 상수니까 바꿀 수 없음
System.out.println(superObject.finalM());
Super subObject = new Sub();
System.out.println(subObject.finalM());
}
}
class Super{
final int FINAL_V = 100;
public int finalM() {
return FINAL_V;
}
}
class Sub extends Super{
@Override
public int finalM() {
return 10;
}
}
100
10
자식클래스로 만든 subObject에 대해서 finalM()은 똑같은 Method가 Override 되었기 때문에 자식클래스 Method사용
* @Override annotation
1. 자식 클래스에 여러 개의 메서드가 정의가 되어 있을 경우 명시적으로 Override 했다고 편하게 보기위해
2. 컴파일러에게 문법 체크를 하도록 알린다(바로 빨간줄 떠서 알려주더라)
컴파일러, JVM, 프레임워크 등이 보는 주석
package inheritance;
public class inheritanceTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Sub subObject = new Sub();
subObject.subVariable = 100;
subObject.superVariable = 100;
}
}
class Super{
int superVariable;
//
public Super() {
System.out.println("Super Constuctor");
}
public Super(int superVariable) {
this.superVariable = superVariable;
}
public int superMethod() {
return superVariable;
}
}
//상속 : 부모의 variable, method 상속 받아서 자식의 객체에서 참조
// 생성자는 상속되지 않아서 호출해서 사용 : 묵시적 super(), 명시적 첫라인 super(args)
class Sub extends Super{
int subVariable;
//자식 클래스는 변수,메소드 부모꺼 쓸 수 있는데 생성자는 상속이 안되서 문제가 생김
public Sub(int superVariable, int subVariable) {
super(superVariable); // 명시적. 첫라인
this.subVariable = subVariable;
}
}
4. Polymorphism(다형성)
상속을 전제
Object는 모든 객체의 부모클래스
심지어 기본형도 담을 수 있음(Wrapper Class)
1. Animal myAnimal = new Pig(); //부모타입의 자식생성자
2. Pig myPig = new Animal(); //자식타입의 부모생성자
3. Dog myDog = new Pig(); //자식타입의 자식생성자
생성자는 초기화를 위해 사용하는 것이다.
1번을 보면 Animal variable를 가져야한다. pig는 자식이기 때문에 Animal variable을 메모리에 적재 가능
따라서, 1번 가능
2번은 Pig는 부모로 Animal을 가지고있으니까 Animal variable,pig variable 2개를 가져야하는데 new Animal하면 Animal variable만 가지고 있어서 안됨
3번은 Dog는 부모로 Animal을 가지고 있으니까 Animal variable, dog variable 2개를 가져야하는데 new Pig하면 Animal variable만 가지고 있어서 안됨
즉, 부모타입의 자식 생성자만 가능
Animal myAnimal = new Animal(); // Create a Animal object
Animal myPig = new Pig(); // Create a Pig object
Animal myDog = new Dog(); // Create a Dog object
Animal myAnimal = new pig();
((pig)myAnimal).varible = 10;
((dog)myAnimal).variable = 10; //ClassCastingException
Polymorphism of Method()
부모 타입의 Method name, return type, argumentList가 동일하고 구현만 다르게 재구현한 경우 자식의 override한 메소드가 응답
Animal o = new Pig()
o.animalMethod() //override한 pig의 pigMethod()응답
if Pig Method()에서
pigMethod() : int //override
pigMethod(int i) : int //overloading
@Override annotation : override 규칙 체크
Animal myAnimal = new Animal(); // Create a Animal object
Animal myPig = new Pig(); // Create a Pig object
Animal myDog = new Dog(); // Create a Dog object
myAnimal.animalSound();
myPig.animalSound();
myDog.animalSound();
The animal makes a sound
The pig says: wee wee
The dog says: bow wow
instanceof 연산자
어떤 타입의 대한 instanceof 연산의 결과가 true라는 것은 검사한 타입으로 형변환이 가능하다는 것을 뜻한다.
Person person = new Person();
//person은 jiwon을 상속하고 있냐? 라는 뜻
person instanceof jiwon
//무조껀 o
Object o instanceof 자손 인스턴스
* annotation
@Deprecated
컴파일러에게 해당 메서드가 deprecated 되었다고 알려줌
@Override
컴파일러에게 해당 메서드는 override한 메서드임을 알려줌
반드시 super class에 선언 되어있는 메서드이어야함
@SuppressWarning
컴파일러에게 사소한 warning의 경우 신경 쓰지 말라고 알려줌'
SingleTon Class
객체의 인스턴스가 오직 1개만 생성되는 패턴을 의미
여러 개의 객체가 필요없어서 1개만 생성을 막아둠
객체를 계속 생성/삭제 하는데 많은 비용이 들어서 재사용이 유리한 경우
class SingletonClass{
//객체를 1개만 내부에서 만들었으니까 Singleton 성공
private static SingletonClass sc = new SingletonClass();
// public으로 해버리면 외부에서 객체 생성을 할 수 있기 때문에 Singleton 하지 않음
private SingletonClass() {}
//static으로 해야 내부에서 1개를 만들자마자 바로 메모리에 올라가니까!
public static SingletonClass getSingleTonClass() {
return sc;
}
public void sayHello() {
System.out.println("Hello");
}
}
public class SingletonTest {
public static void main(String[] args) {
SingletonClass sc = SingletonClass.getSingleTonClass();
sc.sayHello();
SingletonClass sc1 = SingletonClass.getSingleTonClass();
sc1.sayHello();
}
}
'Backend > Java' 카테고리의 다른 글
[JUnit] JUnit에 대해 (0) | 2023.04.28 |
---|---|
[JAVA] Origin 서버가 대상 리소스를 위한 현재의 representation을 찾지 못했거나, 그것이 존재하는지를 밝히려 하지 않습니다. (1) | 2022.09.21 |
Cookie & Session (0) | 2022.09.20 |
JSP Programming (0) | 2022.09.16 |
Servlet Programming (0) | 2022.09.16 |