https://cerulean85.tistory.com/149
객체와 인스턴스의 차이
* 자의적인 해석이므로 논란의 여지가 있음 객체와 인스턴스의 차이를 알아보니 블로그마다 말이 다르다. 어떤 블로거는 인스턴스는 객체와 같지만, 관계적인 측면에서 이야기할 때 객체 대신
cerulean85.tistory.com
객체 지향 프로그래밍 (Object Oriented Programming)
: 부품 객체들 먼저 만들고, 하나씩 조립해나가 프로그램 완성
객체 : 소프트웨어 세계에 구현할 대상 / 독립적으로 존재하며 서로 상호작용
클래스 : 객체 구현 위한 설계도
인스턴스 : 클래스에 의해 소프트웨어 세계에 구현된 실체
객체⊃인스턴스
- 객체
물리/추상적으로 존재하는 것 중 속성 갖고 식별 가능한 것
객체 모델링 : 현실 세계의 객체 -> 소프트웨어 객체
A 객체가 B 객체 기능 이용하려면 메소드 호출해야 함 ex. B.메소드(매개값);
- OOP 특징
1. 캡슐화 : 객체의 내부 구조를 감추고 노출된 필드, 메소드만 이용 가능하게 하여 사용범위 제한, 보호
2. 상속 : 상위 객체가 하위 객체에 필드, 메소드 물려줌 => 효율적, 코드 중복 줄임
3. 다형성: 하나의 타입에 여러 객체 대입 가능
=> 부모 타입에 모든 자식 객체 대입 가능, 인터페이스 타입에 모든 구현 객체 대입 가능
ex. A 인터페이스 타입 타이어 = 여러 회사의 A 구현 타이어들 모두 교체 가능
객체 & 클래스
클래스 이름 대문자로 시작
메인 메소드 없이 생성 => run 안 됨
구성 멤버 : 필드, 생성자, 메소드
- 클래스 선언
public class Account { //클래스 선언
//필드
String accountNo;
String ownerName;
int balance;
//생성자
//메서드: 예금
void deposit (int amount) { //void : 리턴값 없음 //괄호 안: 매개변수 ex.주스 받을 컵
balance+=amount;
}
//메서드: 인출
int withdraw(int amount) { //리턴값 : int
if (balance<amount) {
return 0;
}
balance-=amount;
return amount;
}
}
- 객체 생성
Account chulsu; //클래스 변수 선언
chulsu= new Account(); //새 객체 생성, 변수에 저장
=>축약
Account chulsu = new Account(); //Account 클래스의 객체(인스턴스) 생성
public class AccountEx1 {
public static void main(String[] args) {
Account chulsu = new Account(); //객체(인스턴스) 생성
chulsu.accountNo = "0101-10101-1010"; //해당 클래스 내 필드, 메서드 사용 가능
chulsu.ownerName = "김철수";
chulsu.balance = 1000;
Account gildong = new Account();
gildong.accountNo = "0202-020202-0202";
gildong.ownerName = "홍길동";
gildong.balance = 0;
chulsu.deposit(5000);
gildong.deposit(30000);
chulsu.deposit(20000);
int amount = gildong.withdraw(7000);
System.out.println("찾은 금액: "+amount);
System.out.println("잔액: "+gildong.balance);
}
}
※
괄호 O => 메소드
괄호 X => 필드
※
라이브러리 클래스 : 다른 클래스에서 이용하는 클래스 ex. Account
실행 클래스 : main() 메소드 제공하여 프로그램을 실행하는 클래스 ex. AccountEx1
필드 (=변수)
: 객체의 정보 저장하는 곳
객체 생성 시 초기값 설정 안 된 필드는 자동으로 기본 초기값 (0,false,null..) 설정됨
생성자
: 객체 생성 시 객체 초기화(필드 초기화, 메소드 호출-> 객체 사용할 준비함)를 위해 가장 처음 실행되는 메소드
생성자 생략 -> 중괄호 {} 블록 비어있는 기본 생성자 자동 생성 => 객체 생성에 생성자 필수
생성자 명시적으로 선언 시 기본 생성자 자동 생성 X
리턴 타입 X, 클래스 이름과 동일
- 생성자 선언 및 호출
public class Account { //클래스
//필드
String accountNo;
String ownerName;
int balance;
//생성자
//public Account(String accNo, String ownerNa, int bal) { //생성자 선언
//accountNo=accNo; //accountNo : 필드, accNo : 매개변수
//ownerName=ownerNa;
//balance=bal;
//}
// => 코드 작성 편의 위해 매개변수명, 필드명 같도록 수정
public Account(String accountNo, String ownerName, int balance) {
this.accountNo=accountNo; //매개변수 String accountNo 받아서 객체 자신의 필드 accountNo에 전달
this.ownerName=ownerName;
this.balance=balance;
}
//메서드: 예금
void deposit (int amount) {
balance+=amount;
}
//메서드: 인출
int withdraw(int amount) {
if (balance<amount) {
return 0;
}
balance-=amount;
return amount;
}
}
public class AccountEx2 {
public static void main(String[] args) {
Account younghee = new Account("222-222-222","이영희",100); //생성자 호출
Account chanho = new Account("111-222-3333", "박찬호" , 0);
younghee.deposit(50000);
chanho.deposit(30000);
younghee.deposit(40000);
chanho.withdraw(12000);
printAccount(younghee);
printAccount(chanho);
}
//통장 정보 출력 메서드 => 메소드의 분업화
static void printAccount(Account obj) { //매개변수=>Account 클래스 객체만 받음
System.out.println("계좌번호: "+obj.accountNo);
System.out.println("예금주이름: "+obj.ownerName);
System.out.println("잔액: "+obj.balance);
System.out.println("-------------------------");
}
}
//
계좌번호: 222-222-222
예금주이름: 이영희
잔액: 90100
-------------------------
계좌번호: 111-222-3333
예금주이름: 박찬호
잔액: 18000
-------------------------
- 생성자 오버로딩
: 매개변수 타입, 개수, 순서 다르게 선언
=> 다양한 방법으로 객체 생성 가능해짐
public class Car {
Car(){..}
Car(String model){..}
Car(String model, String color){..}
Car(String model, String color, int speed){..}
}
- this() - 다른 생성자 호출
생성자 오버로딩 많아지면 중복 코드 발생
=> 필드 초기화 내용을 한 생성자에만 작성하고 나머지 생성자에서는 해당 생성자 호출
생성자 첫 줄에서만 사용 가능
public class Car{
//필드
String compnay="현대";
String model;
String color;
int maxSpeed;
//생성자
Car(){}
Car(String model){
this(model, "은색", 250); //호출
}
Car(String model, String color){
this(model, color, 250); //호출
}
Car(String model, String color, int maxSpeed){ //공통 실행 코드
this.model=model;
this.color=color;
this.maxSpeed=maxSpeed;
}
}
메소드
: 객체의 동작(기능, 일)에 해당하는 중괄호 { } 블록
=> 객체 간 상호작용의 수단, 객체가 다른 객체 기능 이용하도록 함
- 메소드 오버로딩
: 클래스 내에 같은 이름의 메소드를 여러 개 선언
1. 매개변수 개수 달라야 함
2. 매개변수 개수 같으면 타입 or 순서 달라야 함
public class PhysicalInfo {
//필드
String name;
int age;
float height, weight;
//생성자
public PhysicalInfo(String name, int age, float height, float weight) {
this.name=name;
this.age=age;
this.height=height;
this.weight=weight;
//매개변수 이름=필드 이름 편리, but 구분 필요 => 필드값에는 this 추가
}
//메소드
void update (int age, float height, float weight) {
this.age=age;
this.height=height;
this.weight=weight;
}
//메소드 오버로딩
void update (int age, float height) {
this.age=age;
this.height=height;
}
}
//PhysicalInfoEx
public static void main(String[] args) {
PhysicalInfo younghee = new PhysicalInfo("이영희", 10, 135.5f, 38.0f);
printPhyiscalInfo(younghee);
younghee.update(11, 145.0f, 44.2f); //기존 메소드
printPhyiscalInfo(younghee);
younghee.update(12, 157.9f); //오버로딩한 메소드
printPhyiscalInfo(younghee);
}
public static void printPhyiscalInfo(PhysicalInfo obj) {
System.out.println("이름 : "+obj.name);
System.out.println("나이 : "+obj.age);
System.out.println("키 : "+obj.height);
System.out.println("몸무게 : "+obj.weight);
System.out.println("---------------------------");
}
//
이름 : 이영희
나이 : 10
키 : 10.0
몸무게 : 38.0
---------------------------
이름 : 이영희
나이 : 11
키 : 145.0
몸무게 : 44.2
---------------------------
이름 : 이영희
나이 : 12
키 : 157.9
몸무게 : 44.2
---------------------------
- 매개변수 없는 메소드
public class Rectangle {
int width;
int height;
public Rectangle(int width, int height) {
this.width=width;
this.height=height;
}
int getArea() { //매개변수 없음 => 호출 시 내부 코드 실행해 값 리턴
return width*height;
}
}
public class RectangleEx1 {
public static void main(String[] args) {
Rectangle rect1 = new Rectangle(20, 30);
int area = rect1.getArea(); //내부 계산 실행해 리턴한 값을 변수에 전달
System.out.println("사각형 너비 : "+rect1.width );
System.out.println("사각형 높이 : "+rect1.height );
System.out.println("사각형 면적 : "+area );
}
}
- 매개변수 개수 모를 때
매개변수를 "..."으로 선언 => 메소드 호출 시 배열 요소들만 나열
public class Calculator {
//배열을 매개변수로 받아 처리하는 메소드
int sum1(int[] values) {
int sum=0;
for (int i=0;i<values.length;i++) {
sum+=values[i];
}
return sum;
}
//매개변수로 데이터를 받아서 처리하는 메소드
int sum2(int num1, int num2, int num3) {
int sum=0;
sum=num1+num2+num3;
return sum;
}
//매개변수의 수를 모를 경우 처리하는 메소드
int sum3(int ...nums) {
int sum=0;
for (int i=0;i<nums.length;i++) {
sum+=nums[i];
}
return sum;
}
}
public class CalculatorEx1 {
public static void main(String[] args) {
Calculator myCalc = new Calculator();
int[] value1 = {10,85,31,64,33};
int result1=myCalc.sum1(value1); //배열 자체 대입
System.out.println("배열의 총합 : "+result1);
int result2 = myCalc.sum1(new int[] {85,90,40});
System.out.println("배열의 총합 : "+ result2);
int result3 = myCalc.sum3(20, 80, 60); //배열 요소만 대입
System.out.println("자료의 총합 : "+result3);
int result4 = myCalc.sum3(20, 80, 60,85,90);
System.out.println("자료의 총합 : "+result4);
}
}
인스턴스 멤버 & this
인스턴스 멤버 : 객체(인스턴스) 생성해야 사용 할 수 있는 필드, 메소드 (인스턴스 필드, 인스턴스 메소드)
- this => 객체 내부에서 인스턴스 멤버에 접근
Car(String model){
this.model = model; //this 통해 객체의 필드에 접근
}
정적 멤버 (static)
정적 멤버(=클래스 멤버) : 클래스에 고정된 멤버 / 객체 생성하지 않아도 사용할 수 있는 필드와 메소드
정적 블록 안에서 인스턴스 멤버, this 사용 불가
=> 객체 생성, 참조변수로 접근하면 인스턴스 멤버 사용 가능
메인 메소드도 정적 메소드 ex. public static void main(String[] args){}
public Class ClassType {
//정적 멤버
static int field();
static void method(){}
//인스턴스 멤버
int field2;
void method2(){}
//정적 블록
static {
field=20;
method();
field2=10; //컴파일 에러 (인스턴스 멤버 사용 불가)
method2(); //컴파일 에러
}
static void method3(){
this.field2=100; //컴파일 에러 (this 사용불가)
ClassType obj = new ClassType(); //객체 생성 후 참조변수로 접근하면 인스턴스 멤버 사용 가능
obj.field2=20; //O
obj.method1(); //O
}
}
public class Printer {
//정적 메소드
static void println(int value) {
System.out.println(value);
}
static void println(boolean value) {
System.out.println(value);
}
static void println(double value) {
System.out.println(value);
}
static void println(String value) {
System.out.println(value);
}
}
public class PrinterExample {
public static void main(String[] args) {
Printer.println(10); //static => 객체 생성 없이 클래스 통해 바로 메소드 구현
Printer.println(true);
Printer.println(4.6);
Printer.println("홍길동");
}
}
final 필드 & 상수
- final 필드
: 초기값이 최종값이 되어 수정 불가한 필드
객체마다 저장되며, 생성자의 파라미터를 통해 값 가질 수 있음
- 초기값 부여하는 방법
1. 필드 선언 시 부여
2. 생성자에서 부여
public class Person{
final String name="a"; //필드로 초기값 부여
final int age=12;
public Person(int age){ //생성자로 초기값 부여
this.age=age;
}
}
- 상수(static final) : 변하지 않는 값
객체마다 저장되지 않고 클래스에만 포함됨
=> 객체 생성되지 않아도 원본클래스 자체에서 접근 가능
초기값 수정 불가
필드명 전체 대문자 권장
public class Account {
//상수 필드
static final String BANKNAME = "신한은행";
//인스턴트 필드 : 변수
String accountNo;
String ownerName;
int balance;
public Account(String accountNo, String ownerName, int balance) {
this.accountNo=accountNo; //this=> 필드
this.ownerName=ownerName;
this.balance=balance;
}
public Account() {
}
void deposit (int amount) {
balance+=amount;
}
int withdraw(int amount) throws Exception {
if (balance<amount) {
throw new Exception("잔액 부족");
}
balance-=amount;
return amount;
}
}
public class AccountEx2 {
public static void main(String[] args) {
Account younghee = new Account("222-222-222","이영희",100);
System.out.println(Account.BANKNAME); //객체 없이 클래스로만 접근
~
패키지
클래스 관리하기 위한 폴더
클래스 식별자 역할 => 다른 패키지에 있으면 클래스 이름 같아도 다른 클래스로 인식됨
- import
다른 패키지 클래스 사용하려면 import문 작성
import 패키지명.클래스명;
import 패키지명.*; //패키지의 모든 클래스 import
접근 제한자
접근제한 | 적용 대상 | 접근 가능/불가 클래스 |
public | 클래스, 필드, 생성자, 메소드 | 모두 접근 가능 |
protected | 필드, 생성자, 메소드 | 같은 패키지 + 다른 패키지 자식클래스 접근 가능 |
default | 클래스, 필드, 생성자, 메소드 | 같은 패키지만 접근 가능 (다른 패키지 접근 불가) |
private | 필드, 생성자, 메소드 | 모든 외부 클래스 접근 불가 |
- private
public class Rectangle {
private int width; //private 접근 제한 생성자
private int height;
}
public class RectangleEx1 {
public static void main(String[] args) {
Rectangle rect1 = new Rectangle(20, 30);
// rect1.width=-10;
int area = rect1.getArea();
// System.out.println("사각형 너비 : "+rect1.width );
//객체 생성 -> 필드, 메소드에 접근 가능
// System.out.println("사각형 높이 : "+rect1.height );
System.out.println("사각형 면적 : "+area );
}
}
=> 다른 클래스에서 필드 단독 사용 불가, 에러 발생
=> 해결
getter, setter 메소드
: 두 메소드 통해 접근 제한된 객체의 값 가져옴
- getter : 필드값 가공, 외부로 전달
public class Rectangle {
private int width;
private int height;
public Rectangle(int width, int height) {
this.width=width;
this.height=height;
}
int getArea() { //
return width*height;
}
public int getWidth() { //
return width;
}
public int getHeight() { //
return height;
}
}
public class RectangleEx1 {
public static void main(String[] args) {
Rectangle rect1 = new Rectangle(20, 30);
int area = rect1.getArea();
System.out.println("사각형 너비 : "+rect1.getWidth());
System.out.println("사각형 높이 : "+rect1.getHeight());
System.out.println("사각형 면적 : "+area );
}
}
필드에 음수값, 0 비허용 설정
public class Rectangle {
private int width;
private int height;
public Rectangle(int width, int height) throws Exception { //
if (width<=0 || height<=0) {
throw new Exception("너비와 높이는 양수만 가능");
}
this.width=width;
this.height=height;
}
int getArea() {
return width*height;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public int getHeight() {
return height;
}
}
public class RectangleEx1 {
public static void main(String[] args) {
try {
Rectangle rect1 = new Rectangle(20, 30);
int area = rect1.getArea();
System.out.println("사각형 너비 : "+rect1.getWidth());
System.out.println("사각형 높이 : "+rect1.getHeight() );
System.out.println("사각형 면적 : "+area );
}catch(Exception e){
System.out.println(e.getMessage());
}
}
}
=> throws Exception 설정 => ex 클래스에 오류 대응책으로 try catch문 작성 필수
- setter : 매개값 필드에 저장
public class Rectangle {
private int width;
private int height;
public Rectangle(int width, int height) throws Exception {
if (width<=0 || height<=0) {
throw new Exception("너비와 높이는 양수만 가능");
}
this.width=width;
this.height=height;
}
int getArea() {
return width*height;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public void setWidth(int width) { //
this.width = width;
}
public void setHeight(int height) { //
this.height = height;
}
}
public class RectangleEx1 {
public static void main(String[] args) {
try {
Rectangle rect1 = new Rectangle(20, 30);
int area = rect1.getArea();
System.out.println("사각형 너비 : "+rect1.getWidth());
System.out.println("사각형 높이 : "+rect1.getHeight() );
System.out.println("사각형 면적 : "+area );
rect1.setWidth(50);
rect1.setHeight(70);
area=rect1.getArea();
System.out.println("사각형 너비 : "+rect1.getWidth());
System.out.println("사각형 높이 : "+rect1.getHeight() );
System.out.println("사각형 면적 : "+area );
}catch(Exception e){
System.out.println(e.getMessage());
}
}
}
싱글톤
: 클래스 외부에서 new 연산자로 생성자 호출할 수 없도록 막아 만들어지는 단 하나의 객체
생성자 앞에 private 제한자 붙임
정적 필드, 정적 메소드
public class Cheomseongdae {
//정적 필드
private static Cheomseongdae cheom = new Cheomseongdae(); //클래스 자체가 필드가 됨
//private 생성자
private Cheomseongdae() {
}
//정적 메서드
static Cheomseongdae getInstance() { //Cheomseongdae: 타입 이름 / getInstance: 메소드 이름
return cheom;
}
void history() {
System.out.println("경주");
}
}
public class CheomseongdaeEx1 {
public static void main(String[] args) {
//Cheomseongdae cheom1 = new Cheomseongdae(); //싱글톤이므로 새 객체 생성 불가
//Cheomseongdae cheom2 = new Cheomseongdae();
Cheomseongdae cheom1 = Cheomseongdae.getInstance(); //getInstance()로 외부에서 객체 받기
Cheomseongdae cheom2 = Cheomseongdae.getInstance();
if (cheom1==cheom2) {
System.out.println("같은 첨성대 객체");
}else {
System.out.println("다른 첨성대 객체");
}
cheom1.history();
cheom2.history();
}
}
//
같은 첨성대 객체
경주
경주
=> 하나의 객체(싱글톤) 가리킴
어노테이션
= 메타데이터 (정보)
1. 컴파일러에 문법 에러 체크하도록 정보 제공
2. 소프트웨어 개발 툴이 코드 자동 생성하도록 정보 제공
3. 실행 시 기능 실행하도록 정보 제공
https://velog.io/@jkijki12/annotation
[Java] 어노테이션이 뭔데??
자바 어노테이션에 대해서 공부하자!!
velog.io
- 내장 어노테이션
@Override
int witdhraw(int amount) throws Exception { //오류 발생 => 오타 방지
- 커스텀 어노테이션
new - Annotation - Add @Retention-Runtime & Add @Target
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RUNTIME)
public @interface PrintAnnotation {
String value() default "#"; //값 전달받지 않으면 default로 # 출력
int number() default 20;
}
public class Service {
@PrintAnnotation
public void corona() {
System.out.println("코로나 박멸!");
}
@PrintAnnotation("*") //PrintAnnotation.class value값 변경
public void corona2() {
System.out.println("오미크론 박멸!");
}
@PrintAnnotation(value="$", number=30) //PrintAnnotation.class value, number 값 변경
public void corona3() {
System.out.println("변이 코로나 박멸!");
}
}
import java.lang.reflect.Method;
public class ServiceEx1 {
public static void main(String[] args) {
Method[] methods = Service.class.getDeclaredMethods();
//서비스 클래스에서 만들어진 메소드 정보 얻음
for (Method m : methods) {
if (m.isAnnotationPresent(PrintAnnotation.class));
PrintAnnotation print = m.getAnnotation(PrintAnnotation.class);
System.out.println("***"+m.getName()+"***"); //메소드이름 (corona) 출력
for (int i=0;i<print.number();i++) {
System.out.print(print.value());
}
System.out.println();
try{
//메소드 호출
m.invoke(new Service());
//메소드 안 내용 출력 요구 //try catch 필수(null의 가능성)
}catch(Exception e) {
System.out.println("메소드 처리 에러");
}
}//외부for
}
}
//
***corona***
####################
코로나 박멸!
***corona3***
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
변이 코로나 박멸!
***corona2***
********************
오미크론 박멸!
'Programming > 자바' 카테고리의 다른 글
자바 재정리 - 인터페이스 (0) | 2022.08.25 |
---|---|
자바 재정리 - 상속 (0) | 2022.08.23 |
자바 재정리 - 참조 (0) | 2022.08.05 |
생활코딩 자바 - Collections framework (0) | 2022.04.24 |
생활코딩 자바 - 제네릭 (0) | 2022.04.20 |