카테고리 없음

자바의 정석 chapter6 정리

from-alien 2023. 6. 17. 17:04

자바의 정석 정리

객체지향 언어의 주요특징

코드의 재사용성의 높다.-> 새로운 코드를 작성할 때 기존의 코드를 이용하여 쉽게 작성할 수 있다.

코드의 관리가 용이하다. → 코드간의 관계를 이용해서 적은 노력으로 쉽게 코드를 변경할 수 있다.

신뢰성의 높은 프로그래밍을 가능하게 한다-> 제어자와 메서드를 이용해서 데이터를 보호하고 올바른 값을 유지하도록 하며, 코드의 중복을 제거하여 코드의 불일치로 인한 오동작을 방지할 수 있다.

코드의 재사용성이 높고 유지보수가 용이하다.

->객체지향개념에 얽매여서 고민하기 보다는 일단 프로그램을 기능적으로 완성한 다음 어떻게 하면 보다 객체지향적으로 코드를 개선할 수 있을지를 고민하여 점차 개선해 나가는 것이 좋다.

클래스로부터 객체를 만드는 과정을 클래스의 인스턴스화라고 한다. 어떤 클래스로부터 만들어진 객체를 그 클래스의 인스턴스라고 한다.

클래스 ->인스턴스화-> 인스턴스(객체)

객체는 속성과 기능, 두 종류의 구성요소로 이루어져 있으며, 일반적으로 객체는 다수이 속성과 다수의 기능을 갖는다. 객체는 속성과 기능의 집합이라고 할 수 있다.

객체가 가지고 있는 속성과 기능을 그 객체의 멤버라고 한다.

속성 : 멤버변수, 특성, 필드, 상태

기능: 메서드, 함수, 행위

 

 

★인스턴스의 생성과 사용

 

클래스명 변수명;
변수명 = new 클래스명();

Tv t;
t = new  Tv();

 

Tv 클래스 

class Tv{

	String color;
    boolean power;
    int channel;
    
    
    void power() {
    	power != power;
    }
    void channelUp(){
    	++channel;
    }
    void channelDown(){
    	--channel;
    }
}





class TvTest{
	public static void main(String args[]){
    	Tv t; // Tv인스턴스를 참조하기 위한 변수 t를 선언
        t = new Tv(); // Tv 인스턴스를 생성
        t.channel = 7;  //Tv의 인스턴스의 멤버변수 channel의값을 7로 한다.
        t.channelDown();
    
    
    }
	


}

 

 

★인스턴스는 참조변수를 통해서만 다룰 수 있으며, 참조변수의 타입은 인스턴스의 타입과 일치해야한다.

 

class Tv{

	String color;
    boolean power;
    int channel;
    
    void power(){
    	power= !power;
    }
    void channelUp(){
    	++channel;
    }
    void channelDown(){
    	--channel;
    }
}


class TvTest3{
	public static void main(String args[]){
    	Tv t1 = new Tv();
        Tv t2 = new Tv();
        System.out.println("t1의 channel 값 " + t1.channel);//0
    	System.out.println("t2의 channel 값 " + t2.channel);//0
        
        t2 = t1;//t1은 t2에  t1이 저장하고 있는 주소를 t2에 저장을 한다.
        
        t1.channel = 7;
        
        //t1.channel, t2.channel의 출력 값은 둘다 7로 변한다.
        
        
        
    }


}

 

 객체 배열 : 객체 역시 배열로 다루는 것이 가능하며, 이것을 객체 배열이라고 한다.

객체 배열 안에 객체가 저장되는 것은 아니고 객체의 주소가 저장된다.

 객체 배열 안에 객체가 저장되는 것은 아니고, 객체의 주소가 저장된다.

 

 

Tv[] tvArr = new Tv[3]하면 길이가 3인 참조변수 배열
Tv tv1, tv2, tv3; 있으면 vtArr[0],vtArr[1],vtArr[2] 이런식으로 선형적으로 null 값을 가지고 저장

 

 

객체를 생성해서 객체 배열의 각 요소에 저장하는 것을 잊으면 안 된다.

Tv[] tvArr = new Tv[3];

tvArr[0] =  new Tv();
tvArr[1] = new Tv();
tvArr[2] = new Tv();

//객체를 생성해서 배열의 각 요소에 저장

//객체의 수가 많으면 for문 사용 예시

for(int i =0; i <3;i++){
	tvArr[i] = new Tv();
}

 

class TvTest4{
	public static void main(String args[]){
    
    	Tv[] tvArr = new Tv[3];
        //객체 배열을 생성해서 각요서에 저장
        for(int i =0; i <tvArr.length; i++){
        
        	tvArr[i] = new Tv();
            tvArr[i].channel = i + 10;
        }
    }


}

 

 

 

 선언위치에 따른 변수의 종류

 

class Variables{
	int iv; // 인스턴스 변수
    static int cv; //클래스변수
    
    void method(){// 메서드 영역
    	int iv =0; //지역변수
    }
}

//변수의 생성시기
//클래스 변수 - 클래스가 메모리에 올라갈 때
//인스턴스변수 - 인스턴스가 생성되었을 때
// 지역변수 - 변수 선언문이 생성되었을 때

 

 

 인스턴스변수 

▶인스턴스는 독립적인 저장공간을 가지므로 서로 다른 값을 가질 수 있다. 인스턴스마다 고유한 상태를 유지해야하는 속성의 경우, 인스턴스변수로 선언한다.

 

클래스변수

▶인스턴스변수 앞에 static을 붙이기만 하면된다.

▶클래스 변수는 인스턴스변수와 달리 인스턴스를 생성하지 않고도 언제라도 바로 사용할 수 있다는 특징이 있다.

 

지역변수

▶메서드 내에 선언되어 메서드 내에서만 사용 가능, 메서드가 종료되면 소멸되어 사용할 수 없게 된다.

 

 

 

class Card{

	String kind;
    int number;
    static int width = 100;
    static int height =250;
}


class CardTest{
	public static void main(String args[]){
    	Card c1 = new Card();
        c1.kind ="Heart";
        c1.number = 7;
        
        Card c2 = new Card();
        c2.kind = "Spade"; // 인스턴스변수의 값을 변경한다.
        c2.number =4;
        
        c1.width = 50;//클래스변수의 값을 변경한다.
        c1.height = 80; 

    
    
    }


}

 

 

★객체지향에서 메서드의 이름을 지을 때는 함축적이면서 의미있는 이름을 짓도록 노력해야한다.★

 

 

class MyMathTest{

	public static void main(String args[]){
    
    	MyMath mm = new MyMath();
        
        long result1 = mm.add(5L, 3L);
        
    }

}


class MyMath{

	long add(long a, long b){
    	long result = a+b;
        return result;
    
    }
}

 선언된 메서드를 호출하는 방법이다.

divide(double a , double b){

           return a /b;

}

위와 같이 divide로 선언된 메서드는 매개변수로 int 형 숫자를 넣어도 같은 결과가가 나온다.

double a = 5L; 을 수행 했을 때 long형의 값인 5L은 double형 값인 5.0으로 자동 형변환되어 divide의 매겨변수 a에 저장된다.

divide 메서드에 두 개의 정수값(5L, 3L)을 입력하여 호출하였음에도 불구하고 연산결과 더블형에 값이 된다.

 

▶return 문은 현재 실행중인 메서드를 종료하고 호출한 메서드로 되돌아간다.

 

♣매개변수의 유형성 검사

메서드의 구현부{}를 작성할 때, 제일 먼저 해야 하는 일이 매개변수의 값이 적절한 것인지 확인하는 것이다.

메서드를 작성을 할 때는 호출하는 쪽에서 알아서 적절한 값을 넘겨주겠지 라고 생각하면 안 된다.

타입만 맞으면 어떤 값도 매개변술글 통해 넘어올 수 있기 때문에, 가능한 모든 경우의 수에 대해 고민하고 그에 대비한 코드를 작성 해야 한다.

 

예제

 

float divide(int x, int y){
	if(y==0){//작업을 하기 전에 나누는 수 y가 0인지 확인한다.
    	System.out.println("0으로 나눌 수 없습니다.");
        return 0;//매개변수가 유효하지 않으므로 메서드를 종료한다.
    }
	return x / (float)y;
}

 

 메서드 영역

▶ 프로그램 실행 중 어떤 클래스가 사용되면, jvm은 해당 클래스의 클래스파일을 읽어서 분석하여 클래스에 대한 정보를 이곳에 저장한다. 클래스 변수도 이 영역에 생성된다.

 

힙 

▶인스턴스가 생성되는 공간. 프로그램 실행 중 생성되는 인스턴스는 모두 이곳에 생성

 

호출스택

▶메서드의 작업에 필요한 메모리 공간을 제공 메서드가 호출되면 호출스택에 호출된 메서드를 위한 메모리가 할당 

▶메모리는 메서드가 작업을 수행하는 동안 지역변수들과 연산의 중간결과 등을 저장하는데 사용된다.

▶메서드가 작업을 마치면 할당되었던 메모리공간은 반환되어 비워진다.

 

 

메서드가 메모리에 스택을 할당 받는 순서

■ 메서드가 호출되면 수행에 필요한 만큼의 메모리를 스택에 할당받느다.

  메서드가 수행을 마치고나면 사용했던 메모리를 반환하고 스택에서 제거된다.

  호출스택의 제일 위에 있는 메서드가 현재 실행 중인 메서드이다.

  아래 있는 메서드가 바로 위의 메서드를 호출한 메서드이다.

 

 

 

참조형 반환타입

 

class Data {
	int x;
}

class ReferenceReturnEx{
	public static void main(String[] args){
    	Data d = new Data();
        d.x =10;
        Data d2 = copy(d);
        ///.... sout 출력시 d.x =10
        ///...... 출력시 d2.x =10
    }
    
    //메서드의 반호나 타입이 data 이므로 호출결과를 저장하는 변수의 타입 역시 data 타입의 참조변수
    static Data copy(Data d){
    	Data tmp = new Data();//새로운 객체 tmp를 생성
        tmp.x = d.x;//d.x 값을 tmp.x에 복사한다
        return tmp;//복사한 객체의 주소를 반환
    }
}

 

■ copy메서드를 호출하면서 참조변수 d의 값이 매개변수 d에 복사

■  새로운 객체를 생성하고 d.x엗 저장된 값을 tmp.x에 복사

■ copy 메서드가 종료되면서 반환한 tmp의 값은 참조변수 d2에 저장된다.

■ copy메서드가 종료되어 tmp가 사라졌지만 d2로 새로운 객체를 다룰 수 있다.

 

반환타입이 참조형 이라는 것은 메서드가 객체의 주소를 반환한다는 것을 의미한다.

 

 

 

클래스 메서드와 인스턴스 메서드

 

인스턴스 메서드는 인스턴스 변수와 관련된 작업을 하는 메서드의 작업을 수행하는데 인스턴스 변수를 필요로 하는 메서드이다. 메서드 중에서 인스턴스와 관계없는메서드를 클래스 메서드라고 한다. static

 

클래스의 멤버변수 중 모든 인스턴스에 공통된 값을 유지해야하는 것이 있는지 살펴 보고 있으면, static

작성한 메서드 중에서 인스턴스 변수나 인스턴스 메서드를 사용하지 안는 메서드에 static을 붙일 것을 고려한다.

 

class MyMath2{
	long a, b;
    long add(){return a+b;}
    long subtract{return a-b;}
    long multiply(){return a*b;}
    double divide(){return a/b;}
    ///상위 메소드 들은 인스턴스로 호출
    static long add(long a, long b){ return a+b;}
	static long subtract(long a, long b){ return a-b;}
    static long multiply(long a, long b){return a*b;}
    static double divide(double a, double b){return a/b;}
    
   
}


class MyMathTest2{
	public static void main(String args[]){
    
    	//인스턴스 없이 호출 가능예시 
        MyMath.add(200L, 100L);
        
        //인스턴스를 호출하고 호출가능한 메서드
        
        MyMath2 m = new MyMath2();
        m.a =200L;
        m.b = 100L;
        mm.add();
    }

}

 

 클래스 멤버와 인스턴스 멤버간의 참조와 호출

 

 

class MemberCall{
	int iv =10;
    static int cv = 20;
    
    int iv2 = cv;
    static int cv2 = new MemberCall().iv;//클래스 변수는 객체 생성의 방식
    //static int cv2 =iv 는 에러발생
    
    static void staticMethod1(){
    	// System.out.println(iv); // 클래스 메소드 안에서는 인스턴스 변수를 사용불가
        MemberCall c = new MemberCall();
        //c.iv 를 해야 객체 생성 후에 참조가 가능하다.
        c.instanceMethod1();//객체 생성 후에 호출이 가능하다.
    }
    
    void instanceMethod1(){
    	System.out.println(cv);
        System.out.println(iv);
        staticMethod1();//인스턴스 생성없이 호출 가능
    }
    

}