클래스 정의하는 방법
클래스(class)란 객체 지향 프로그래밍의 추상화(abstraction)라는 개념을 직접 구현한 것이라 할 수 있다.
클래스의 선언
접근제어자 class 클래스이름 {
접근제어자 필드1의타입 필드1의이름;
접근제어자 필드2의타입 필드2의이름;
...
접근제어자 메소드1의 원형
접근제어자 메소드2의 원형
...
};
Car라는 클래스를 선언할 때는 아래와 같다.
접근 제어자(Access Modifier)
변수나 메소드의 사용 권한은 다음과 같은 접근 제어자를 사용하여 설정할수 있다.
private -> default -> protected -> public 순으로 보다 많은 접근을 허용한다.
private : private 이 붙은 변수, 메소드는 해당 클래스에서만 접근이 가능하다.
public class Sample {
private String secret;
private String getSecret() {
return this.secret;
}
}
// secret, getSecret()은 Sample class 내에서만 접근이 가능하다.
default : 접근 제어자를 별도로 설정하지 않는다면 해당 변수, 메소드는 default 접근 제어자가 되어 동일한 패키지 내에서만 접근이 가능하다.
package house; // 패키지가 동일하다.
public class HouseKim {
String lastname = "kim"; // lastname은 default 접근제어자로 설정된다.
}
package house; // 패키지가 동일하다.
public class HousePark {
String lastname = "park";
public static void main(String[] args) {
HouseKim kim = new HouseKim();
System.out.println(kim.lastname); // HouseKim 클래스의 lastname 변수를 사용할 수 있다.
}
}
protected : 동일 패키지의 클래스 또는 해당 클래스를 상속받은 다른 패키지의 클래스에서만 접근이 가능하다.
package house; // 패키지가 서로 다르다.
public class HousePark {
protected String lastname = "park";
}
package house.person; // 패키지가 서로 다르다.
import house.HousePark;
public class EungYongPark extends HousePark { // HousePark을 상속했다.
public static void main(String[] args) {
EungYongPark eyp = new EungYongPark();
System.out.println(eyp.lastname); // 상속한 클래스의 protected 변수는 접근이 가능하다.
}
}
위에서 만약 HoustPark class의 lastname이 default였다면, eyp.lastname은 에러를 발생시킨다.
public : 어떤 클래스에서라도 접근이 가능하다.
package house;
public class HousePark {
protected String lastname = "park";
public String info = "this is public message.";
}
객체 만드는 방법
인스턴스의 생성
위와 같이 선언된 클래스의 정의를 가지고 다음과 같은 순서대로 Car 객체의 인스턴스를 생성할 수 있다.
//클래스이름 객체참조변수이름;
Car myCar;
//객체참조변수이름 = new 클래스이름();
myCar = new Car();
//클래스이름 객체참조변수이름 = new 클래스이름();
Car myCar = new Car();
new란?
힙(Heap) 영역에 저장할 공간을 할당해서 참조 값을 객체에게 반환하여 주는 것 입니다.
new 연산자는 객체를 Heap이라는 메모리 영역에 메모리 공간을 할당해주고 메모리주소를 반환한 후 생성자를 실행시켜준다. 리터럴과는 달리 new 연산자로 생성된 객체는 똑같은 변수값을 가진 객체가 있어도 서로 다른 메모리를 할당하기 때문에 서로 다른 객체로 분류된다.
public class Main {
public static void main(String[] args) {
String str = new String("string");
}
}
위 코드가 실행 되면 아래 그림과 같은 과정이 발생한다.
일단 변수는 Stack 영역에 할당 될것이고, new String으로 생성된 문자열값이 Heap영역의 메모리 공간을 할당받아 str이라는 변수가 그 메모리주소를 가르키고 있을것이다. 이를 다른 말로 참조라고도 한다.
public class Main {
public static void main(String[] args) {
String str = new String("string");
String str2 = new String("string");
}
}
처음에 생성한 "string"을 가르키지 않고 Heap 메모리에 새로운 영역을 할당받아 생성한것을 볼 수 있다.
public class Main {
public static void main(String[] args) {
String str = new String("string");
String str2 = new String("string");
System.out.println(System.identityHashCode(str)); //result:2008362258
System.out.println(System.identityHashCode(str2)); //result:760563749
//메모리주소는 컴퓨터마다 다르기때문에 실행결과가 다르게 나올수도 있다.
}
}
위 코드의 결과로 str과 str2는 같은 값을 가지지만, 메모리를 참조하는 값이 다름을 볼 수 있다.
public class Main {
public static void main(String[] args) {
String str = "string";
String str2 = "string";
System.out.println(System.identityHashCode(str)); //result:2008362258
System.out.println(System.identityHashCode(str2)); //result:2008362258
}
}
클래스의 new 키워드를 이용한 메모리 참조로 만들어진 변수와 달리 리터럴 변수의 경우에는 같은 주소값을 갖는다.
정리하자면 new 연산자는 객체를 생성할 때 사용하고 Heap이라는 메모리 영역에 각각의 새로운 메모리 공간을 할당해주는 역할을 한다.
메소드 정의하는 방법
메소드란?
어떠한 문제를 처리하기 위한 방법을 소스 코드로 묶어놓고 필요(호출)에 따라 동작하는 기능 정도로 생각할 수 있다.(다른 언어에서는 함수(function)으로 불린다.)
접근제어자 반환타입 메소드이름(매개변수목록) { // 선언부
// 구현부
}
1. 접근 제어자 : 해당 메소드에 접근할 수 있는 범위를 명시한다.
2. 반환 타입(return type) : 메소드가 모든 작업을 마치고 반환하는 데이터의 타입을 명시한다.
3. 메소드 이름 : 메소드를 호출하기 위한 이름을 명시한다.
4. 매개변수 목록(parameters) : 메소드 호출 시에 전달되는 인수의 값을 저장할 변수들을 명시한다.
5. 구현부 : 메소드의 고유 기능을 수행하는 명령문의 집합이다.
(참고) 메소드 시그니처(method signature)란 메소드의 선언부에 명시되는 매개변수의 리스트를 가리킨다.
만약 두 메소드가 매개변수의 개수와 타입, 그 순서까지 모두 같다면, 이 두 메소드의 시그니처는 같다고 할 수 있다.
class Car {
private int currentSpeed;
private int accelerationTime;
...
public void accelerate(int speed, int second) { // 선언부
// 구현부
System.out.println(second + "초간 속도를 시속 " + speed + "(으)로 가속함!!");
}
...
}
위 코드에서는 accelerate() 메소드를 정의하고 있다.
이 메소드는 public 접근 제어자를 사용하여 선언되어 해당 객체를 사용하는 프로그램 어디에서나 직접 접근할 수 있다.
반환 타입에는 어떠한 값도 반환하지 않는다는 의미를 가진 void를 명시한다.
그 다음으로 메소드의 이름을 명시하고, 매개변수로 int형 변수인 speed와 second를 전달받는다.
이렇게 전달받은 매개변수를 가지고 메소드 구현부에서 고유한 작업을 수행할 수 있는 있다.
메소드의 호출
메소드는 멤버 참조 연산자(.)를 사용하여 호출할 수 있다.
1. 객체참조변수이름.메소드이름(); // 매개변수가 없는 메소드의 호출
2. 객체참조변수이름.메소드이름(인수1, 인수2, ...); // 매개변수가 있는 메소드의 호출
Car myCar = new Car(); // 객체를 생성함.
myCar.accelerate(60, 3); // myCar 인스턴스의 accelerate() 메소드를 호출함.
생성자 정의하는 방법
생성자란?
클래스를 가지고 객체를 생성하면, 해당 객체는 메모리에 즉시 생성된다.
하지만 이렇게 생성된 객체는 모든 인스턴스 변수가 아직 초기화되지 않은 상태이다.
자바에서 클래스 변수와 인스턴스 변수는 별도로 초기화하지 않으면, 다음 값으로 자동 초기화된다.
변수의 타입 | 초깃값 |
char | '\u0000' |
byte, short, int | 0 |
long | 0L |
float | 0.0F |
double | 0.0 또는 0.00 |
boolean | false |
배열, 인스턴스 등 | null |
사용자가 원하는 값으로 인스턴스 변수를 초기화하려면, 일반적인 초기화 방식으로는 초기화할 수 없다.
인스턴스 변수 중에는 private 변수도 있으며, 이러한 private 변수에는 사용자나 프로그램이 직접 접근할 수 없기 때문이다.
따라서 private 인스턴스 변수에도 접근할 수 있는 초기화만을 위한 public 메소드가 필요해진다.
이러한 초기화만을 위한 메소드는 객체가 생성된 후부터 사용되기 전까지 반드시 인스턴스 변수의 초기화를 위해 호출되어야 한다.
생성자(constructor)
자바에서는 객체의 생성과 동시에 인스턴스 변수를 원하는 값으로 초기화할 수 있는 생성자(constructor)라는 메소드를 제공한다.
자바에서 생성자(constructor)의 이름은 해당 클래스의 이름과 같아야 한다.
즉, Car 클래스의 생성자의 이름은 Car가 됩니다.
생성자의 특징
1. 생성자는 반환값이 없지만, 반환 타입을 void형으로 선언하지 않는다.
2. 생성자는 초기화를 위한 데이터를 인수로 전달받을 수 있다.
3. 객체를 초기화하는 방법이 여러 개 존재할 경우에는 하나의 클래스가 여러 개의 생성자를 가질 수 있다.
즉, 생성자도 하나의 메소드이므로, 메소드 오버로딩이 가능하다.
Car(String modelName) {}
Car(String modelName, int modelYear) {}
Car(String modelName, int modelYear, String color) {}
Car(String modelName, int modelYear, String color, int maxSpeeds) {}
생성자의 선언
1. 클래스이름() { ... } // 매개변수가 없는 생성자 선언
2. 클래스이름(인수1, 인수2, ...) { ... } // 매개변수가 있는 생성자 선언
Car(String modelName, int modelYear, String color, int maxSpeeds) {
this.modelName = modelName;
this.modelYear = modelYear;
this.color = color;
this.maxSpeed = maxSpeed;
this.currentSpeed = 0;
}
생성자의 호출
자바에서는 new 키워드를 사용하여 객체를 생성할 때 자동으로 생성자가 호출됩니다.
class Car {
private String modelName;
private int modelYear;
private String color;
private int maxSpeed;
private int currentSpeed;
Car(String modelName, int modelYear, String color, int maxSpeed) {
this.modelName = modelName;
this.modelYear = modelYear;
this.color = color;
this.maxSpeed = maxSpeed;
this.currentSpeed = 0;
}
public String getModel() {
return this.modelYear + "년식 " + this.modelName + " " + this.color;
}
}
public class Method02 {
public static void main(String[] args) {
Car myCar = new Car("아반떼", 2016, "흰색", 200); // 생성자의 호출
System.out.println(myCar.getModel()); // 생성자에 의해 초기화되었는지를 확인함.
}
}
//실행 결과 : 2016년식 아반떼 흰색
기본 생성자(default constructor)
자바의 모든 클래스에는 하나 이상의 생성자가 정의되어 있어야 한다.
하지만 특별히 생성자를 정의하지 않고도 인스턴스를 생성할 수 있다.
이것은 자바 컴파일러가 기본 생성자(default constructor)라는 것을 기본적으로 제공해 주기 때문이다.
기본 생성자는 매개변수를 하나도 가지지 않으며, 아무런 명령어도 포함하고 있지 않다.
//클래스이름() {}]
Car() {}
class Car {
private String modelName = "소나타";
private int modelYear = 2016;
private String color = "파란색";
public String getModel() {
return this.modelYear + "년식 " + this.color + " " + this.modelName;
}
}
public class Method03 {
public static void main(String[] args) {
Car myCar = new Car(); // 기본 생성자의 호출
System.out.println(myCar.getModel()); // 2016년식 파란색 소나타
}
}
//실행 결과 : 2016년식 파란색 소나타
하지만 기본 생성자는 아무런 동작도 하지 않으므로, 인스턴스 변수를 클래스 필드에서 바로 초기화하고 있다.
이처럼 인스턴스 변수의 초기화는 생성자를 사용하여 수행할 수도 있지만, 클래스 필드에서 바로 수행할 수도 있다.
하지만 만약 매개변수를 가지는 생성자를 하나라도 정의했다면, 기본 생성자는 자동으로 추가되지 않는다.
따라서 매개변수를 가지는 생성자를 하나 이상 정의한 후 기본 생성자를 호출하면, 오류가 발생할 수 있다.
class Car {
private String modelName;
private int modelYear;
private String color;
private int maxSpeed;
private int currentSpeed;
① Car(String modelName, int modelYear, String color, int maxSpeed) {
this.modelName = modelName;
this.modelYear = modelYear;
this.color = color;
this.maxSpeed = maxSpeed;
this.currentSpeed = 0;
}
public String getModel() {
return this.modelYear + "년식 " + this.modelName + " " + this.color;
}
}
public class Method04 {
public static void main(String[] args) {
② Car myCar = new Car(); // 기본 생성자의 호출
③ // Car myCar = new Car("아반떼", 2016, "흰색", 200); // 생성자의 호출
System.out.println(myCar.getModel()); // 생성자에 의해 초기화되었는지를 확인함.
}
}
위의 예제는 ①번 라인에서 4개의 매개변수를 갖는 생성자를 정의하고 있다.
따라서 자바 컴파일러는 Car 클래스에 별도의 기본 생성자를 추가하지 않는다.
하지만 ②번 라인에서는 기본 생성자를 호출하여 인스턴스를 생성하려고 하고 있다.
따라서 자바 컴파일러는 오류를 발생시킬 것이며, ③번 라인과 같이 4개의 매개변수를 전달해야만 인스턴스가 생성된다.
this 키워드 이해하기
this는 인스턴스의 자기 자신을 의미한다.
this 키워드의 역할
- 자기 자신의 메모리를 가르킨다.
public class Student {
private int studentID; //학번
private String studentName; //학생 이름
public void setStudentID(int studentID) {
this.studentID = studentID;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
}
위 코드에서 this를 사용하지 않으면 매개변수 이름과 대입하는 이름이 똑같기 때문에 구분할 수 없어서 에러가 발생한다.
매개변수의 이름을 멤버 변수와 다른 이름으로 설정한다면 this 키워드를 쓰지 않아도 된다.
하지만 가독성을 위해 매개 변수 명과 멤버 변수를 동일하게 쓰는것을 권장하고 있다.
- 생성자에서 다른 생성자를 호출할 경우 사용한다.
public class Student {
private int studentID; //학번
private String studentName; //학생 이름
public Student() {
this(150, "피망");
}
public Student(int studentID, String studentName) {
this.studentID = studentID;
this.studentName = studentName;
}
public void showInfo() {
System.out.println("학번: " + studentID);
System.out.println("이름: " + studentName);
}
}
public class StudentTest {
public static void main(String[] args) {
Student studentPark = new Student();
studentPark.showInfo();
Student studentLee = new Student(200, "Lee");
studentLee.showInfo();
}
}
//실행결과
//학번: 150
//이름: 피망
//학번: 200
//이름: Lee
매개 변수가 없는 생성자에서 this를 사용하여 다른 생성자를 호출할 경우 해당 구문이 첫번째 구문이 되어야 한다.
this 키워드 위에 다른 구문을 작성할 경우 에러가 발생한다.
public Student() {
studentID = 100;
this(150, "피망");
}
// 위 코드는 에러를 발생시킨다.
- 인스턴스 자신의 주소를 반환할 때 사용한다.
public class Student {
private int studentID; //학번
private String studentName; //학생 이름
public Student(int studentID, String studentName) {
this.studentID = studentID;
this.studentName = studentName;
}
public Student getSelf() {
return this;
}
}
public class StudentTest {
public static void main(String[] args) {
Student studentPark = new Student(200, "Park");
System.out.println(studentPark);
Student test = studentPark.getSelf();
System.out.println(test);
}
}
//실행결과
//classpart.Student@28a418fc
//classpart.Student@28a418fc
getSelft() 메소드를 이용해 출력한 값과 인스턴스의 값이 같은 것(참조하는 주소가 같다)을 확인할 수 있다.
ref {
07-02 접근제어자 (Access Modifier)
자바는 접근제어자를 사용하여 변수나 메소드의 사용 권한을 설정할 수 있다. [TOC] ## 접근 제어자 변수나 메소드의 사용 권한은 다음과 같은 접근 제어자를 사용 ...
wikidocs.net
http://www.tcpschool.com/java/java_class_declaration
https://yoo11052.tistory.com/52
http://www.tcpschool.com/java/java_methodConstructor_method
http://www.tcpschool.com/java/java_methodConstructor_constructor
코딩교육 티씨피스쿨
4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등
tcpschool.com
https://peemangit.tistory.com/395
}
'Programming > Java' 카테고리의 다른 글
[JAVA] 패키지 (0) | 2022.02.21 |
---|---|
[JAVA]상속 (0) | 2022.02.14 |
[JAVA]제어문 (0) | 2022.01.28 |
[whiteship/live-study]3주차 과제: 연산자 (0) | 2022.01.24 |
[whiteship/live-study]2주차 과제: 자바 데이터 타입, 변수 그리고 배열 (0) | 2022.01.17 |
댓글