자바 기초문법 S2

‍정진철·2022년 7월 4일
0

자바 문법

목록 보기
2/2

1. 객체지향프로그래밍

  1. 상태와 행위로 이루어진 객체를 만드는것.
    --> 마치 레고 블럭처럼 조립해서 하나의 큰 프로그램을 만듦.

  2. 추상화
    --> 복잡한 현실을 소프트웨어적으로 구현하는 행위 (ex.지하철맵)

  3. 은닉화/캡슐화
    --> 내부의 동작방법을 단단한 케이스(객체)안에 숨기고 사용자에게는 그 부품의 사용법만을 노출.

  4. 클래스/인스턴스/객체
    1) 중복의 제거: 메소드사용

package test;

public class javatest {
	public  static void sum(int left , int right) {
		System.out.println(left + right);
}

public static void main(String[] args) {
		sum(10,20);
		sum(20,40);
	
	}
}

2) 객체화
--> 객체는 변수와 메소드의 집합인 하나의 "프로그램"이라고 여기자.

package test;

class Calculator {
	int left,right; 
	
	public void setOperands(int left, int right) {
		this.left = left;
		this.right = right;
	}
	public void sum() {
		System.out.println(this.left + this.right);
		
	}
	public void avg() {
		System.out.println((this.left + this.right)/2);
	}
	
}

public class CalculatorDemo {	
	public static void main(String[] args) {
		Calculator c1 = new Calculator();
		c1.setOperands(10,20);
		c1.sum();
		c1.avg();
		
		Calculator c2 = new Calculator();
		c2.setOperands(20,40);
		c2.sum();
		c2.avg();
		
	}
}

--> this : 클래스 Calculator의 객체 'c1'을 뜻함.
따라서 this.left와 this.right는 class를 생성할 때 초입에서 생성한 int left , int right 변수를 의미한다.
Ex) c1.setOperands(10,20)에서 10,20은 각각 setOperands함수의 파라미터(int left , int right)안에 할당이되고 this.left,right는 class의 전역변수인 int left,right가 되는것이다.

3) 클래스변수
인스턴스 - 클래스맴버
변수,메소드 - 인스턴스맴버

class Calculator {
	static double PI = 3.14; 
	int left,right; 
  • static 이 붙으면 클래스 소속 변수가 된다는것을 의미하고,
    클래스 소속 변수가 된다는것은 해당 변수를 모든 인스턴스에서
    동일한 값으로 가져오게 된다는 것이다.
package test;

class Calculator {
	static double PI = 3.14; (클래스맴버)
	static int base = 0;  (클래스맴버)
    int left,right; 
	
	public void setOperands(int left, int right) {
		this.left = left;
		this.right = right;
	}
	public void sum() {
		System.out.println(this.left + this.right + base);
		
	}

	
}

public class CalculatorDemo {	

		Calculator c1 = new Calculator();
		c1.setOperands(20,40);
		c1.sum(); ==> '60'출력
        
        Calculator c2 = new Calculator();
        c2.setOperands(30,50);
        c2.sum(); ==> '80'출력
        
        Calculator.base = 10;
        
        cl.sum();   ==> '70'출력
        c2.sum();   ==> '90'출력
		
}
  • 클래스 변수를 사용하는 때 :
    1) 인스턴스 불문 고정된 값이 필요할 경우 ( 위에서는 PI , base)
    2) 추가적으로 인스턴스를 생성하지 않고도 가져오고 싶은 값이 있을때
    3) 특정 값의 변화를 모든 인스턴스가 공유해야할 때

4) 클래스 메소드

package test;

class Calculator {
	
	public static void sum(int left, int right) {
		System.out.println(left+right);
	}
	public static void avg(int left, int right) {
		System.out.println((left+right)/2);
		
	}
}
public class CalculatorDemo {	
	
	public static void main(String[] args) {
		Calculator.sum(10,20);
		Calculator.avg(10,20);
		
		Calculator.sum(20,40);
		Calculator.avg(20,40);
		
	}
}
  • 해당 코드는 c1,c2라는 인스턴스 생성"없이" 곧바로 클래스명.메소드의 형식으로된 코드이다.
    일회용 물품처럼 단순 1회만 사용하는 목적이면 굳이 인스턴스를 생성해 메모리를 차지하기보다는 클래스와 클래스메소드를 사용하는것이 더 효율적이다.

5) 타입별 비교

package test;

class C1 {
	static int static_variable = 1; //static이 붙어있으므로 클래스변수.
	int instance_variable = 2;  //static이 없으므로 instance 변수.
	static void static_static() { //클래스메소드(static)가 클래스변수(static)를 호출할 때.
		System.out.println(static_variable); 
}

static void static_instance() {  
	//클래스 메소드에서는 인스턴스 변수에 접근 할 수 없다.
	//System.out.println(instance_variable);
}
void instance_static() {  //인스턴스 메소드 (static이 없는것)
	//인스턴스 메소드에서는 클래스멤버에 접근가능.
	System.out.println(static_variable);
}
void instance_instance() { //인스턴스 메소
	System.out.println(instance_variable);
}

public class ClassDemo {
	public static void main(String[] args) {
		C1 c = new C1() ;
		
		c.static_static() ;  //인스턴스변수는 클래스메소드에 접근가능.
		
		c.static_instance() ; //인스턴스변수는 static메소드에 접근불가.
        //static메소드와 class static메소드는 다름.
        //인스턴스변수가 class static메소드에는 접근가능하지만 단순 static메소드에는 접근불가.
        
		
		c.instance_static(); //인스턴스변수는 static클래스변수에 접근가능.
		
		c.instance_instance(); // 인스턴스변수는 인스턴스메소드에 접근가능.
        
        c1.static_static() ; //클래스자체(인스턴스아님)c1은 클래스메소드에 직접 접근가능.
        
        c1.static_instance() ; //클래스c1은 static메소드에 접근불가.
        c1.instance_static() ; // 클래스c1은 인스턴스가 아니므로 인스턴스메소드에 접근불가.
        c1.instance_instance(); //클래스c1은 인스터스가 아니므로 인스턴스메소드에 접근불가.
	}
  }
}

6) 용어
인스턴스변수 -> Non-static Field
클래스변수 -> static Field


2. 유효범위

  • class 내에서 Static 함수 위에 선언된 static int i 는 전역변수
    static void a() 라는 함수안에 선언된 int i 는 지역변수이다.

따라서 오른쪽 그림의 i는 전역변수이므로 main함수를 실행시킬때 a()함수역시 실행되고 a라는 함수에는 i가 0 이므로 for문의 i 즉 0 이 무한 출력되는것이다. 이것은 i가 전(지)역 변수이므로 모든 함수에 적용되는 변수이기 때문이다.

  • 하지만 함수 a의 변수 i를 int i = 0; 으로 설정해주면 전역변수 int i 랑은 다른 int i다. 즉 a함수내에서 끝나는 지역변수이다.

  • 이와 마찬가지로 for문에서 i 대신 int i = 0; 으로 설정시 i는 for문 '내'에서만 존재하는 i이므로 a함수의 i랑은 상관이 없다.

2. 유효범위 - 다양한 유효범위

1)
public class javatest {
	static void a() {
		String title = "coding everybody";
	
	 }
	
	public static void main(String[] args) {
    a();
	System.println(title);
    
    -> title 출력불가능.
    title은 지역변수이므로 main함수입장에서는 인지할 수 없음.
	}
}
2)
public class javatest {
	public static void main(String[] args) {
		for(int i=0; i<5; i++) {
			System.out.println(i);
		}
        
		System.out.println(i);
        -> i 출력불가능 , i는 for문의 중괄호안에서만 존재.
        
	}
}
3)
public class javatest {
	static int i = 5;
	
	static void a() {
		int i = 10;
		b();
	}
	static void b() {
		System.out.println(i);
        
        -> i는 함수b의 유효범위 내 존재하는 i로 값이 할당됨.
        따라서 함수 b에 예를들어 지역변수 int i = 33; 이 선언되어있다면 
        33을 출력할것이고 지역변수가 없다면 전역변수를 끌어와 5를 출력할 것이다.
        
	}
	public static void main(String[] args) {
		a();
	}
}
  • 위와같은 유효범위를 '정적인 유효범위'라 일컫는다.

2. 유효범위 - this.

class C {
	int v  = 10;
	
	void m() {
		int v = 20;
		System.out.println(v);
        System.out.println(this.v);
	}
}

public class javatest {
	public static void main(String[] args) {
		C c1 = new C();
		c1.m();
	}
}
  • 이와같은 상황에서는 전역변수vs지역변수 형태인데 이와같은 경우엔 지역변수가 이기므로 20을 출력한다.

  • System.out.println(this.v);
    this -> 인스턴스에 대한 '전역'의 의미를 갖게됨. (10 출력)

class Calculator {
	static double PI = 3.14;
	int left, right;
	
	public void setOperands(int _left , int _right) {
		left = _left;
		right = _right;
	}
}
  • this를 사용하지 않고 전역변수에 값을 할당하는 방법은 setOperands함수의 파라미터들에게 '_'(언더바)를 붙여주는것이다. 이렇게되면 left,right는 전역변수로서 존재하는 아이들밖에 없으므로 자동적으로 _left, _right의 값이 left,right(전역변수)로 들어가게된다.

3. 생성자


class Calculator {
	int left, right;
	
    //생성자
	public Calculator(int left , int right) {
		this.left = left;
		this.right = right;
	
}

public void sum() {
	System.out.println(this.left + this.right);

}

public void avg() {
	System.out.println((this.left + this.right)/2);
}

public class CalculatorDemo {
	public static void main(String[] args) {
		Calculator c1 = new Calculator(10,20);
		c1.sum();
		c1.avg();
	}
}



}
  • setOperands와 같이 파라미터에 값을 할당하는 함수를 따로 만들지 않고도 클래스를 만들때부터 인자값을 줄 수 있도록 하기위해서 '생성자'(Constructor)를 만든다. 이때 주의점은 클래스명과 생성자의 이름이 완벽히 동일해야한다.

  • 생성자는 그 어떠한 메소드보다 먼저 실행되므로 '초기화' 작업을 실행할 수 있다.

  • Cacluator c1 = new Calculator(10,20); 에서 new 뒤에 붙는 Calculator는 클래스가 아닌 생성자를 의미. 즉, new Calculator(생성자)를 이용해 인스턴스 클래스명이 Calculator인 인스턴스 c1을 만드는것이다.


4 상속

class Calculator {
	int left, right;
	
	public Calculator(int left , int right) {
		this.left = left;
		this.right = right;
	
}

public void setOperands(int left , int right) {
	this.left = left;
	this.right = right;
}

public void sum() {
	System.out.println(this.left + this.right);

}

public void avg() {
	System.out.println((this.left + this.right)/2);
}



//상속

class SubtractionableCalculator extends Calculator {
	pulbic void subtract () {
		System.out.println(this.left - this.right);
	}
}
public class CalculatorDemo {
	SubtractionableCalculator c1 = new SubtractionableCalculator() ;
	
	c1.setOperands(10,20);
	c1.sum();
	c1.avg();
	c1.subtract();
}
}

또한 상속받은것을 재상속 받을 수 도 있음.

class MultiplicationableCalculator extends SubtractionableCalculator() {
	public void Multiple() {
		System.out.println(this.left * this.right);
	}
}

5. 상속과 생성자 : 기본생성자

public class Constructor {
	public Constructor() {
	public Constructor(int param1) {}
	public static void main(String[] args) {
		Constructor c = new Constructor() ;
	}
	}
}
  • 해당 인스턴스는 매개변수를 받지않는다. 따라서 만약 생성자가 파라미터를 가지는 생성자라면 받지않는 생성자를 만들어주어야한다.

5. 상속과 생성자 : super

class Calculator {
	int left, right;
	
	public Calculator(int left , int right) {
		this.left = left;
		this.right = right;
	
}

public void setOperands(int left , int right) {
	this.left = left;
	this.right = right;
}

public void sum() {
	System.out.println(this.left + this.right);

}

public void avg() {
	System.out.println((this.left + this.right)/2);
}




class SubtractionableCalculator extends Calculator(int left, int right) {
	}
    	this.left = left;
        this.right = right;
--> 지금은 상위클래스의 생성자와 하위클래스의 생성자가 동일. 즉, 중복된다.
따라서 하위클래스가 상위클래스의 생성자를 그대로 받고 싶으면
super(left, right); 라고 해준다.
    
	pulbic void subtract () {
		System.out.println(this.left - this.right);
	}
}
  • super : 부모클래스를 의미.
    ( ) : 부모클래스의 생성자.
    left -> int left (하위클래스 매개변수)
    right -> int right ( //)

6. 오버라이딩(overriding)

부모가 가진 메소드를 자식이 나름대로의 변형을 통해 "재정의" 한다.

1)
class SubtractionableCalculator extends Calculator(int left, int right) {
	}
    	this.left = left;
        this.right = right;

    
	public void subtract () {
		System.out.println("실행 결과는 " + (this.left - this.right) + "입니다");
	}
}


2)
class Calculator {
	int left, right;
	
	public Calculator(int left , int right) {
		this.left = left;
		this.right = right;
	
}

public void sum() {
	System.out.println(this.left + this.right);

}

public void avg() {
	System.out.println((this.left + this.right)/2);
}




class SubtractionableCalculator extends Calculator {
	
	public int avg() {
		return ((this.left - this.right) /2);
	}
  }
}
  • 2)와같은 경우에는 부모클래스의 avg함수의 리턴값(void)과 자식클래스의 avg함수의 리턴값(int)이 다르다.

오버라이딩 만족조건:
1) 메소드 이름
2) 메소드 매개변수 숫자, 데이터타입 , 순서
3) 리턴타입이 모두 동일!


3)
public int avg() {
 	return ((this.left + this.right)/2);
}

class SubtractionableCalculator extends Calculator {
	
	public int avg() {
		return ((this.left - this.right) /2);
	}
  }

3)과 같은경우는 avg함수가 부모,자식클래스간에 동일하게 적용된다. 중복되므로 자식클래스에서 return super.avg(); 라고 하면 부모클래스의 메소드를 적용받을 수 있게된다.


7. 오버로딩(overloading)

public void sum(int a , int b ) {
	System.out.println(a + b);

}

public void sum(int a , int b , int c) {
	System.out.println(a+b+c);

}
  • 함수이름은 같으나 매개변수의 개수나 타입이 다를때 오버라이딩한다고 한다.
    자바는 메소드명이 동일할지라도 매개변수의 개수나 타입이 다르면 '다른' 메소드로 인식한다.
class overloading {
	void A() {System.out.println("void A()");} 
	void A(int arg1) {System.out.println("void is A(int arg1)");}
	void A(String arg1) {System.out.println("void A(String arg1)");}
	
    //int A() {System.out.println("void A()");}
    -->리턴값이 다르므로 오버로딩 불가.
	
	public static void main(String[] args) {
		overloading od = new overloading() ;
		od.A();
		od.A(1);
		od.A("I love you");
	}
}
  • 추가적으로 void A(int param1) 과 같이 파라메터의 이름만 바꾼다고해서 다른 메소드로 취급x, 컴퓨터가 구분 못함.

public class overloading2 extends overloading {
	void A(Stirng arg1, Stirng arg2) {System.out.println("sub class: void A()");} 
	void A() {System.out.println("sub class: void A()");}
	
	public static void main(String[] args) {
		overloading2 od = new overloading2() ;
		od.A();
		od.A(1);
		od.A("I love you");
		od.A("I love you", "you too?");
	}
}
  • void A(Stirng arg1, Stirng arg2) 함수는 부모클래스를 "오버로딩"함.
    (이름은같음 but 매개변수의 개수가 다름.)
  • void A() 는 부모클래스의 메소드와 동일하므로 "오버라이딩"
    (오버라이딩은 부모클래스의 매소드이름, 리턴타입, 매개변수개수,타입이 모두 일치하면서 리턴하는 내용만 달라지게끔 하는것.) -> 부모클래스에 그대로 탑승.

8. 패키지

package org.opentutorials.javatutorials.packages.example2;
import org.opentutorials.javatutorials.packages.example1.A;
-> 클래스A만 import (B는제외)
만약 모든 클래스를 소환하고 싶으면 '*' 사용

public class B {
	public static void main(String[] args) {
		A a = new A();
	}
}

  • 클래스 A는 example.1 패키지
    클래스 B는 example.2 패키지에 들어있다.
    위 코드에서 example2는 현재 불러온 상태이고 example1에 들어있는 클래스A 즉 현재 패키지에는 없는 클래스를 불러오고 싶은것이다.
    해결법: import
profile
WILL is ALL

0개의 댓글