class = 멤버변수(값 저장) + 메서드(기능)
1. 생성자 (constructor)
- 역할: 객체 초기화 메서드
- 이름: 클래스와 동일
- 반환타입 없음
- 파라메터는 있을 수도 있고 없을 수도 있음. -> 있는 경우 파라메터의 타입과 개수를 맞춰 호출해야 함.
- 생성자를 작성하지 않아도 컴파일러가 자동으로 생성해줌.
but, 생성자를 하나라도 작성하면 자동생성 안됨.
- 생성자는 마음대로 호출할 수 없고 객체 생성시에만 호출 & 실행 가능하다.
(함수(메소드)는 호출할 때마다 실행)
예시1. 파라메터 없는 생성자 (디폴트 생성자)
class Member2 {
String name, tel, addr;
//생성자 작성
Member2() {
System.out.println("생성자");
name = "aaa";
tel = "1234";
addr = "대한민국";
}
}
class Member2 {
String name, tel, addr;
// 생성자
Member2() {
System.out.println("생성자");
name = "aaa";
tel = "1234";
addr = "대한민국";
}
void printData() {
System.out.println("name: " + name);
System.out.println("tel: " + tel);
System.out.println("addr: " + addr);
}
}
public class ConstructorTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Member2 m = new Member2(); //생성자 호출
m.printData();
m.name = "bbb";
m.tel = "1445";
m.addr = "캐나다";
m.printData();
}
}
=========================================
(print)
생성자
name: aaa
tel: 1234
addr: 대한민국
name: bbb
tel: 1445
addr: 캐나다
예시2. 파라메터 있는 생성자
class Member3 {
String name, tel, addr;
// 파마레터 있는 생성자 작성
Member3(String n, String t, String a) {
System.out.println("생성자");
name = n;
tel = t;
addr = a;
}
void printData() {
System.out.println("name: " + name);
System.out.println("tel: " + tel);
System.out.println("addr: " + addr);
}
}
public class ConstructorPara {
public static void main(String[] args) {
// TODO Auto-generated method stub
//생성자도 메소드이기 때문에 파라메터의 타입과 개수를 맞춰서 호출해야함
Member3 m = new Member3("aaa", "1234", "대한민국");
m.printData();
}
}
- 생성자를 만들지 않으면 컴파일러가 자동생성 해주지만 하나라도 만들면 생성이 안되기 때문에 -> error
=> 파라메터를 받는 생성자를 만들면 꼭!!!!!! 디폴트 생성자도 같이 만들어줘라.
class Member3 {
String name, tel, addr;
Member3() {
System.out.println("생성자");
name = "ggg";
tel = "4567";
addr = "캐나다";
}
Member3(String n, String t, String a) {
System.out.println("생성자");
name = n;
tel = t;
addr = a;
}
void printData() {
System.out.println("name: " + name);
System.out.println("tel: " + tel);
System.out.println("addr: " + addr);
}
}
public class ConstructorPara {
public static void main(String[] args) {
// TODO Auto-generated method stub
Member3 m = new Member3("aaa", "1234", "대한민국");
m.printData();
Member3 m2 = new Member3();
m2.printData();
}
}
======================================
(print)
생성자
name: aaa
tel: 1234
addr: 대한민국
생성자
name: ggg
tel: 4567
addr: 캐나다
2. 메서드 오버로딩
: 동일한 이름의 메서드 여러개 만들 수 있음.
- 대신 이름과 파라메터까지 완벽히 같으면 컴파일러가 어떤걸 호출할지 결정을 못내림. -> error
==> 이름이 같아도 파라메터의 개수나 타입을 다르게 만들면 됨.
- 메소드의 리턴 타입과는 상관없음!! ----- 컴파일러가 알아서 판단함.
예시1. 이름은 같지만 / 타입과 파라메터가 다름.
class Overtest1 {
int add(int a, int b) {
return a + b;
}
String add(String a, String b) {
return a + b;
}
float add(float a, float b) {
return a + b;
}
}
public class OverTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Overtest1 ot = new Overtest1();
System.out.println(ot.add(2.34f, 4.75f));
System.out.println(ot.add(3, 7));
System.out.println(ot.add("Aaa", "Bbb"));
}
}
====================================
(print)
7.09
10
AaaBbb
예시2. 타입과 이름은 같지만 / 파라메터 값이 다름.
class Buyer {
int money = 1000;
int point = 0;
// 메서드 오버로딩을 사용해서 제품 구매하는 buy 메서드 구현.
public void buy (Tv p) {
if (money >= p.price) {
money -= p.price;
point += p.point;
System.out.println(p.name + " 구매함");
System.out.println("money: " + money);
System.out.println("point: " + point);
} else {
System.out.println("잔액부족");
}
}
public void buy (Audio p) {
if (money >= p.price) {
money -= p.price;
point += p.point;
System.out.println("money: " + money);
System.out.println("point: " + point);
} else {
System.out.println("잔액부족");
}
}
}
3. this
: 현재 객체의 참조값을 갖는 참조 변수
- 클래스 내에서만 쓸 수 있음. (main에서 사용 불가)
-- 클래스 정의할 때, 즉 객체 생성 전 객체를 부르는 이름.
- 지역변수와 멤버변수의 이름이 같을 때 멤버변수를 구분하기 위해 사용.
this.멤버변수 : 현 객체의 멤버변수
this : 현재 객체의 참조값이 할당됨.
생성자를 만들지 않아도
이클립스의 Source > Generate Constructor using Fields...
자동 생성자 형성.
class Member3 {
String name, tel, addr;
Member3() {
System.out.println("생성자");
name = "ggg";
tel = "4567";
addr = "캐나다";
}
Member3(String name, String tel, String addr) {
System.out.println("생성자");
this.name = name;
this.tel = tel;
this.addr = addr;
//this.멤버변수 : 현 객체의 멤버변수
//this : 현재 객체의 참조값이 할당됨.
}
}
** super: 부모 객체의 참조값을 갖는 참조 변수
--- 오버라이딩된 메서드(자식)에서 부모 객체의 메서드(오버라이딩 전 메서드)를 호출하고 싶을 때 사용.
super.함수명: 부모 객체의 메서드 호출
super(): 부모 객체의 생성자 호출.
- 부모 클래스 생성자가 파라메터가 있는 경우 이 값을 넣어주기 위해 사용.
- 단, 생성자에서 다른 실행문보다 앞서야만 사용 가능.
@Override
public String toString() {
String str = super.toString(); // 부모 객체의 toString()호출
return id + "/" + pwd;
}
class Parent {
int a;
public Parent(int a) {
this.a = a;
}
}
class Child extends Parent {
int b;
public Child(int a, int b) { //자식클래스의 생성자에서 부모클래스의 파라메터값을 넣어줘야함.
// 부모 생성자 호출. 부모클래스 생성자가 파라메터가 있을 때 이 값을 전달하기 위해 사용.
super(a); // 함수. 생성자에서 다른 실행문보다 앞서야 사용 가능.
this.b = b;
}
}
-------------- main{}---------------
Child c = new Child(3, 6);
https://intheham.tistory.com/15
4. 메서드 오버라이드
: 상속받은 메서드(toString(): 객체를 설명하는 문자열 반환)를 고쳐 씀.
이클립스의 Source > Override/Implement Methods...
@Override
public String toString() {
// TODO Auto-generated method stub
return super.toString();
}
...> 값 변환
@Override
public String toString() {
// TODO Auto-generated method stub
return "grfae";
}
...........> 출력
System.out.println(m1.toString());
================
(print)
grfae
출력 대용
이클립스의 Source > Generate toString()...
@Override
public String toString() {
return "Member [name=" + name + ", tel=" + tel + ", address=" + address + "]";
}
//vo : 값 저장 클래스
public class Member {
String name, tel, address;
public Member() {
}
public Member(String name, String tel, String address) {
this.name = name;
this.tel = tel;
this.address = address;
}
//printData() 대용으로 활용
@Override
public String toString() {
return "Member [name=" + name + ", tel=" + tel + ", address=" + address + "]";
}
}
5-1. static 변수
: 정적(static) 멤버 정의
class 타입명 {
static 타입 변수명;
}
타입명.변수명 = 값;
멤버 변수 | 정적 멤버 변수 |
- heap에 할당 - 객체마다 따로 사용 - 객체 생성시 만들어짐 => 객체를 생성해야 존재 |
- static 메모리에 할당 ==> 클래스 소속 (객채소속X) - 이 클래스를 만든 모든 객체들이 공유함. - 프로그램 시작시 만들어짐 => 객체 유무와 상관없이 존재 -- 객체 생성하지 않아도 사용 가능 - 클래스이름.멤버변수 - 주로 상수 정의할 때 사용 ------- 5-2. final final static int MAX = 100; // read-only |
- 일반 메서드 -- static 멤버변수 사용 가능 -- static 메서드 호출 가능 |
- static 메서드 -- 일반 멤버변수 사용 불가 -- 일반 메서드 호출 불가 |
정적 멤버 (println,Math..) |
static | ||
배열, 객체 (new ...) |
heap | 주소로만 접근 가능 (객체 이름(4B)에 주소값에 해당하는 참조값 매칭) |
자동 초기화 O |
메서드, 지역변수 (: 클래스 안의 함수) (main() ...) |
stack | 변수 이름으로 접근 가능 (변수 이름 == 주소) |
자동 초기화 X (이전에 실행된 내용이 지워지지 않고 쓰레기 값으로 남아있음 |
수학 수식 관련 변수는 static 변수로 system에 있음 >> class 생성 없이 사용 가능.
상수 >> 대문자 >> static
변수 >> 소문자
System.out.println("PI: " + Math.PI);
System.out.println("Math.abs(-13): " + Math.abs(-13));
System.out.println("Math.ceil(3.4): " + Math.ceil(3.4));
System.out.println("Math.sin(45): " + Math.sin(45));
System.out.println("Math.log(1): " + Math.log(1));
=============================================
(print)
PI: 3.141592653589793
Math.abs(-13): 13
Math.ceil(3.4): 4.0
Math.sin(45): 0.8509035245341184
Math.log(1): 0.0
class Test {
int a; // 일반 멤버 변수 --> 객체 소속
static int b; //static 변수 --> 클래스 소속 --- static 메모리에 1개만 만들어짐.
}
---------------------main
Test t1 = new Test();
Test t2 = new Test();
Test t3 = new Test();
// heap에 Test 객체 3개 만들어짐. 단, b 빼고 a만 가짐.
t1.a = 1;
t2.a = 2;
t3.a = 3;
Test.b = 30; //클래스 이름으로 사용.
b++ 예시
class MyStatic {
int a; //heap에 저장. 객체마다 따로 사용. 객체 생성시 만들어짐.
static int b; //static 메모리에 저장. 모든 객체가 공용. 프로그램 시작시 만들어짐.
}
public class StaticMemberTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyStatic ms1 = new MyStatic();
ms1.a++;
ms1.b++;
System.out.println("ms1.a: " + ms1.a);
System.out.println("ms1.b: " + ms1.b);
MyStatic ms2 = new MyStatic();
ms2.a++;
ms2.b++;
System.out.println("ms2.a: " + ms2.a);
System.out.println("ms2.b: " + ms2.b);
MyStatic ms3 = new MyStatic();
ms3.a++;
ms3.b++;
System.out.println("ms3.a: " + ms3.a);
System.out.println("ms3.b: " + ms3.b);
}
}
==================================
(print)
ms1.a: 1
ms1.b: 1
ms2.a: 1
ms2.b: 2
ms3.a: 1
ms3.b: 3
↓
class MyStatic {
int a; //heap에 저장. 객체마다 따로 사용. 객체 생성시 만들어짐.
static int b; //static 메모리에 저장. 모든 객체가 공용. 프로그램 시작시 만들어짐.
}
public class StaticMemberTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
//static 멤버 변수는 객체 유무와 상관없이 존재
System.out.println("b: " + MyStatic.b);
//일반 멤버변수는 객체를 생성해야 존재
//System.out.println("a: " + MyStatic.a);
MyStatic ms1 = new MyStatic();
ms1.a++;
//ms1.b++;
System.out.println("ms1.a: " + ms1.a);
System.out.println("ms1.b: " + MyStatic.b);
MyStatic ms2 = new MyStatic();
ms2.a++;
//ms2.b++;
System.out.println("ms2.a: " + ms2.a);
System.out.println("ms2.b: " + MyStatic.b);
MyStatic ms3 = new MyStatic();
ms3.a++;
//ms3.b++;
System.out.println("ms3.a: " + ms3.a);
System.out.println("ms3.b: " + MyStatic.b);
}
}
==============================
(print)
b: 0
ms1.a: 1
ms1.b: 0
ms2.a: 1
ms2.b: 0
ms3.a: 1
ms3.b: 0
Q1. 객체가 생성될 때마다 "몇번째 객체 생성됨" 메시지 출력
class Massage {
static int cnt;
Massage() {
cnt++;
System.out.println(cnt + " 번째 객체가 생성됨");
}
}
public class StaticAssign {
public static void main(String[] args) {
// TODO Auto-generated method stub
for (int i = 0; i < 5; i++) {
new Massage();
}
}
}
===================================
(print)
1 번째 객체가 생성됨
2 번째 객체가 생성됨
3 번째 객체가 생성됨
4 번째 객체가 생성됨
5 번째 객체가 생성됨
5-1. static 메서드
- 클래스 소속이기 때문에 "클래스.메서드()" 로 호출함.
- 객체 생성 없이 사용 가능.
- 일반 메서드에서는 static 멤버변수 사용이 가능하지만, --------- 이미 static 멤버변수가 생성된 뒤라서.
static 메서드에서 일반 멤버변수 사용 불가. -------------- 일반멤버변수가 없을 수도 있음.
- 일반 메서드에서 static 메서드 호출 가능,
static 메서드에서 일반 메서드 사용 불가. ----------- 객체 생성 전에 이 메서드를 호출할 수도 있기 때문.
class StaticMethod {
int a;
static int b;
void f1() {
System.out.println("일반 메서드. f1()");
// 일반 메서드는 일반 멤버변수, static 변수 모두 사용 가능.
System.out.println("a: " + a);
System.out.println("b: " + b);
}
static void f2() {
System.out.println("static 메서드. f2()");
// static 메서드는 일반 멤버변수 사용불가, static 변수는 사용 가능.
// System.out.println("a: " + a); // error: 객체 생성 전에 호출할 수도 있어서.
System.out.println("b: " + b);
}
void f3() {
f1(); // 일반 메서드
f2(); // static 메서드
}
static void f4() {
// f1(); // static 메서드에서 일반 메서드 호출 불가
f2(); // static 메서드
}
}
public class StaticMethodTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("객체 생성 전");
System.out.println("static 멤버 변수만 사용 가능");
StaticMethod.f2();
StaticMethod.f4();
System.out.println(StaticMethod.b);
System.out.println("객체 생성 후");
System.out.println("일반 멤버, static 멤버 변수 모두 사용 가능");
StaticMethod sm = new StaticMethod();
System.out.println(sm.a);
System.out.println(StaticMethod.b);
sm.f1();
StaticMethod.f2();
sm.f3();
StaticMethod.f4();
}
}
5-2. final 키워드
>> 고치는 것을 막음. 확장X, 수정X
final 변수: 상수 (초기값 할당받은 값만 사용가능. 값 변경 불가) >> 생성시 꼭 초기화까지 함께!! (이후에는 값 넣을 곳이 없음)
final 메서드: 메서드 오버라이드 (값 수정) 불가
final 클래스: 상속 불가
상수 -- 대문자 -- static
변수 -- 소문자
public class MathTest {
final static int MAX=100;
public static void main(String[] args) {
// TODO Auto-generated method stub
//상수는 값 변경 불가
// MathTest.MAX = 200; //error!
System.out.println("MAX: " + MathTest.MAX);
}
}
===================================
(print)
MAX: 100
* 초기화 블럭
: 멤버변수 초기화
-- 상수를 정의할 때 초기화(값 할당)를 하지 않았을 때 -- 초기화 블럭에서 할 수 있음.
class Test {
int a;
static int b;
// 일반 초기화 블럭
{
a = 10;
}
// static 초기화 블럭
static {
b = 20;
}
}
public class 상수테스트 {
//상수 정의
final static int X; //상수
//static 초기화 블럭
static {
X = 10;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("X: " + 상수테스트.X);
}
}
============================
(print)
X: 10
멤버변수 초기화 과정 예시
** 멤버 변수가 초기값이 할당되는 순서 ----- 순서대로 값 할당됨
1. 기본값 자동 할당 (숫자타입(0), 객체타입(null), boolean타입(false))
2. 멤버 변수 선언시 할당한 값
3. 초기화 블럭에서 할당한 값
4. 생성자에서 할당한 값
class InitTest {
int a = 1;
static int b = 2;
// 일반 초기화 블럭
{
System.out.println("초기화 블럭에서 변경 전 a: " + a);
a = 10;
}
// static 초기화 블럭
static {
System.out.println("초기화 블럭에서 변경 전 b: " + b);
b = 20;
}
// 생성자
InitTest() {
System.out.println("생성자에서 변경 전 a: " + a + " / b: " + b);
a = 100;
b = 200;
}
}
public class 멤버변수초기화 {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("main 객체 생성 전");
System.out.println("b: " + InitTest.b);
InitTest it = new InitTest();
System.out.println("main 객체 생성 후");
System.out.println("a: " + it.a);
System.out.println("b: " + InitTest.b);
}
}
========================================
(print)
main 객체 생성 전
초기화 블럭에서 변경 전 b: 2
b: 20
초기화 블럭에서 변경 전 a: 1
생성자에서 변경 전 a: 10 / b: 20
main 객체 생성 후
a: 100
b: 200