
클래스(class)
데이터와 기능을 포함하는 코드 묶음
/*
class 클래스명 {}
클래스는 대문자로 시작
*/
class Person {
// 내용
}
public static void main(String[] args) {
Person person = new Person(); // 객체 만들기
}
클래스 == 틀
객체 == 틀로인해서 나온 빵
인스턴스 변수(instance variable)
클래스 내에 선언된 변수
/*
class 클래스명 {
인스턴스 변수1
인스턴스 변수2
...
}
*/
class Person {
String name;
int age;
}
public static void main(String[] args) {
Person person = new Person();
person.name = "John";
person.age = 20; // 점(.)으로 인스턴스 변수에 접근
}
클래스 변수(class variable)
클래스 내에 static으로 선언된 변수 == 모든 객체가 공유하는 변수
class Person {
String name;
int age;
static int personCount = 0; // 클래스 변수
}
public static void main(String[] args) {
Person.personCount = 10;
System.out.println(Person.personCount); // 10 출력
}
객체를 만들 필요 없이 클래스 명으로 접근
인스턴스 메소드(instance method)
클래스 내에 정의된 메소드
class Person {
String name;
int age;
static int personCount = 0;
public void introduce() { // 인스턴스 메소드
System.out.println("name =" + name);
System.out.println("age =" + age);
}
}
public static void main(String[] args) {
Person person = new Person();
person.name = "John"
person.age = 20;
person.introduce();
}
클래스 메소드(class method)
클래스 내에 static으로 선언된 메소드 == 모든 객체가 공유하는 메소드
class Person {
String name;
int age;
static int personCount = 0;
public static void printPersonCount() { // 클래스 메소드
System.out.println(personCount);
}
}
public static void main(String[] args) {
Person.personCount = 10;
Person.printPersonCount(); // 클래스 메소드
}
this
자기자신 (인스턴스 / 지역변수 구분)
/*
this.인스턴스변수;
*/
class Person {
String name;
public void setName(String name) {
this.name = name; // this.name은 인스턴스 변수, name은 파라미터 변수
}
}
public static void main(String[] args) {
Person person = new Person();
person.setName("John");
System.out.println(person.name);
}
생성자(constructor)
객체가 생성될 때 호출되는 메소드
/*
클래스명(전달값) {
초기화 명령문
}
*/
class Person {
String name;
int age;
Person(String name, int age) {
this.nname = name; // 초기화 작업
this.age = age; // 초기화 작업
}
}
public static void main(String[] args) {
Person.person = new Person("John", 20); // 인수
}
getter&setter
getter
인스턴스 변수의 값 반환
/*
반환형 get이름() {
return 반환값;
}
*/
class Person {
String name;
int age;
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
setter
인스턴스 변수의 값 설정
/*
void set이름(전달값) {
값을 설정하는 작업
}
*/
class Person {
String name;
int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
getter&setter
class Person {
int age;
public int getAge() {
return age;
}
public void setAger() {
this.age = age;
}
}
public static void main(String[] args) {
Pesron person = new Person(); // 객체(object)생성 및 생성자(constructor)호출
person.setAge(20); // 값 설정(setter)
System.out.println(person.getAge()); // 값 읽기(getter)
}
getter와 setter는 언뜻 보면 생성자와 비슷하게 인수를 받아 값을 설정하는것 같지만
특징 | getter&setter | 생성자 |
초기화 시점 | 객체 생성 후에도 값을 설정하거나 변경 가능 | 객체 생성 시점에서만 초기화 가능 |
캡슐화 | 멤버 변수 보호 및 데이터 무결성 보장 | 초기화만 수행함, 이후 보호 로직 구현 필요 |
유효성 검사 | setter에서 값을 설정하기 전에 조건 검증 가능 | 생성자 내부에서만 초기 조건 검증 가능 |
유연성 | 값 읽기(getter) 쓰기(setter)를 분리 가능 | 초기화 이외의 추가 동작 구현 어려움 |
코드 가독성 | 멤버 변수와 동작을 명확히 구분 | 간결한 초기화 작업에 적합 |
예시 | 나이, 이름, 주소 등 변경 가능한 값 | 값이 불변하거나, 객체 생성 후 값의 변경이 필요 없는 경우 |
이러한 차이가 있다.
접근 제어자(access modifier)
접근 권한 지정
/*
접근제어자 class 클래스명 {
접근제어자 인스턴스 변수
접근제어자 인스턴스 메소드
}
*/
class Person {
String name;
private int age; // private == 접근제어자
public void setAge(int age) { // public == 접근제어자
this.age = age;
}
}
접근 제어자 | 접근 가능 범위 |
private | 해당 클래스 내에서만 |
public | 모든 클래스에서 |
default | 같은 패키지 내에서만(아무것도 안 적었을 때) |
protected | 같은 패키지 내에서 다른 패키지인 경우 자식 클래스에서 |
패키지(package)
관련 클래스들을 그룹화 (폴더)
/*
package 패키지명;
*/
- JavaWorkspace
- .idea
- out
- src
- sample
- MyClass.java
- sample
이러한식으로 디렉토리가 구성돼 있을 때
package sample; // 폴더 명
public class Myclass{} // java파일 명
이렇게 표기 된다
또는 다른곳에 있는 패키지를 사용할 때에는
/*
import 패키지명.클래스명;
*/
import java.util.Random; // java라는 패키지 내, util이라는 패키지 내, Random이라는 class를 쓰겠다
import java.util.*; // util 패키지 내 모든 class 사용
public class MyClass {
public static viod main(Sring[] args) {
Random random = new Random();
int num = random.nextInt();
}
}
상속(extends)
특정 클래스(부모 클래스)의 기능을 재사용(자식 클래스) 및 확장
부모 클래스 | 기능 1, 2 | |
↑ | ↓ | 부모 클래스의 기능1, 2를 재사용 |
자식 클래스 | 기능 1, 2, 3 | 새로운 기능3 구현 |
/*
class 자식클래스명 extends 부모클래스명 {}
*/
class Person {
int age;
}
class Student extends Person { // Person이라는 부모클래스 상속
String school; // int age; 를 구현할 필요 없음
}
public class Main {
public static void main(String[] args) {
Student student = new Student();
student.age = 20; // 변수초기화를 하지 않아도 Person클래스의 필드를 사용, 메소드도 동일
}
}
메소드 오버라이딩(method overriding)
부모 클래스의 메소드를 재정의(덮어쓰기)
class Person {
public void introduce() {
System.out.println("I'm Person");
}
}
class Student extends Person {
@Override
public void introduce() {
System.out.println("I'm Student");
}
}
public class Main {
public static void main(String[] args) {
Person person = new Person();
Student student = new Student();
person.introduce(); // I'm Person
student.introduce(); // I'm Student
}
}
다형성(polymorphism)
여러 형태로 동작할 수 있는 성질
class Person {
public void introduce() {
System.out.println("I'm Person");
}
}
class Student extends Person {
@Override
public void introduce() {
System.out.println("I'm Student");
}
}
public class Main {
public static void main(String[] args) {
Person person = new Person();
Person student = new Student(); // Student => Person (Upcasting)
person.introduce(); // I'm Person
student.introduce(); // I'm Student
}
}
객체를 초기화할때 Student student 가 아닌 Person Student형식으로 정의 가능 이를 "업캐스팅"이라고 함
super
부모 클래스에 접근
/*
super.부모클래스 변수;
super.부모클래스 메소드();
super(부모클래스 변수);
*/
class Person {
int age;
Person(int age) {
this.age = age;
}
}
class Student extends Person {
String school;
Student(int age, String school) {
super(age); // super
this.school = school;
}
}
참조(reference)
객체의 메모리 주소를 가리킴
자료형 | 비고 | 종류 |
기본 자료형 | 실제 값 저장 | int, long, float, double, boolean, |
참조 자료형 | 값이 저장된 메모리 주소를 저장 | String, 클래스, ... |
[Java] 기초 자료형, 문자열, 정수, 실수, 비교
자료형 (자료의 형태 Data Type) 문자열 (String)큰 따옴표 내에 들어오는 문자형 자료숫자 자료형 (int, long, double, float)실수 정수 등의 자료불리언 자료형 (boolean)true, false를 반환하는 자료 기본 자
ujo-orr.tistory.com
기초 자료형에서
int a = 10;
int b = 20;
이렇듯 변수가 선언됐다 가정 하였을 때
a | b |
10 | 20 |
이러한 형식으로 값이 들어가게 됨. 여기서
a = b;
이러한 식으로 b의 값을 a에 복사를 하게되면
a | b |
20 | 20 |
이러한 형식으로 값이 들어가게 됨
참조 자료형에서는
String a = "가";
String b = "나";
a | b |
가 | 나 |
가 라는 문자열이 있는 위치를 a 에서 참조하게 되고
나 라는 문자열이 있는 위치를 b 에서 참조하게 됨
위와 같이
a = b;
를 선언하게 되면 b의 값을 a에 복사하게 되는건데 값을 복사하는게 아닌
b에서 가리키고 있는 참조를 a에서 복사하게 된다.
고로 값을 복사하는게 아니게 됨으로
public class Main {
public static void main(String[] args) {
String a = "가";
String b = "가";
System.out.println(a == b); // true (참조값 비교)
System.out.println(a.equals(b)); // true (값 비교)
}
}
public class Main {
public static void main(String[] args) {
String a = new String("가");
String b = new String("가");
System.out.println(a == b); // false (참조값 비교)
System.out.println(a.equals(b)); // true (값 비교)
}
}
이러한 형식으로 비교할 수 있음
- 문자열 리터럴 "가"는 String Pool에 저장됨
- 동일한 문자열 리터럴이 있을 경우 같은 객체를 참조하게 됨.
- new 키워드를 사용하면 항상 새로운 객체를 Heap Memory에 생성
final
변경할 수 없게
class Person {
final String name = "John"; // final 키워드로 불변의 변수값으로 설정
public final void introduce() { // final 키워드로 불변의 메소드로 설정
System.out.println("I'm Person");
}
}
class Student extends Person {
@Override
public void introduce() { // 부모클래스에 선언된 final 때문에 오버라이드 불가
System.out.println("I'm Person");
}
}
열거형(enum)
상수들의 묶음
/*
enum 열거형명 {상수명1, 상수명2, ...}
*/
enum Animal {DOG, CAT, BIRD, RABBIT} // 열거형 선언(열거형 상수는 대문자로 선언)
class Person {
Animal animal; // 열거형 필드 선언
public void setAnimal(Animal animal) { // setter 선언
this.animal = animal;
}
public void introduce() { // 메소드 선언
System.out.println("My animal is " + animal);
}
}
public class Main{
public static void main(String[] args) {
Person person = new Person(); // Person 객체 초기화
person.setAnimal(Animal.CAT); // 열거형 상수 CAT 설정
person.introduce(); // My animal is RABBIT 출력
switch(person.animal) {
case DOG :
System.out.println("강아지");
break;
case CAT :
System.out.println("고양이");
break;
case BIRD :
System.out.println("새");
break;
case RABBIT :
System.out.println("토끼");
break;
default :
System.out.println("unknown");
break;
}
}
}
추상 클래스(abstract class)
아직 완성되지 않은(추상적인) 클래스
/*
abstract class 클래스명 {}
*/
abstract class Shape { // 추상클래스
abstract double calculateArea(); // 추상메소드
}
class Square extends Shape {
private double s;
public Square(double s) { // 차후에 s 값을 파라미터로 받아 private double s; 로 전달
this.s = s;
}
@Override
double calculateArea() { // 추상클래스 오버라이드
return s * s;
}
}
class Circle extends Shape {
private double r;
public Circle(double r) {
this.r = r;
}
@Override
double calculateArea() {
return Math.PI * r * r;
}
}
인터페이스(interface)
클래스를 작성할 때 기본이되는 뼈대
/*
interface 인터페이스명 {}
*/
interface Shape {
double calculateArea();
}
class Square implements Shape { // interface용 implements
private double s;
public Square(double s) { // 생성자
this.s = s;
}
@Override
public double calculateArea() { // interface에서는 @Override 메서드도 반드시 public
return s * s;
}
}
class Circle implements Shape {
private double r;
public Circle(double r) {
this.r = r;
}
@Override
public double calculateArea() { // interface에서는 @Override 메서드도 반드시 public
return Math.PI * r * r;
}
}
추상 클래스와 인터페이스의 차이
특징 | 추상 클래스 | 인터페이스 |
목적 | "is-a" 관계 클래스의 확장(상속)을 위한 기반 |
"can-do" 관계 클래스의 행동(기능)계약 제공 |
다중 상속 | 단일 상속만 지원 | 다중 구현 가능 |
메소드 | 추상 메소드와 구현된 메소드 모두 포함 | 모든 베소드는 기본적으로 public abstract |
변수 | 인스턴스 변수, 정적 변수, 상수를 가질 수 있음 | public, static, final 상수만 가질 수 있음 |
생성자 | 생성자 정의 가능 | 생성자 정의 불가능 |
접근 제어자 | public, protected, private 모두 사용 가능 | 모든 메소드는 public이어야 함 |
추상 메소드 구현 여부 | 구현하지 않아도 됨 | 모든 메소드는 구현해야 함 |
제네릭스(generics)
다양한 형태의 데이터를 일반화하여 다룰 수 있게
/*
T 변수명
*/
// 단순 메소드 오버로딩 방식
public class Main {
public static void printValue(int value) { // 타입별 메소드 정의
System.out.println(value);
}
public static void printValue(double value) { // 타입별 메소드 정의
System.out.println(value);
}
public static void printValue(String value) { // 타입별 메소드 정의
System.out.println(value);
}
public static void main(String[] args) {
int intValue = 3;
double doubleValue = 3.14;
String stringValue = "Hi";
printValue(intValue);
printValue(doubleValue);
printValue(stringValue);
}
}
// 제너릭 방식 (컴파일러가 타입 매개변수 T를 추론함)
public class Main {
public static <T> void printValue(T value) { // 제너릭을 통해서 타입을 일반화
System.out.println(value);
}
public static void main(String[] args) {
int intValue = 3;
double doubleValue = 3.14;
String stringValue = "Hi";
printValue(intValue);
printValue(doubleValue);
printValue(stringValue);
}
}
제네릭 클래스(generic class)
다양한 데이터 유형을 처리할 수 있도록 설계된 제네릭 기반 클래스
/*
class 클래스명 <T> {}
*/
// 일반적인 클래스
class BoxInteger {
int data; // 인스턴스 변수
public void setData(int data) { // 생성자
this.data = data;
}
}
class BoxString {
String data;
public void setData(String data) {
this.data = data;
}
}
public class Main {
public static void main(String[] args) {
BoxInteger iBox = new BoxInteger(); // 일반적인 객체 생성
BoxString sBox = new BoxString(); // 일반적인 객체 생성
iBox.setData(3); // 정수 담기
sBox.setData("Hi"); // 문자열 담기
}
}
// 제너릭 클래스
class Box<T> { // 클래스 일반화
T data; // 일반화 된 인스턴스 변수
public void setData(T data) { // 생성자
this.data = data;
}
}
public class Main {
public static void main(String[] args) {
Box<Integer> iBox = new Box<>(); // 정수 제너릭 객체 생성
Box<String> sBox = new Box<>(); // 문자열 제너릭 객체 생성
iBox.setData(3); // 정수 담기
sBox.setData("Hi"); // 문자열 담기
}
}
제너릭 클래스를 만들때 타입지정은 불필요하지만
객체를 생성할 때에는 타입을 지정해주어야 함
래퍼 클래스(wrapper class)
기본 자료형을 객체로 감싸 추가 기능 제공하는 클래스
// 기본 변수 선언
public class Main {
public static void main(String[] args) {
int i =1;
double d = 1.0;
char c = 'a';
}
}
// 래퍼 클래스 변수 선언
public class Main {
public static void main(String[] args) {
Integer i =1;
Double d = 1.7;
Character c = 'a';
System.out.println(i.intValue());
System.out.println(d.intValue()); // 1출력. 소숫점 이하는 버림
System.out.println(c.cahrValue());
}
}
기본 타입(primitive) | 래퍼 클래스(wrapper class) |
int | Integer |
double | Double |
char | Character |
boolean | Boolean |
long | Logn |
float | Float |
byte | Byte |
short | Short |
'Java > Java Language' 카테고리의 다른 글
[Java 기초] 익명클래스 Anonymous, 람다 Lambda, 스트림 Stream (0) | 2024.11.28 |
---|---|
[Java 기초] 리스트 list (0) | 2024.11.28 |
[Java 기초] 아스키코드 ascii code, 메소드 method (0) | 2024.11.26 |
[Java 기초] 제어문 control statement, 반복문 loop statement, 배열 array (0) | 2024.11.26 |
[Java 기초] 자료형 type, 문자열 String, 정수 int, 실수 double (0) | 2024.11.26 |