class MyClass {
// field, constructor, and
// method declarations
}
기본 선언 방식은 위와 같다.
클래스 몸체는 새로운 객체를 초기화하는 생성자
, 클래스와 그 객체의 상태를 제공하는 필드
, 행동을 구현하는 메소드
를 포함한다.
class MyClass extends MySuperClass implements YourInterface {
// field, constructor, and
// method declarations
}
클래스가 상위 클래스의 상속을 받는지, 인터페이스를 구현하는지에 대한 정보 역시 선언할 때 제공할 수 있다.
또한 public
과 private
과 같이 다른 클래스들이 구현하는 클래스에 접근가능한지의 여부를 결정하는 접근자 역시 클래스 선언 가장 앞부분에 쓸 수 있다.
클래스 이름은 관례상 앞글자는 대문자로 한다. 상위 클래스 앞에 extends
를 붙이는데, 자바에서는 다중상속은 되지 않는다. 오직 한 클래스만 상속할 수 있다.
필드
- 클래스에서의 멤버변수지역변수
- 메소드나 코드 내의 변수파라미터
- 메소드 생성에서의 변수public
- 모든 클래스에서 접근 가능한 필드private
- 자신의 클래스에서만 접근가능한 필드예시
public int age;
public String name;
public int add(int a, int b) {
return a + b;
}
관습적으로 메서드 이름은 소문자로 된 동사의 형태
이거나 소문자인 동사로 시작하고, 뒤에는 형용사, 명사 등 여러단어가 합쳐진다. 여러 단어로 구성될 때 두 번째 부터의 단어는 반드시 대문자로 시작해야한다.
ex) run, runFas, getFinalData, isEmpty, compareTo, etc.
자바는 오버로딩을 지원하는데, 자바는 메소드 시그니처가 다른 메소드들을 구별할 수 있다. 즉 다른 형태의 파라미터를 가지지만 같은 이름인 클래스의 메소드들을 가질 수 있다는 뜻이다.
public class Calculation {
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
클래스는 객체를 생성할 때 호출되는 생성자를 가진다. 생성자 선언은 메소드 선언과 유사해보이지만, 대신 클래스 이름을 그대로 쓰고 리턴 타입이 없다.
public class Bicycle {
private int geer;
private int cadence;
private int speed;
public Bicycle(int startCadence, int startSpeed, int startGeer) {
geer = startGeer;
cadence = startCadence;
speed = startSpeed;
}
}
JDK1.5부터 동적으로 매개변수를 지정할 수 있게 되었다. 즉 인자값의 개수가 모호할 때 사용할 수 있다. 이전에는 배열을 주로 사용했는데, 배열을 만드는 것 보다 더 간단하다.
void test(String... args){};
String... args
타입이름 + ...+ 공백 + 파라미터 이름 형식public Polygon polygonFrom(Point... corners) {
int numberOfSides = corners.length;
double squareOfSide1, lengthOfSide1;
squareOfSide1 = (corners[1].x - corners[0].x)
* (corners[1].x - corners[0].x)
+ (corners[1].y - corners[0].y)
* (corners[1].y - corners[0].y);
lengthOfSide1 = Math.sqrt(squareOfSide1);
}
배열
처럼 다뤄진다.자바에서는 클래스 내부에 다른 클래스를 정의하는 것이 가능하다. 이런 클래스들은 중첩클래스라고 불린다.
class OuterClass {
...
class NestedClass {
}
}
static
중첩 클래스와 non-static
중첩 클래스로 나뉜다. non-static 중첩 클래스는 내부 클래스(inner class)라고도 불린다.class OuterClass {
...
static class StaticNestedClass {
}
class InnerClass {
}
}
중첩 클래스들은 둘러싼 클래스의 멤버이다. inner 클래스들은 설령 private으로 선언되었다고 해도 둘러싼 클래스들의 멤버들에 접근할 수 있다. static 중첩 클래스들은 둘러싼 클래스의 멤버에 접근할 수 없다. OuterClass의 멤버로서, 중첩 클래스들은 private, public, protected, package private으로 선언할 수 있다. (외부 클래스들은 오직 public이나 package private으로만 선언가능하다.
InnerClass의 한 종류인 익명클래스는 코드를 보다 간결하게 만들어주고, 클래스를 선언함과 동시에 인스턴트화할 수 있다. 이름이 없는 것을 제외하고 로컬 클래스처럼 사용할 수 있다. 클래스를 단 한 번만 사용해야한다면 익명클래스를 사용하는 것이 좋다. 또한 부모 클래스를 상속받는 서브 클래스를 생성하지 않고도, 단일 객체를 만들어 부모 클래스에 정의된 행위를 추가할 수 있다. 익명클래스는 클래스와 인터페이스로부터 만들 수 있다.
익명클래스 vs 일반 클래스
[익명 클래스를 사용하지 않은 예제]
interface Age {
int age = 29;
void getAge();
}
class MyClass implements Age {
@Override
public void getAge() {
System.out.print("Age is " + age);
}
}
class demo {
public static void main(String... args) {
MyClass myClass= new MyClass();
myClass.getAge();
}
}
[익명 클래스를 사용한 예제]
class AnonymousDemo {
public static void main(String[] args) {
Age age = new Age() {
@Override
public void getAge() {
System.out.print("Age is " + age);
}
};
age.getAge();
}
}
열거형은 변수가 미리 정의된 상수집합이 되도록 하는 특수한 데이터 타입이다. 변수는 반드시 사전에 정의된 값 중 하나와 같아야한다.
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
}
public class EnumTest {
Day day;
public EnumTest(Day day) {
this.day = day;
}
public void tellItLikeItIs() {
switch (day) {
case MONDAY:
System.out.println("Mondays are bad.");
break;
case FRIDAY:
System.out.println("Fridays are better.");
break;
case SATURDAY: case SUNDAY:
System.out.println("Weekends are best.");
break;
default:
System.out.println("Midweek days are so-so.");
break;
}
}
public static void main(String[] args) {
EnumTest firstDay = new EnumTest(Day.MONDAY);
firstDay.tellItLikeItIs();
EnumTest thirdDay = new EnumTest(Day.WEDNESDAY);
thirdDay.tellItLikeItIs();
EnumTest fifthDay = new EnumTest(Day.FRIDAY);
fifthDay.tellItLikeItIs();
EnumTest sixthDay = new EnumTest(Day.SATURDAY);
sixthDay.tellItLikeItIs();
EnumTest seventhDay = new EnumTest(Day.SUNDAY);
seventhDay.tellItLikeItIs();
}
}
/*
Mondays are bad.
Midweek days are so-so.
Fridays are better.
Weekends are best.
Weekends are best.
*/
객체란, 세상에 존재하는 모든 것
들이다. 각각의 사물은 고유하고, 속성(상태)
을 갖고 행위
를 한다. 즉, 객체는 속성(field)
와 행위(method)
로 이루어져 있다고 볼 수 있다. 예를들어 강아지는 이름, 색, 털, 배고픔이라는 속성(상태)과, 짖기, 꼬리말기 등의 행위를 가진다.
객체는 클래스로부터 만들 수 있고, 객체 생성에서는 다음과 같은 과정을 가진다.
Declaration
: 객체를 참조하는 변수 선언
변수를 선언할 때, type name;
형태로 타입을 type으로 가지는 데이터를 참조하기 위해, name이라는 변수를 사용할 것이라고 컴파일러에게 알린다.
마찬가지로 Person person;
과 같이 레퍼런스 타입을 선언할 수 있다. 이런식으로 객체를 선언한다면, 객체의 값은 객체가 실제로 만들어지고 할당될 때 까지 정해지지 않는다. 단순히 레퍼런스 변수를 선언하는 것이 객체를 생성하는 것을 뜻하지 않는다. 객체를 생성하기 위해서는 new
연산자가 필요하다. 반드시 person에 객체를 할당해야 컴파일 에러가 나지 않는다.
어떤 객체도 참조하지 않는 변수의 상태는 아래와 같이 묘사될 수 있다.
person은 어떤 것도 가리키지 않는다.
Instantiation
: 클래스 인스턴트화
new
연산자는 새로운 객체에 메모리를 할당하고 그 메모리에 참조를 반환함으로써 클래스를 인스턴트화 시킨다. 또한 new 연산자는 객체 생성자를 호출한다.
'클래스를 인스턴트화
' 한다는 것은 객체를 생성하는 것과 같은 의미이다. 객체를 생성할 때, 클래스의 '인스턴스'를 만드는 것이 즉 클래스를 인스턴트화 한다는 것이다.
new 연산자는 생성자 호출이 필요하다. 생성자의 이름은 인스턴트화할 클래스가 뭔지 알려준다. new 연산자는 자신이 생성한 객체에 대한 참조를 반환한다. 이 참조는 일반적으로 알맞은 타입의 변수로 할당된다.
new 연산자가 반환하는 참조는 변수에 할당될 필요는 없다. (값 그대로 사용)
또한 int height = new Rectangle().height;
와 같이 표현식에서 직접적으로 사용할 수 있다.
아래에서 계속..
Initialization
: 객체 초기화
public class Person {
public String name;
public int age;
// constructor
public Person(String name, int age) {
this.name = name;
this age = age;
}
}
이 클래스는 하나의 생성자만 가진다. 생성자는 클래스와 같은 이름을 가지고 리턴 타입이 없기 때문에 생성자임을 인식할 수 있다. 생성자는 String name, int age 와 같이 String, int 인자를 가진다.
Person person = new Person("Seul", 26);
위와 같은 선언문은 각각의 인자에 "Seul", 26을 제공한다.
또한 초기화된 객체는 Heap에 그 값이 저장되고, Stack엔 참조변수만 저장된다.
Static 영역
JVM이 종료될 때 까지 사라지지 않는다. Class에 대한 정보, 패키지, static 키워드가 선언된 클래스 멤버나 메소드 등이 static 영역에 속한다.
Stack 영역
primitive가 저장되고, refernce는 참조값만 저장된다. 스레드 역시 스택 영역에 생성되는데, 하나의 스레드는 별개의 T메모리를 갖는다. 따라서 하나의 스레드는 다른 스레드로 접근할 수 없지만 static과 heap은 공유한다.
Heap 영역
new
를 통해 인스턴스화 되면, 객체의 값들은 Heap
에 메모리 공간이 할당되고 저장된다.
package week5;
public class Person {
public String name = "Jone Doe";
public int age = 1;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
public static void main(String... args){
Person person1 = new Person();
Person person2 = new Person("Seul", 26);
String name1 = person1.name;
String name2= person2.name;
int age1 = person1.age;
int age2 = person2.age;
System.out.println(name1 + " : " + age1);
System.out.println(name2 + " : " + age2);
}
}
그렇다면 객체지향의 개념은 무엇일까? 인간이 현실세계를 인지하는 방법은 직관적이다. 이와같은 방식으로, 눈으로 보고, 느끼고, 생활하는 현실세계 처럼 프로그래밍 하는 것이다. 또한 프리미티브 타입은 변수에 적당한 메모리를 할당한다.
클래스는 분류에 대한 개념이고 실체가 아니다. 하자민 객체는 실체이다. 절대 붕어빵틀과 붕어빵의 관계가 아니다.
this
keyword인스언스 메서드나 생성자 내에서, this
는 그것의 메서드 또는 생성자가 호출되는 최근 객체에 대한 참조이다.
[this
없이 사용]
public class Point {
public int x = 0;
public int y = 0;
//constructor
public Point(int a, int b) {
x = a;
y = b;
}
}
[this
와 사용]
public class Point {
public int x = 0;
public int y = 0;
//constructor
public Point(int a, int b) {
x = a;
y = b;
}
}
생성자 내에서 this
키워드를 사용하여 동일한 클래스의 다른 생성자를 호출할 수 있다.
public class Rectangle {
private int x, y;
private int width, height;
public Rectangle() {
this(0, 0, 1, 1);
}
public Rectangle(int width, int height) {
this(0, 0, width, height);
}
public Rectangle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
...
}
이런식으로 this
를 이용하여 생성자를 호출할 수 있다.
캡슐화(capsulation)
: information hiding객체의 메소드로만 상호작용 함으로써, 객체 내부 구현의 세부한 것들은 외부로부터 숨길 수 있다.
접근 제어자를 통해 가능하다.
접근제어자 | 설명 |
---|---|
private - | 본인만 접근 가능 |
default ~ | 같은 패키지 내의 클래스에서 접근 가능 |
protected # | 상속 / 같은 패키지 내의 클래스에서 접근 가능 |
public + | 모두가 접근 가능 |
상속(extends)
: 재사용 + 확장객체지향에서의 상속은 상위 클래스의 특성을 하위 클래스에서 상속하고, 거기에 필요한 특성을 추가, 즉 확장하여 사용할 수 있다는 의미이다.
예를들어 동물이라는 상위클래스가 있다면, 이 동물 클래스를 상속받아 포유류와 조류 클래스를 각각 만들 수 있다. 또한 포유류라는 상위클래스를 고래와 박쥐 클래스가 각각 상속할 수 있다.
✔️ 상속관계에서 반드시 만족해야 할 문장
추상화(abstraction)
: 모델링구체적인 것을 분해해서 관심영역(Application Boundary)에 있는 특성만 가지고 재조합하는 것, 즉 모델링
이다. 공통 특성 혹은 공통 속성을 추출한다.
모델링과 객체지향의 추상화와 무슨 관련?
클래스를 설계할 때 객체들을 관찰하여, 객체들이 가진 "공통된 특성" 을 찾아야함
메서드(기능/ 행위) : 동사(먹다, 자다, 일하다 ...) 로 표현되는 특성은 수행절차(로직) 을 가짐
애플리케이션 경계(context)
Q. 내가 만들고자 하는 app은 어디에서 사용될 것인가?
애플리케이션 경계 정하기 → 추상화 → 클래스 설계 → 클래스
다형성(polymorphism)
: 사용편의하나의 class 메서드가 다양한 방식으로 동작
오버로딩 - 같은 메서드 이름, 다른 인자
두 메소드가 같은 이름을 갖고 있지만, 인자의 개수나 자료형이 다른 경우
오버라이딩 - 같은 메서드 이름, 같은 인자
상속관계에 있는 클래스의 성격에 맞게 부모 클래스의 함수를 재정의 → 메서드와 이름과 용례가 같음
출처
https://dduddublog.tistory.com/169
java 공식 레퍼런스