인스턴스 멤버
Car myCar = new Car();
객체를 불러내는 것이지만, 주 목적은 클라스 안에 있는 멤버를 쓰기 위함이다. 이러한 것들은 인스턴스 멤버라고 한다.
생성자는 인스턴스 멤버가 아님 . 그냥 객체를 만들때 쓰는 코드임 !
정적멤버 (static)
객체 생성 없이 쓸 수 있는 멤버
클래스에 소속된 멤버로 객체 내부에 존재하지 않고 메소드 영역에 존재한다.
정적 멤버는 객체를 생성하지 않고 클래스로 바로 접근해서 사용한다.
생성자는 정적멤버가 아님 ... 그냥 객체를 만들기 위해 쓰는 것
public String color; //인스턴스 필드 , 객체 각각 다른 값을 가지고 싶음
public static double pi = 3.14159; // 정적필드 : 값을 고정시키고 싶음, 모든 객체가 공유
//인스턴스 메서드멤버: 정사각형의 넓이 구하는 메서드 , 객체를 생성할 때마다 사용됨
public double areaRectangle(double width) {
System.out.println("double 타입 매개변수 1개 메서드");
return width * width ;
}
jvm -> 내가 만든 객체를 실행메소드 가서 인스턴스화 시킴!!
객체가 메모리에 올라가는 순서
내 소스 -> java compiler (영어소스를 바이트코드로 만들어줌) ->
jvm이 바이트 코드를 기계어로 만들어 줌 ->
CPU에 기계어로 객체가 등록되서 그 객체는 힙영역.스택영역에 저장된다.


JDK는 영어소스가 바이트 코드로 변환될 수 있도록 컴파일러를 가지고 있고, JRE는 JVM이 있어서 바이트코드를 기계어로 번역해주는 기능이 있다.
따라서 JDK가 있어서 개발자가 코드를 쓰고 개발할 수 있는 것이며 , JDK안에 내장되어있는 JRE로 바이트코드를 기계어로 변환해준다.
static으로 되어있는 것들은 객체로 안들어가고 그냥 공유 메모리에 들어가있는 것이다!
public String color; //인스턴스 필드 , 객체 각각 다른 값을 가지고 싶음
public static double pi = 3.14159; // 정적필드 : 값을 고정시키고 싶음, 모든 객체가 공유
//정적 메소드 : 공유 메모리 안으로 들어감 , 객체 고유한 값이 설정되지 않음 .
//모두 같은 값을 가지고 있음
public static int plus(int x,int y){
return x+y;
}
//인스턴스 메서드멤버: 정사각형의 넓이 구하는 메서드 , 객체를 생성할 때마다 사용됨
public double areaRectangle(double width) {
System.out.println("double 타입 매개변수 1개 메서드");
System.out.println("계산기의 색깔: "+this.color);
return width * width ;
}
여기서 static이 안들어간 것은 객체 안에 들어가지만 , static 이 들어있는 것은 공유 메모리 안에 들어간다.
Calcualator 객체
public class Calculator {
public Calculator(String color){
this.color = color;
}
//인스턴스 필드:객체의 고유한 값
public String color;
// 정적(static)필드 : 값을 고정시키고 싶음, 모든 객체가 공유
public static double pi = 3.14159;
//정적 메소드 : 공유 메모리 안으로 들어감 , 객체 고유한 값이 사용되지 않음 !!
public static int plus(int x,int y){
return x+y;
}
//인스턴스 메서드멤버: 정사각형의 넓이 구하는 메서드 , 객체를 생성할 때마다 사용됨
public double areaRectangle(double width) {
return width * width ;
}
}
실행메소드
Calculator myCalcu = new Calculator("빨간색");
Calculator yourCalcu = new Calculator("흰색");
//인스턴스 멤버 사용
System.out.println("나의 계산기 색깔: "+myCalcu.color); // 빨간색
System.out.println("나의 사각형 면적: "+myCalcu.areaRectangle(10)); // 100.0
System.out.println("너의 계산기 색깔: " + yourCalcu.color); // 흰색
System.out.println("너의 사각형 면적: "+yourCalcu.areaRectangle(20)); // 400.0
//정적 멤버 사용
System.out.println("나의 pi: "+Calculator.pi);
System.out.println("너의 pi: "+Calculator.pi); //둘다 3.14159
//변수 멤버를 이용하여 정적멤버를 가져올 수도 있다.
System.out.println(myCalcu.pi);
System.out.println(yourCalcu.pi); // 3.14159
하지만 변수 이름으로 정적멤버를 가져오려고 하면 ,
The static field Calculator.pi should be accessed in a static way
이런 경고가 뜬다. 따라서 클라스 이름.정적멤버 로 불러야한다. !
정적필드 특징 또는 주의점
Calculator myCalcu = new Calculator("빨간색");
Calculator yourCalcu = new Calculator("흰색");
myCalcu.pi= 3.14;
System.out.println(myCalcu.pi);
System.out.println(yourCalcu.pi); // 3.14
myCalcu 의 pi만 3.14로 변형된 줄 알았는데 yourCalcu의 객체의 변수값도 바끰
이는 !!! 객체 안에는 정적(static)멤버가 없고, 공유 메모리 쪽에 있기 때문에 동시에 변형된다.
정적멤버를 쓰는 것은 대표적으로 Math 클래스를 들 수 있다
Math의 경우 new Math()로 쓰지않고 바로 Math.random()같은걸 사용했다.
즉, 데이터나 메소드가 공유메모리에 있는 static멤버들이기 때문에 굳이 new 객체로 생성해서 쓸 필요가 없다.
반면에 String의 경우 , new String으로 사용할수 있는데, 이는 안의 필드 멤버들이 static이 아니라 인스턴스 멤버들이기 때문이다.
정적필드는 공유메모리에 들어가기 때문에 생성자를 따로 설정해줄 필요가 없다.
public Calculator(String color){
this.color = color; // 에러는 안나지만 , 쓸필요 없다고 표시가 나옴
}
//정적 필드
public static String color;
공유 메모리에 있기때문에 this를 할필요도 없다.
public static double pi = 3.14159;
public double areaCircle(double radius) {
return radius * radius* this.pi ; // 에러는 안나지만 this 할필요없다고 표시남
}
하지만 메소드 자체를 static 멤버로 설정해주면 this에 에러가 간다.
public static double areaCircle(double radius) {
return radius * radius* this.pi ; // 메소드 자체가 공유메모리에 들어가서 에러 .
}
static메소드에서 필드를 사용할 때는 반드시 공유메모리에 있는 static 멤버의 필드만 사용 가능하다.
https://docs.oracle.com/javase/8/docs/api/
Java Platform SE 8
docs.oracle.com
System.out.println 을 생각해보자
System.out.println 도 그냥 가져와서 쓸 수 있는 이유는 공유메모리에 저장되어있기 때문이다,.
public class System{
public static PrintStream out;
}
out의 타입은 PrintStream 임 . 이 PrintStream의 메소드 중의 하나가 println인거임
public String nation; 이걸 가져와서 쓸 때
nation.charAt() 을 쓸 수 있는 것이랑 같은 것임. 왜냐하면 nation의 타입은 String이기 때문에 String객체의 메소드를 사용할 수 있는 것임
설명
- out (type : PrintStream )
The "standard" output stream. This stream is already open and ready to accept output data. Typically this stream corresponds to display output or another output destination specified by the host environment or user.See Also:PrintStream.println(), PrintStream.println(boolean), PrintStream.println(char), PrintStream.println(char[]), PrintStream.println(double), PrintStream.println(float), PrintStream.println(int), PrintStream.println(long), PrintStream.println(java.lang.Object), PrintStream.println(java.lang.String)
For simple stand-alone Java applications, a typical way to write a line of output data is:
System.out.println(data)
See the println methods in class PrintStream.
- public static final PrintStream out
PrintStream은 static이며, 얘가 가지고 있는 메소드는 여러개가 있다 !
따라서 객체 생성없이 System.out.println() 을 마음대로 사용하는 것이다.
정적 메소드에는 , 인스턴스 필드를 사용할 수 없다.
public String color; // 인스턴스
public static double areaCircle(double radius) {
System.out.println(color);
//에러 : Cannot make a static reference to the non-static field color
return radius * radius*pi ;
}
static 을 설정하는 경우
public class Television {
//240p Television.java 작성
public static String company = "전자회사"; //정적필드
public static String model = "LCD"; //정적필드
public static String info ; //정적필드
public int size ; //인스턴스 멤버
public Television(String company, String model, String info, int size) {
Television.company = company ;
Television.model = model ;
Television.info = info ;
//Television.size = size ;//오류: size 는 인스턴스 맴버이므로 클래스이름.필드이름 형식을 사용할 수 없습니다.
this.size = size ;
}
//정적 필드를 생성자를 통해서 초기화 시킬 수 있지만, 정적 필드의 값을 객체가 가지고 있지 않으므로
//객체의 고유성이 확보되지 않음
//따라서, 정적필드는 생성자를 통해서는 초기화하지 않습니다.
public Television(int size) {
if (size < 0) {
this.size = 24 ;
} else {
this.size = size ;
}
}
//사용자가 원하는 초기값이 지정되지 않은 static 필드에 초기값을 대입하려는 경우,
//정적 필드는 생성자를 통해 초기화하는 대신 static { } 을 사용합니다
//static { } 블록에는 정적 맴버들만 기술될 수 있습니다.
static {
if (Television.info == null ) {
Television.info = Television.company + "-" + Television.model ;
//인스턴스 멤버는 static { } 블록에서 사용할 수 없습니다.
//this.size = 24 ; //오류
//Television.size = 24 ; //오류
} else if(Television.info.equals("")) {
info = model + "-" + company ;
} else {
info = "전 LG 텔레비젼인데요...." ;
}
}
static {
//필요한 경우, 2개 이상의 static 블록을 아래에 나열하면 됩니다.
}
}
public class TelevisionExample {
public static void main(String[] args) {
System.out.println("Television.info: " + Television.info);
System.out.println();
//showMyMessage() ; //오류정적 메서드의 { }에서 같은 클래스의 인스턴스 메서드를 호출할 수 없습니다.
//Cannot make a static reference to the non-static method showMyMessage()
//from the type TelevisionExample
showYourMessage();
}
public void showMyMessage() {
System.out.println("나는 인스턴스 멤버 메서드 입니다.");
}
public static void showYourMessage() {
System.out.println("나는 인스턴스 멤버 메서드 입니다.");
}
}
Television.info: 전자회사-LCD
나는 인스턴스 멤버 메서드 입니다.
final 은 변수값이 변하지 않는 것이다. 메소드에서 필드를 사용할 때 변경을 못하도록 강제함
public class Person {
public int weight; //인스턴스 필드
public static String nation; //정적(static) 필드
public final String name = "pudding"; //인스턴스 final 필드
public static final String company = "삼성자동차"; // static final 필드
}
메소드에서 name필드를 사용할 때 pudding이 항상 고정된 것이다.
만약 필드에서 정의해주지 않는 다면 , 생성자를 통해 값을 초기화 시켜준다.
public class Person {
public int weight; //인스턴스 필드
public static String nation; //정적(static) 필드
public final String name; //인스턴스 final 필드
public static final String company = "삼성자동차"; // static final 필드
public Person(String name) {
this.name = name; // 이제 처음 만든 객체의 name값이 계속 사용됨
}
}
처음에 이름 설정하고 , 그 다음부터 객체를 생성하면 , Person pudding = new Person(~~~~), name값은 절대 변하지 않음
결론 : static 은 인스턴스를 생성하지 않고도 쓸 수 있음 . 값이 모든 인스턴스에 공유됨
반면에 final 은 객체를 생성해야 쓸 수 있긴 하지만 , 값이 변할 수 없음
따라서 두개를 합쳐서 static final ! 을 만들어서 영원히 변하지 않는 필드를 만들어버림
필드에 미리 정의해둠
인스턴스 멤버 정적멤버 실행메소드 있는 클래스에서 쓸 때
public class TelevisionExample {
public static void main(String[] args) {
System.out.println("Television.info: " + Television.info);
System.out.println();
//showMyMessage() ; //오류정적 메서드의 { }에서 같은 클래스의 인스턴스 메서드를 호출할 수 없습니다.
//Cannot make a static reference to the non-static method showMyMessage()
//from the type TelevisionExample
showYourMessage();
TelevisionExample t1 = new TelevisionExample();
t1.showMyMessage();
}
public void showMyMessage() {
System.out.println("나는 인스턴스 멤버 메서드 입니다.");
}
public static void showYourMessage() {
System.out.println("나는 정적 멤버 메서드 입니다.");
}
}
static final 필드는 관례적으로 전부 대문자로 쓴다.
Math.PI
public static final int NOT_FOUND = -1000;
접근제한자 (Access Modifier)
-클래스 레벨의 접근 제한 ( public,default / package)
public : 다른 패키지에서 쓸 수 있음
default(public을 안씀): 같은 패키지에서만 쓸 수 있음
주의 ! 클래스가 public 으로 안되어있으면 , import를 하더라도 쓸 수 없음
-멤버 레벨의 접근 제한(public , (default) , private , protected)
public : 다른 패키지에서도 쓸 수 있음
default(public 을 안씀) : 같은 패키지에서만 쓸 수 있음
private: 같은 클래스에서만 쓸 수 있음 !
생성자에 private 쓰는 것이 가능하지만 절대 쓰면 안된다.
다른 곳에서 객체를 사용하는 경우가 많으니까 , 생성자를 private 으로 해놓으면 객체지향이 이루어지지 않는다.
protected: 상속받은 필드만 쓸 수 있음 , 다른 패키지에 있는 클래스에서 사용은 못하지만 , 만약 해당 필드의 클래스에서 상속받은 클래스면 쓸 수 있음
일터에서는 !
클래스는 대부분 public 씀 !
필드 선언 시에 주로 private을 사용 !
protected는 거의 사용되지 않음 (개발자가 만든 클라스들을 이용해 상속 개념을 잘 안씀,
그냥 스프링 API를 상속받아서 쓰기만 함 !)
Getter VS Setter : private 접근제한 필드 사용 !
VO , DTO : 필드만 정의되어있는 객체 , 다른 객체로 값을 보낼 때 사용
public class DepartmentVO {
private int department_id;
private String department_name;
private int manager_id;
private int location_id;
private boolean delFlag;
//디폴트 생성자
public DepartmentVO() {
}
//파라메터 생성자
public DepartmentVO(int depart_id,String departName,int manager_id,
int location_id) {
this.depart_id = depart_id;
this.departName = departName;
this.manager_id = manager_id;
this.location_id = location_id;
}
public String getDepartment_id() {
return this.department_name;
}
}
DTO 나 VO 객체를 만들 때 디폴트 생성자를 쓰는 이유는 @RequestBody를 DTO로 연결하는 과정에서 기본생성자가 존재하지 않는 다면 정상적으로 연결되지 않기 때문이다.
파라메터 생성자를 쓰는 이유는 , 객체 하나하나마다 고유한 값을 가지고 있는 객체를 만들고 싶기 때문이다. (사용자 마다 정보 다름)
private으로 설정된 필드는 다른 객체에서 바로 못씀 !
public static void main(String[] args) {
DepartmentVO myDepartmentVO = new DepartmentVO();
myDepartmentVO.변수;//에러
DepartmentVO 객체의 필드가 다 private으로 설정되어 있기 때문에 접근이 불가하다.
getter와 setter를 이용하여 값을 가져오고 수정할 수 있다.
/* getter : 필드의 값을 반환 */
public int getDepart_id() {
return this.depart_id;
}
public String getDepartName() {
return this.departName;
}
public int getManager_id() {
return this.manager_id;
}
public int getLocation_id() {
return this.location_id;
}
public boolean getDelFlag() {
return this.delFlag;
}
/* setter:값을 수정 */
public void setDepart_id(int departId) {
this.depart_id=departId;
}
public void setDepartName(String name) {
this.departName=name;
}
public void setManager_id(int id) {
this.manager_id = id;
}
public void setLocation_id(int location) {
this.location_id = location;
}
public void setDelFlag(boolean delFlag) {
this.delFlag = delFlag;
}
다른 객체에서 가져와서 쓸 때
DepartmentVO myDepartmentVO = new DepartmentVO();
myDepartmentVO.setDepartName("pudding");
System.out.println(myDepartmentVO.getDepartName());
쓰는 이유 !
private은 함부로 값을 대입하거나 , 값을 읽어오는 것을 막는 역할임
하지만 객체지향이기 때문에 getter setter를 사용하는 것이다 !
'Development (국비 복습 ) > 자바' 카테고리의 다른 글
[2023-03-30]예외처리,제네릭, (0) | 2023.03.30 |
---|---|
[2023-03-24]싱글톤,은행계좌만들기 (0) | 2023.03.24 |
[2023-03-22]인스턴스,VO,오버로딩 (0) | 2023.03.22 |
[2023-03-21]배열 중복값, (0) | 2023.03.21 |
[2023-03-20]배열복사,다차원 배열,자바 문제 (0) | 2023.03.20 |
댓글