ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 221209. 자바4 (객체지향 프로그래밍, 클래스, 메소드, 변수, static, 오버라이딩, 호출스택)
    스타터스 백엔드 3기 2022. 12. 9. 17:09

    하루입니다.

    chap6 : EmployeeTest, EmployeeArrayTest, MemberLocalTest, StaticTest,  MethodTest, CallByValueTest, OverloadTest, test1


     

     

    객체지향 프로그래밍

    1. 객체가 가진 정적 특성과 동적 특성을 파악해야 한다.

        정적 특성 - 변수로 표현, 동적 특성 = 메소드로 표현

    2. 클래스 구조 정의 : 변수 + 메소드

    3. 클래스로부터 변수와 메소드를 복사해서 메모리에 할당한다. 이걸 instance라고 한다. \

    4. 객체 안에 인스턴스가 포함된다. 객체는 현실 명사까지 포함하는 것,

        과정을 진행하는 동안 객체 = 인스턴스로 말한다.

     

     

     

     

    객체지향언어의 장점

    • 객체 단위로 구성되어 객체 내부를 일부 변경시 해당 객체만 변경된다. 코드 관리가 쉽다.
    • 객체의 재사용이 쉽다.

     

     

     

    클래스 작성  예시

    • 소스파일의 이름은 public class의 이름과 일치해야 한다.
    • 하나의 소스파일에 두 개 이상의 public class가 존재할 수 없다. 
    • 같은 패키지 안에서 클래스 이름은 겹치면 안 된다. 

     

     

     

    객체를 생성하면 일어나는 일

    Employee e1 = new Employee();		// e1 = 참조변수
    // 클래스명 변수명 = new 클래스명();			객체생성
    // new : 객체생성연산자 (heap영역에 클래스의 복사본을 할당한다.)
    e1.id = 100;			 // 객체주소참조변수명.객체변수명
    e1.name = "이사원";
    e1.title = "사원";
    e1.dept = "it개발부";
    e1.salary = 10000;
    • e1(stack)을 만들면 heap 영역에 id, name, salary, dept, salary가 만들어진다. 
    • 자바 내부에서 객체를 생성하면(클래스를 복사하면) 변수값이 자동 초기화된다. 
    • 변수값의 자동 초기화
    • boolean은 false,char은 '\u0000'(공백임), int는 0, double은 0.0이다. 참조형변수들은 null으로 자동 초기화된다.
    • 변수들을 100번지 안에 묶어두고, 그 번지를 e1에 할당했다.
    • e1.name 형태로 조회하거나 수정 가능하다.

     

     

    객체배열

    Employee arr[] = new Employee[10];
    
    Employee e1 = new Employee();		
    e1.id = 100;			 
    e1.name = "이사원";
    e1.title = "사원";
    e1.dept = "it개발부";
    e1.salary = 10000;
    arr[0] = e1;
    
    for(int i = 0; i < arr.length; i++) {
        System.out.printf("사번 %d번, 이름 %s, 직급 %s, 부서명 %s, 급여 %.2f입니다. \n",
    arr[i].id, arr[i].name, arr[i].title, arr[i].dept, arr[i].salary);
    }

     

     

     


     

     

    클래스란?

    객체는 변수와 메소드의 묶음 단위이다.

    사용자가 정의하는 타입 중 하나이다.

     

    자바의 클래스구조

    [modifier] class 클래스이름 [extends ... ] [implements ... ] {

            [modifier] 변수;

            [modifier] 메소드;

            [modifier] 생성자;

            [modifier] 내부클래스;

    }

     

     

    [modifier] 란?

    자바의 요소 앞에 선언되는 해당 요소의 접근제한, 활용방법 제시 키워드이다.

    역할 modifier 클래스 변수 메소드 생성자
    접근제한 public O O O O
      protect X O O O
      private X O O O
    활용방법 static X O O X
      final O O O X
      abstract O X O X
    기타     tramsient
    volatile
    native
    synchronized
     

     

     


     

     

    변수란?

    메소드 외부 - 멤버변수 non-static 변수 = 객체변수(인스턴스 변수) X
      static 변수 = 클래스변수 static
    메소드 내부 지역변수   메소드 내부
      매개변수 : 전달받은 변수 { } 블록 내부

     

     

     

    static

    자바 클래스가 실행(run) 되면

    1. 컴파일한다. 문법 오류를 검사한다. 이후 실행오류를 검사한다.

        만약 class A 를 다운받아서 실행한다. 그런데 class A는 class B를 사용한다. 그러면 class B가 없기에 실행오류가 발생한다.

    2. static 변수를 찾아서 메모리에 할당한다.

        객체끼리 static 변수를 공유하기 위해서는 , 객체가 생기기 전에 생성되어야 한다. 클래스영역(공유영역)

    3. main 메소드를 실행한다.

        객체를 생성하는 문장을 실행한다.

     

     

    내가 헷갈린 부분 : 왜 static인데 stu.name = args[0]; 하면 값이 바뀌지?

    static이라고 값이 바뀌지 않는 게 아니다. 한 class의 객체들이 공동으로 사용할 수 있는 값을 만들어서 메모리에 저장한 것 뿐이다. 내가 직접 지정했으니 바뀔 수 있는 거다 (아마도 ?)

     

    내가 생각한 건 static final NAME 이거였다. 이거는 바꾸려는 시도 하면 컴파일 오류(빨간 거) 뜬다.

     

    static 변수

    • 모든 객체가 공통값을 저장하기 때문에 사용한다. 만약 static을 사용하지않으면 메모리에 여러개가 생성될 것이다. 메모리에 한 개만 만들고 공유해서 사용하자.
    • 변수명 = 클래스명.static 변수명 으로 적고 사용한다.
    • 메소드는 static 변수 전용 사용 메소드를 사용하자.
    • static 변수만 사용하는 메소드라면 static 메소드로 정의해야 한다.

     

     

    non-static 변수 (일반적인 거)

    • 여러 객체마다 서로 다른 값을 가진다.
    • 객체참조변수명.non-static 변수명
    • static 변수 +  non_static 변수를 사용하거나, non-static 변수만 사용하는 경우는 non-static 메소드를 정의한다.

     

     

    STATIC 예시 1번

    class Person {
    	String name;
    	int age;
    	static String nation = "한국";
    }
    
    public class StaticTest {
    	public static void main(String[] args) {
        	System.out.println("모든 사람의 국적은 " + Person.nation + "입니다.")
    		Person p1 = new Person();
    		p1.name="홍";
    		p1.age = 22;
    		
    		System.out.println(p1.name + "," + p1.age + "," + p1.nation);
    		
    		Person p2 = new Person();
    		p2.name="김";
    		p2.age = 21;
    		
    		System.out.println(p2.name + "," + p2.age + "," + p2.nation);
    	}
    }
    
    Person 객체 내부에서 공유되는 거니까
    Person.nation        p1.nation       으로도 사용이 가능하다!!! 대박!!!!

     

    • class영역. 모든 객체들이 공유 가능한 영역이다. 1개 메모리를 할당해서 모든 객체의 공통값으로 쓴다.
    • 1000번지 : static nation = "한국";
    • 이미 nation 있기에 Person으로 만들어진 객체들의 nation은 class의 static nation을 사용한다.

     

     

     

     

    static 예시 2번

     


     

     

    메소드와 지역변수와 매개변수와 this

    • 메소드 안에는 지역변수가 있다. 
    • 필요에 따라 매개변수를 전달받을 수 있다.
    • 같은 이름이 없을 때, id name 이렇게만 적어도 Employee의 id와 name을 가리킨다.
    • 그렇다면 밑의 코드처럼 변수명이 중복된 상황에서 id, name, title은 누구를 가리킬까?

     

    class Employee {
    	int id;
    	String name;
    	String title;
    	
    	void printInform(String name) {
    		int id = 1000;
    		System.out.printf("사번 %d번, 이름 %s, 직급 %s입니다. \n", id, name, title);
    	}
    }

     

    그냥 id라고 적으면 포함된 메소드 안의 지역변수 id를 가리킨다.

     

     

    this.id라고 적으면 포함된 클래스의 멤버변수 id를 가리킨다.

     

     

    this.id라고 하면&nbsp;포함된 클래스의 멤버변수 id를 가리킨다.

     

     

    name이라고 입력하면 자신이 포함된 메소드의 매개변수인 name을 가리킨다.

     

     


     

     

    매개변수

    기본형 : stack에 저장되는 값은 실제값이 복사된 값이다.

                 전달 이후(add{}) 메소드 내부의 매개변수값(i)을 변경해도 인수(j)는 변경되지 않는다.

    참조형 : stack에 저장되는 값은 주소값이 전달되는 값이다. (객체도 이와 같은 방식으로 전달된다.)

                 인수(main_d)를 매개변수(d)로 "주소"를 복사해(200)서 전달하면 인수와 매개변수는 동일한 객체를 참조한다.

                 인수가 참조하는 객체의 내부 변수값(main_d.k)이 변경되면 매개변수참조객체의 내부 변수값(d.k)이 변경된다. 

     

     

     

    1. 기본형 변수 전달 테스트 코드

    메소드가 호출되며 메모리에 i값이 생긴다. j의 값인 10을 복사해서 i에 넣는다.

    syso(i++) 일 때, i값 출력 후 값을 1 더한다. syso 후 i의 값이 11로 바뀐다.

    public class CallByValueTest {
        public static void main(String[] args) {
            C c1 = new C();
            int j = 10;
            c1.add(j); 
            System.out.println("main에서 add 종료 후 j =" + j);
        }
    }
    class C {
        void add(int i) { // 매개변수 == 입력변수
            System.out.println(i++);
        }
    }
    i = 10;
    (메소드가 호출될 때 생성되며, 메소드가 종료되면 사라진다.)

    j = 10;

     

     

    2. 참조형 변수 전달 테스트 코드

    public class CallByValueTest {
           public static void main(String[] args) {
                   C c1 = new C();
                    Data main_d = new Data();
                    System.out.println("main에서 addData 시작 전 main_d =" + main_d.k);

                   c1.addData(main_d);
                    System.out.println("main에서 addData 종료 후 main_d =" + main_d.k);
            }
    }
      Data와 main_d가 같은 곳을 바라보고 있어서 값이 변한 거임!!!

    main_d의 200번지를 복사해온다. d가 200번지를 가지고 있으니 따라가서 k를 찾고, k의 값을 11로 증가시킨다.

     

     

     

     


     

     

    호출스택

     

      stack

    가장 늦게 실행된 게 가장 먼저 끝난다.

    와!!!!!!!
    이걸 왜 다른 곳에서 못 쓰냐면!!!
    메소드가 호출되며 지역변수들이 호출되고, 호출이 끝나면 지역변수들이 아예 stack에서 사라지기 때문에 다른 곳에서 사용할 수 없던 거였어!!!!!!!!!!!!!!!!!!!!

    와 

    소름돋아 ...

    왜 지역변수를 다른데서 못 쓰는지 이해헀다!!!!!!!!!!

    main 실행 main 지역변수
    B mb() 실행 mb() 지역변수
    main 지역변수
    A ma() 실행 ma() 지역변수
    mb() 
    지역변수
    main 지역변수
    A ma() 종료 ma() 지역변수
    mb() 
    지역변수
    main 지역변수
    B mb() 종료 mb() 지역변수
    main 지역변수
    main 종료 main 지역변수

     

     

     


     

     

    메소드란?

    입력변수를 받고, 기능을 나타내고, 결과를 return하는 것이다.

    class A {
    	[modifier]리턴타입 test( [매개변수] ) {
        	지역변수 있을 수도 있다;
        	"기능" (입력변수/수행결과) 표현 순차 문장;
            [ return 결과표현변수 ]
        }
    }

     

    class Employee {
    	// 회사원을 정적으로 나타내는 요소들, 객체변수.
    	String name;
    	String title;
    	String dept;
    	double salary;
    	
    	void printInform() {
    		System.out.printf("사번 %d번, 이름 %s, 직급 %s, 부서명 %s, 급여 %.2f입니다. \n",
    				this.id, this.name, this.title, this.dept, this.salary);
                    // this 적는 이유는 e1.name이 될지 e2.name이 될지 모르기 때문이다.
                    id, name, title, dept, salary);
                    // 이렇게 해도 된다.
    	}
    }

     

     

     

    내 클래스 안의 메소드 / 타 클래스 안의 메소드 사용하는 법

    class A {
       void m1(){}
       void m1(){ m1(); }
    }
    class B {
        main() {
             A a1= new A();
             a1.m1();
        }

    }

     

     

     

     


     

     

    오버로딩 overloading 다형성!

    • 보통 메소드는 기능을 대표하는 이름으로 준다.
    • 1개 클래스 안에 이름이 같은 여러개의 메소드를 정의할 수 있다.
    • 매개변수의 개수, 타입, 순서 중 하나 이상 다르게 정의해야 한다.
    • 같은 기능을 매개변수의 형태에 따라 여러개의 기능을 선택하도록 할 수 있다.

     

    class D {
    	int add(int i, int j){
    		return i + j;
    	}
        
    	String add(String i, String j){
    		return i + j;
    	}
        
    	double add(double i, double j){
    		return i + j;
    	}
    }
    
    public class OverloadTest {
    	public static void main(String[] args) {
    		D d = new D();
    		System.out.println(d.add(1, 2));		// 3
    		System.out.println(d.add(1.0, 2.0));		// 3.0
    		System.out.println(d.add("1", "2"));		// 12
          	  	System.out.println(d.add(1, 2.5));	// int가 double로 자동형변환 가능해서 오류 발생하지 않는다.
    		System.out.println(d.add(1, 'a'));	// char가 int로 자동형변환 가능해서 오류 발생하지 않는다.
    		  System.out.println(d.add("1", 2.5)); 	// String이 double로 자동형변환 불가해서 오류 발생한다.
    	
    <형변환 오버로딩 메소드>
        		System.out.println(Integer.parseInt("100", 2));		// 2진수 변환 0 1
    		System.out.println(Integer.parseInt("153", 8));		// 8진수 변환 0 ~ 8
    		System.out.println(Integer.parseInt("13DF", 16));	// 16진수 변환
        
        }

     

     

     


     

     

    짱잼!!!!!

     

     

     

Designed by Tistory.