클래스 (Class)
클래스란 객체를 정의해놓은 것으로 객체를 생성하는데 사용된다.
객체와 인스턴스 (Instance)
정의
클래스로부터 만들어진 객체를 그 클래스의 인스턴스라고 한다.
클래스 | 인스턴스화 | 인스턴스 (객체) |
--------------------------------------> |
객체는 속성 (property) 과 기능 (function)으로 이루어져 있고 이를 그 객체의 멤버 (member) 라고 한다.
속성 - 멤버 변수(member variable), 특성(attribute), 필드(field), 상태(state)
기능 - 메서드(method), 함수(function), 행위(behavior)
* 멤버변수 (클래스변수, 인스턴스변수)
생성과 사용
클래스명 변수명; // 클래스의 객체를 참조하기 위한 참조변수 선언
변수명 = new 클래스명; // 클래스의 객체를 생성 후, 객체의 주소를 참조변수에 저장
Tv t;
t = new Tv();
인스턴스는 참조변수를 통해서만 다룰 수 있다.
객체 배열
참조변수들을 하나로 묶은 참조변수 배열
Tv tv1, tv2, tv3;
Tv[] tvArr = new Tv[3];
객체 배열을 생성하는 것은
객체를 다루기 위한 참조 변수들이 만드는 것일 뿐이라 초기화를 시켜주어야 한다.
// 객체 배열 선언
Tv[] tvArr = new Tv[3];
// 초기화 1번째 방법
TvArr[0] = new Tv();
TvArr[1] = new Tv();
TvArr[2] = new Tv();
// 초기화 2번째 방법
Tv[] tvArr = { new Tv(), new Tv(), new Tv() };
// 초기화 3번째 방법
Tv[] tvArr = new Tv[3];
for(int i=0; i<tvAtt.length; i++){
tvArr[i] = new Tv();
}
변수와 메서드
변수의 종류
1. 인스턴스 변수 (instance variable)
- 클래스 영역에 선언되며, 클래스의 인스턴스를 생성할 때 만들어진다.
- 인스턴스마다 고유한 상태를 유지해야하는 경우, 선언한다.
- 인스턴스가 생성되었을 때 생성된다.
2. 클래스 변수 (class variable)
- 인스턴스 변수 앞에 static 을 붙이는 것으로 선언한다.
- 한 클래스의 모든 인스턴스들이 공통적인 값을 유지해야하는 속성의 경우, 선언한다.
- 인스턴스를 생성하지 않고 '클래스이름.클래스변수' 의 형식으로 언제든지 바로 사용할 수 있다.
- 클래스가 메모리에 올라갈 때 생성된다.
클래스 변수는 모든 인스턴스가 하나의 저장공간을 공유하므로, 항상 공통된 값을 갖는다.
'인스턴스.클래스변수' 로도 표현 가능하지만 '클래스이름.클래스변수' 를 권장한다.
멤버 변수 (클래스 변수, 인스턴스 변수) 는 초기화 시켜주지 않아도 자동적으로 타입형의 기본값으로 초기화된다.
3. 지역 변수 (local variable)
- 메서드 내에 선언되어 메서드 내에서만 사용 가능하다.
class Variables{
int iv; // 인스턴스 변수
static int cv; // 클래스 변수
void method(){
int lv = 0; // 지역 변수
}
}
메서드 (Method)
특정 작업을 수행하는 일련의 문장들을 하나로 묶은 것.
반환타입 메서드이름 (매개변수 ...){ // 선언부
메서드 호출시 수행될 코드 // 구현부
}
기본형 매개변수와 참조형 매개변수
기본형 매개변수 (primitive type) : 변수의 값을 읽기만 할 수 있다.
참조형 매개변수 (reference type) : 변수의 값을 읽고 변경할 수 있다.
class Data{
int x;
}
public class Main {
public static void main(String[] args){
Data d = new Data();
d.x = 10;
System.out.println("Before : " + d.x);
notChanged(d.x);
System.out.println("Not changed result : " + d.x);
changed(d);
System.out.println("Changed result : " + d.x);
}
static void notChanged(int x){ // 기본형 매개변수 (primitive)
x = 1000;
System.out.println("Not changed : " + x);
}
static void changed(Data d){ // 참조형 매개변수 (reference)
d.x = 1000;
System.out.println("Changed : " + d.x);
}
}
참조형 반환타입
class Data {
int x;
}
public class Main {
public static void main(String[] args) {
Data d = new Data();
d.x = 10;
Data d2 = copy(d);
System.out.println("d.x = "+d.x);
System.out.println("d2.x = "+d2.x);
}
static Data copy(Data d){
Data tmp = new Data();
tmp.x = d.x;
return tmp;
}
}
반환타입이 참조형 이라는 것은 메서드가 객체의 주소를 반환한다는 것을 의미한다.
클래스 메서드, 인스턴스 메서드
- 클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통적으로 사용해야하는 것에 static 을 붙인다.
- 클래스 변수는 인스턴스를 생성하지 않아도 사용할 수 있다.
- 클래스 메서드는 인스턴스 변수를 사용할 수 없다. (인스턴스 변수, 메서드에서는 static 이 붙은 멤버들을 사용할 수 있다.)
- 메서드 내에서 인스턴스 변수를 사용하지 않는다면 static 을 붙이는 것을 권장한다.
class MyMath{
long a, b;
long add(){
return a+b;
}
// 매개변수만으로 작업이 가능, a, b = 지역변수
static long add(long a, long b){
return a+b;
}
}
public class Main {
public static void main(String[] args) {
// 인스턴스 생성 없이 클래스 메서드 호출
System.out.println(MyMath.add(200L, 100L));
// 객체 생성 후, 인스턴스 메서드 호출
MyMath mm = new MyMath();
mm.a = 200L;
mm.b = 100L;
System.out.println(mm.add());
}
}
call c = new call();
int result = c.instanceMethod();
// 한 줄로 가능
int result = new call().instanceMethod();
// 하지만 참조변수를 선언하지 않았기 때문에 생성된 call 인스턴스는 재사용 불가
오버로딩 (Overloading)
한 클래스 내에 같은 이름의 메서드를 여러 개 정의하는 것
조건
1. 메서드 이름이 같아야 한다.
2. 매개변수의 개수, 타입이 달라야 한다. (반환 타입은 영향 x)
int add(int a, int b);
int add(int x, int y); // 성립 x
int add(long a, long b); // 성립 o
long add(int a, int b); // 성립 x
가변 인자 (varargs / variable arguments)
- '타입... 변수명' 의 형식으로 선언
- 매개변수 중에서 가장 마지막에 선언해야 한다.
- 인자의 개수를 가변적으로 할 수 있다. (아예 없어도 되고 배열도 가능)
String str(String s1, String s2, String s3 ...){ ... }
// 가변 인자 사용
String str(String... str) { ... }
매개변수를 가변 인자가 아닌 배열 (String[] str) 로 하는 것과의 차이 :
반드시 인자를 지정해 줘야하기 때문에 null 이나 길이가 0인 배열을 인자로 지정해줘야 한다.
가능한 가변 인자를 사용한 메서드는 오버로딩하지 않는다. (메서드가 구분되지 않아 컴파일 에러 발생)
생성자 (Constructor)
인스턴스가 생성될 때 호출되는 인스턴스 초기화 메서드 이다.
( ≒ 메서드)
- 생성자의 이름은 클래스의 이름과 같아야 한다.
- 클래스 내에 선언된다.
- 모든 생성자는 리턴값이 없다.
- 오버로딩이 가능하여 한 클래스 안에 여러 개의 생성자 존재 가능하다.
class Card{
Card(){ // 매개변수가 없는 생성자
}
Card(String k, int num){ // 매개변수가 있는 생성자
}
}
기본 생성자 (Default Constructor)
- 클래스에 생성자가 하나도 정의되지 않은 경우 생성되는 기본 생성자
class Data1{
int value;
}
class Data2{
int value;
Data2(int x){
value = x;
}
}
public class Main {
public static void main(String[] args) {
Data1 d1 = new Data1();
Data2 d2 = new Data2(); // 컴파일 에러
}
}
Data2 클래스에는 Data2(int x) 라는 생성자가 정의되어 있어 기본 생성자가 자동으로 추가되지 않았다.
해결방법
1. Data2 d2 = new Data2(10); 으로 인스턴스 생성
2. Data2 클래스에 Data2() 생성자 정의
매개변수가 있는 생성자
Car c = new Car();
c.color = "white";
c.gearType = "auto";
c.door = 4;
// 한 번에 초기화 가능
Car c = new Car("white", "auto", 4);
this(), this
this | this() |
인스턴스 자신을 가리키는 참조 변수 (인스턴스의 주소가 저장되어 있다.) |
생성자 |
모든 인스턴스 메서드에 지역 변수로 숨겨진 채 존재한다. | 같은 클래스의 다른 생성자를 호출할 때 사용한다. |
- 생성자의 이름으로 클래스이름 대신 this 를 사용한다.
- 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능하다.
class Car{
String color;
String gearType;
int door;
Car(){
this("white", "auto", 4);
}
Car(String color){
this(color, "auto", 4);
}
Car(String color, String gearType, int door){
this.color = color;
this.gearType = gearType;
this.door = door;
}
}
class Main {
public static void main(String[] args) {
Car c1 = new Car();
Car c2 = new Car("blue");
}
}
인스턴스 복사
class Car{
String color;
String gearType;
int door;
Car(){
this("white", "auto", 4);
}
// 인스턴스 복사
Car(Car c){
this(c.color, c.gearType, c.door);
// color = c.color;
// gearType = c.gearType;
// door = c.door;
}
}
class Main {
public static void main(String[] args) {
Car c1 = new Car();
Car c3 = new Car(c1);
System.out.println(c1.color + c1.gearType + c1.door);
System.out.println(c3.color + c3.gearType + c3.door);
}
}
인스턴스 복사가 진행되엇지만 서로 독립적인 메모리 공간에 존재하는 별도의 인스턴스이므로 c1 의 값이 변경되어도 c3 의 값이 변경되진 않는다.
변수의 초기화
멤버 변수 (클래스 변수, 인스턴스 변수) | 초기화 선택적, 초기화 안할 시 자동적으로 타입형의 기본값으로 초기화 됨 |
지역변수 | 초기화 필수적 |
멤버 변수의 초기화 방법
명시적 초기화 (Explicit Initialization)
변수를 선언과 동시에 초기화하는 것
class Car{
int door = 4; // 기본형 변수 초기화
Engine e = new Engine(); // 참조형 변수 초기화
}
생성자
초기화 블럭 (Initialization Block)
복잡한 초기화 작업이 필요할 때 초기화 하는 방법
class InitBlock{
static {
// 클래스 초기화 블럭
}
{
// 인스턴스 초기화 블럭
}
}
1. 클래스 초기화 블럭
- 메모리에 처음 로딩될 때 한 번만 수행
2. 인스턴스 초기화 블럭
- 인스턴스를 생성할 때 마다 수행
- 생성자보다 인스턴스 초기화 블럭이 먼저 수행
인스턴스 변수의 초기화는 주로 생성자를 사용하고,
인스턴스 초기화 블럭은 모든 생성자에서 공통으로 수행돼야 하는 코드를 넣는데 사용된다.
class Car{
String color;
String gearType;
int count;
int serialNo = count;
// 인스턴스 초기화 블럭
// 중복된 인스턴스 초기화 코드를 넣어준다.
{
count++;
serialNo = count;
}
Car(){
// count++;
// serialNo = count;
color = "white";
gearType = "Auto";
}
Car(String color, String gearType){
// count++;
// serialNo = count;
this.color = color;
this.gearType = gearType;
}
}
실행 순서
class BlockTest{
static{
System.out.println("static {}");
}
{
System.out.println("{ }");
}
public BlockTest(){
System.out.println("생성자");
}
public static void main(String[] args) {
System.out.println("BlockTest bt = new BlockTest(); ");
BlockTest bt = new BlockTest();
System.out.println("BlockTest bt2 = new BlockTest); ");
BlockTest bt2 = new BlockTest();
}
}
// 출력 결과
// static {}
// BlockTest bt = new BlockTest();
// { }
// 생성자
// BlockTest bt2 = new BlockTest);
// { }
// 생성자
1. BlockTest 가 메모리에 로딩될 때, 클래스 초기화 블럭이 가장 먼저 수행된다.
2. main 메서드가 수행된다.
3. BlockTest 인스턴스 bt 가 생기면서 인스턴스 초기화 블럭이 실행되고 그 다음에 생성자가 수행된다.
4. 그 다음 bt2 인스턴스가 생성되면서 반복된다.
class InitTest{
static int cv = 1;
int iv = 1;
static { cv = 2; }
{ iv = 2; }
InitTest(){
iv = 2;
}
public static void main(String[] args) {
new InitTest();
}
}
클래스 초기화 | 인스턴스 초기화 | |||||
기본값 | 명시적 초기화 | 클래스 초기화블럭 | 기본값 | 명시적 초기화 | 인스턴스 초기화블럭 | 생성자 |
cv = 0 | cv = 1 | cv = 2 | cv = 2 | cv = 2 | cv = 2 | cv = 2 |
iv = 0 | iv = 1 | iv = 2 | iv = 3 | |||
1 | 2 | 3 | 4 | 5 | 6 | 7 |
클래스 변수 초기화 : 클래스가 처음 메모리에 로딩될 때 차례대로 수행됨
인스턴스 변수 초기화 : 인스턴스를 생설할 때 차례대로 수행됨
클래스 변수는 항상 인스턴스 변수보다 항상 먼저 생성되고 초기화 된다.
( 참고 서적 : Java의 정석 )
'개발 ━━━━━ > Java' 카테고리의 다른 글
[Java/Algorithm] List 오름차순 (0) | 2023.08.24 |
---|---|
[Java] 객체 지향 - 상속, 오버라이딩 (0) | 2023.08.24 |
[Java] 기초 문법 - 컬렉션 (Collection) (0) | 2023.08.16 |
[Java] 기초 문법 - 배열 (0) | 2023.08.16 |
[Java] Input 값 입력 받는 방법 ① - Scanner 클래스 (0) | 2023.08.16 |