자바 문법

공부/Spring 2021. 10. 13. 21:10
반응형

배열

int [] nums;
int nums[];

int [] nums;
nums = new int[5];

int nums[] = {1, 2, 3}


 

생성자

생성자는 자바 클래스의 객체를 생성하기 위해 존재한다.

Test test = new Test();

생성자의 리턴타입은 클래스의 객체이다.

다른 생성자가 없을 경우 기본으로 컴파일할 때 만들어진다.

-> 다른 생성자가 있을 경우, 기본 생성자는 만들어지지 않음


 

메소드 overloading

이름은 같지만 매개변수가 다르다. 매개변수의 종류, 개수, 순서가 다르다.


 

static 메소드

객체를 생성하지 않아도 호출할 수 있다.

static => 클래스가 메모리에 올라갈때 할당된다.

 

자바에서는 하나의 클래스를 컴파일할 때, 관련된 클래스가 컴파일 되어있지않으면 알아서 컴파일해준다.


 

static 블록

static {
//딱 한번만 실행되는 코드
}

객체가 생성되기 전에 한번만 호출됨.

메소드 내에 선언 불가 => static 이므로

생성자가 호출되기 전에 static 블록들이 호출된다.

static한 변수, 메소드를 사용할 수 있다.


 

String

string은 참조형이지만

String b="b";//new를 쓰지않았지만 객체를 생성한것임
b="z";

String b=new String("b");
b=new String("z");

String b="b";
b=b+"z" //더하기 연산시 기존의 객체는 버리고 새로운 객체를 만든다.

 

매개변수 개수가 몇개일지, 호출될때마다 바뀔때 방법

public void calc(int... nums){
}

//호출시
calc(1, 2, 3, 4)
calc(1, 2)


OR

public void calc(String op, int... nums){
}

**여러 매개변수가 있을때, "타입... 변수명"은 항상 맨 뒤에 와야함.
**"타입... 변수명"다음엔 메소드의 선언을 닫는 소괄호가 와야한다.

 

패키지

클래스들을 구분짓는 폴더

어떤 클래스가 어떤 일을 하는지 혼동되는 것을 방지

  • 패키지 이름을 java로 시작하면 안된다.
  • 패키지 선언은 소스 하나에는 하나만 있어야한다.
  • 패키지 이름과 위치한 폴더이름이 같아야한다.
  • (자바 파일을 만든 폴더 이름과 선언된 패키지 이름이 다르면 파일을 찾지 못한다.)
  • 패키지 이름은 모두 소문자로 지정
  • 자바의 예약어를 사용하지 않는다.(com.int.util과 같이 int가 없어야함 )
package c.javapackage;//패키지 선언문

public class Package{
...
}

컴파일시 소스코드와 컴파일된 클래스가 같은 디렉토리에 존재하게 된다.

 

import를 이요하여 다른패키지에 접근할 수 있다.

import 패키지이름.클래스이름


 

import static

static한 변수와 메소드를 사용할때 용이

package c.sub;

public class Sub{
...

	public final static String CLASS_NAME="sub";
	public static void method(){
		System.out.println('sub method');
	}
}
//1. 그냥 import하여 사용
package c;

immport c.sub;

...
public static void main(Strings[] args){
	Sub.method();
	System.out.println(Sub.CLASS_NAME);
}
//2. import static 사용

package c;

import static c.sub.Sub.CLASS_NAME;
import static c.sub.Sub.method;

...
~~ main ~~ {
	method();
	System.out.println(CLASS_NAME);
}
...

static 변수나 메소드가 중복될때는 자신의 클래스에 있는 static 변수나 메소드가 import static으로 가져온 것보다 우선이다.


 

접근제어자

  • public : 누구나 접근
  • protected : 같은 패키지내에있거나 상속받은 경우 접근
  • package-private : 같은 패키지내에 잇을때 (접근제어자 없을경우 기본)
  • private : 해당 클래스내에서만 접근 가능

=> 말그대로 접근을 제어하기 위해 사용, 주로 직접 접근하지 않고 메소드를 통하여 변경이나 조회를 할 수 있도록 할 때 사용

static => 클래스 변수/ 메소드 밖, 클래스 안

자바에서는 하나의 클래스를 컴파일할 때 관련된 클래스가 컴파일 되어 있지 않다면, 알아서 컴파일 해줌

한번만 호출되어야 하는 코드가 있따면 static 블록 사용

public으로 선언된 클래스가 소스내에 있으면, 그 소스 파일의 이름은 public 인 클래스 이름과 동일해야함

하나의 클래스 소스에서 여러 클래스가 선언가능하다 (단, 같은 패키지 내에 있는 클래스만 이 클래스의 객체를 생성하고 사용할 수 있다.)

 

public으로 선언된 클래스가 소스내에 있으면, 소스파일의 이름은 public인 클래스 이름과 동일해야한다.


 

상속

부모 클래스에 선언된 public, protected로 선언된 모든 변수와 메소드를 내가 갖고 잇는 것처럼 사용

자바에서 아무런 상속을 받지 않으면, java.lang.Object 클래스를 확장한다.

자바는 이중상속을 받을 수 없지만, 여러 단계로 상속을 받을 수 있다.

ex) Object -> Parent -> Child

Object 클래스에 있는 메소드를 통해서 클래스의 기본적인 행동을 정의할 수 있음.

(기본적으로 갖추어야될 메소드들 ex) equals, toString, getClass ... )

자식 클래스의 생성자가 호출되면 자동으로 부모클래스의 매개변수 없는 생성자가 실행된다.

=>하나를 만들고 파생되는 것을 조금씩 바꾸면 편리함

 

parent 클래스에 매개변수를 받는 생성자만 있을경우(기본생성자는 자동으로 생성되지 않음) => 에러

child 클래스의 모든 생성자가 실행될때 parent의 기본 생성자를 찾기 때문이다.

따라서 super(매개변수)와 같이 부모 클래스의 생성자를 호출 시켜주면된다.

super은 반드시 생성자의 첫줄에 있어야한다.


 

메소드 오버라이딩(덮어씀)

접근제어자, 리턴타입, 메소드 이름, 매개변수 타입 및 개수 모두 동일

접근제어자는 확장되는것은 괜찮지만 축소되는것은 문제가 된다.

 

참조 자료형의 형변환

Parent parent = new Parent();
Child child = new Child();

//부모 클래스에선 자식 클래스의 메소드와 변수를 사용할 수 없다.
Child obj1 = new Parent();//parent로 생성시 child의 기능을 사용할 수 없다.

//자식클래스에선 부모 클래스의 메소드와 변수 사용가능
Parent obj = new Child();//child로 생성시 parent의 기능을 사용할 수잇다.


Child child = new Child();
Parent parent = child; //child는 paret의 기능을 사용할 수 있다, parent는 실제로 child 객체이다.
Child child2 =(Child)parent;//따라서 형변환이 가능하다.

부모 타입의 객체를 자식 타입으로 형 변환을 할 때에는 명시적으로 타입을 지저해 주어야 한다. 부모타입의 실제 객체는 자식 타입이어야만 한다.


 

다형성

Parent parent1 = new Parent();
Parent parent2 = new Child();
Parent parent3 = new Child2();

//printName메소드는 각 클래스별로 있으며 해당 타입의 이름을 출력
parent1.printName();
parent2.printName();
parent3.printName();

//출력: 각각 타입
parent1 - parent
parent2 - child
parent3 - child2

모두 parent 타입으로 선언되었는데 각 객체의 실제 타입은 다르다.

그리고 형변환을 하더라도 실제 호출되는 것은 원래 객체에 있는 메소드가 호출된다.

=> 원래 객체의 printName 메소드를 호출하여 각각 다른 결과가 나온다.


 

java.lang.Object

아무런 상속을 받지 않으면 java.lang.Object 클래스를 확장한다.

java.lang.Object는 모든 자바 클래스의 부모이다. => Object에 있는 클래스의 메소드를 통해서 클래스의 기본 행동을 정의할 수 있기 때문(이정도 메소드는 잇어야한다~)

다중 상속은 되지 않으나, 여러단계로 상속을 받을 수 있다.


 

인터페이스

자바에선 클래스 파일 이외에 interface, abstract 클래스가 있다.

존재이유 => 프로그램 설계단계에서 인터페이스를 정해놓으면 메소드 이름, 매개변수 등등을 고민하지 않아도 된다. 인터페이스형식에 맞추어 메소드를 구현하면 된다.

구현시 implements로

정의된 메소드를 모두 구현하여야 컴파일이 된다.

인터페이스의 변수는 public static final로 자동 선언된다.

메소드의 경우도 public abstract로 자동 선언된다.

선언시 class 대신 interface를 사용

public interface test {
	methods....
}
MemberManagerInterface manager = new MemberManagerInterface();
//아무것도 구현해놓지 않은 인터페이스로 초기화 하려고하여 에러가남

MemberManagerInterface manager = new MemberManager();
//실제 구현은 MemberManager에 되어있으므로 실제 타입은 MemberManager에

 

abstract 클래스

마음대로 초기화하고 실행할 수 없다.

abstarct 클래스를 구현해 놓은 클래스로 초기화 및 실행이 가능하다.

선언시 class앞에 abstract를 사용

public abstarct class test{
	public abstract boolean addMemeber(MemberDTO member);
	public void test(){
		System.out.println("test");
	}
	...
}

abstract는 추상 메소드가 하나라도 있으면 사용한다.

인터페이스와 달리 구현되어 있는 메소드가 있어도 상관없다.

구현이 아니라 상속을 하여 사용하면된다.

extends하여 abstract한 메소드를 사용하면된다.

사용하는 이유는 어떤 메소드는 미리 만들어 놓아도 문제가 없는 경우가 발생한다.

하지만 해당 클래스를 만들기는 애매할 때, 공통적인 기능을 미리 구현하면 도움이 된다.

 

abstract의 경우 abstract 메소드(구현안된 메소드)가 하나라도 있을경우 class 예약어 앞에 붙인다.

상속과 동일하게 extends를 사용하면 된다.

어떤 메소드는 미리 만들어도되지만 클래스를 만들기는 애매할때 공통적인 기능을 미리 구현해놓으면 도움이 된다.


 

 

final

final의 경우 상속해줄수 없다.

확장해서는 안되는 클래스, 상속받아서 내용을 변경해서는 안되는 클래스 선언시 사용

기본 속성이 변경되면 안되는 클래스에 사용한다.

메소드 또한 final로 선언시 overriding할 수 없게 된다.

인스턴스 변수나 static으로 선언된 클래스 변수의 경우 생성과 동시에 초기화를 해주어야한다. 생성자나 메소드에서 초기화시, 중복되어 변수값이 선언될 수 있다.

하지만, 매개변수의 경우 이미 초기화가 되어 값이 넘어오고

지역변수의 경우 메소드를 선언하는 중괄호 내에서만 참조되므로 다른곳에서 변경할 일이 없으므로 컴파일시 문제발생X

 

객체를 final로 선언시 객체안의 변수들은 제약이 없다. final로 선언되어 있지 않으면

=> 해당 클래스가 final이라고 그 안의 인스턴수 변수나 클래스 변수가 무조건 final로 선언된건 아니다.


 

enum

상수의 집합이다.

클래스의 일종

public enum Time{
	THREE,
	FIVE,
	EIGHT;
}
...
	public int timecheck(Time value){
		switch(value){
			case THREE:
				System.out.println("3")
			...
		}
	}

 

main

~~ ~~~ main(~~){
	Time test = new Time();
	test.timecheck(Time.THREE);
}

클래스이름.상수이름 을 넘겨준다.

생성자를 만들 수 있지만, 생성자를 통하여 객체를 생성할 수는 없다.

 

enum클래스 선언시 각 상수의 값을 지정할 수 있다.

public enum Time{
	THREE(1000),
	FIVE(3000),
	private final int amount;
	
	Time(int amount){
		this.amount= amount;
	}
}

enum클래스의 생성자는 아무것도 명시하지 않는 pacakge-private와 private만 접근 제어자로 사용할 수 있다.

=> 각 상수를 enum 클래스내에서 선언할 때에만 이 생성자를 사용할 수 있다.

 

  • enum 클래스는 다른 클래스와 같이 컴파일 할때 생성자를 자동을 만들어준다.

 

 

Nested 클래스

클래스 안의 클래스

코드를 간단하게 표현하기 위해서

주로 UI처리시 사용자의 입력이나 외부의 이벤트에 대한 처리를 하는 곳에서 많이 사용됨

 

static으로 선언시 static nested 클래스 => 한 곳에서만 사용되는 클래스를 논리적으로 묶어서 처리할 필요가 있을때

아닌경우 내부클래스이다. => 캡슐화가 필요할 때(A클래스의 private 변수접근을 위한 B클래스를 선언하고, B클래스를 외부에 노출시키고 싶지 않을 경우), 다른클래스에서 전혀 필요가 없을 경우

내부클래스는 로컬내부클래스와 익명내부클래스로 구분된다.


 

 

static nested class

내부 클래스는 감싸고 있는 외부 클래스의 어떤 변수도 접근할 수 있다. 심지어 private 변수까지

하지만 "Static"하기 때문에 그렇게 사용하는 것은 불가능하다.

public class Test{
	staic class StaticTest{
		public void setVal(int val){
			...
		}
		...
	}
}

내부 static 클래스 객체 생성?

public class InterClassTest{

	public static void main(String[] args){
		InterClassTest sample = new InterClassTest();
		sample.StaticObject();
	}
	
	public void StaticObject(){
		Test.StaticTest staticNested = new Test.StaticTest();
		staticNested.setVal(1230);
	}
}

감싸는 클래스.내부클래스 로 생성한다.

 

사용하는 이유

예로 학교를 관리하는 school 클래스를 만들고 대학을 관리하느 univ클래스를 만들면,

student는 어디 학생인지 모름

따라서 school안에 static nested 클래스 student를 만들면 용도가 명확해짐

또한 해당 클래스는 univ에서 사용 불가함.


 

 

내부 클래스와 익명클래스

public class Test{
	 class Inner{
		public void setVal(int val){
			...
		}
		...
	}
}

 

생성시 감싸는 클래스의 객체를 만들어야한다.

public class InterClassTest{

...
	public void InnerObject(){
		Test outer = new Test();//감싸는 클래스 객체 생성
		Test.Inner inner = outer.new Inner();//객체를 통해서 생성
	}
...

}

=>다른 클래스에서는 그 클래스가 전혀 필요 없을때 이러한 내부클래스 사용

 

예를 들어 gui에서 버튼 클릭 이벤트 처리시 내부 클래스를 만드는 것이 편이함(따로 클래스를 만드는것 보다)

하지만 익명클래스를 사용하면 더 편리함

 

  1. 내부 클래스 사용방법
package a.inner;

public interface EventListener{
	public void onClick();
}

 

package c.inner;

public class MagicButton{
	public MagainButton(){
	
	}
	//EventListener는 인터페이스이다.
	private EventListener listener;
	public void setListener(EventListener listener){
		this.listener=listener;
	}
	public void onClickProcess(){
		if(listener!=null){
			listener.onClick();
		}
	}
}
package c.inner;

public class NestedSample{
	...
	public void setButtonListner (){
		MagicButton button = new MagicButton();
		MagicButtonListener listener = new MagicButtonListener();
		button.setListener(listener); //<- 별도 클래스를 넘기지 않고 밑의 내부 클래스를 넘김
		button.onClickProcess();
	}
}
package c.inner;

public class NestedSample{
	...
	//내부 클래스
	class MagicButtonListener implements EventListener {
		public void onClick(){
			System.out.println("clicked")
		}
	}
}

 

  1. 익명 클래스 사용방법
package c.inner;

public class NestedSample{
	...
	public void setButtonListner (){
		MagicButton button = new MagicButton();
		//MagicButtonListener listener = new MagicButtonListener();
		//button.setListener(listener); //<- 별도 클래스를 넘기지 않고 밑의 내부 클래스를 넘김
		
		//익명 클래스 생성로 인자 넘김
		button.setListener(new EventListener(){
			public void onClick(){
				System.out.println("button clicked");
			}
		});
		
		button.onClickProcess();
	}
}

new EventListener로 생성자 호출 후 바로 중괄호를 열고 메소드 구현

클래스 이름도 없고 객체 이름도 없어서 다른곳에서 참조할 수는 없다.

 

사용이유

클래스를 많이 만들면 메모리가 많이 필요해짐. 따라서 내부, 익명클래스로 간단하게 객체를 생성할 수 잇다.

클래스 개수를 줄일 수 있으면 좋으니까

또한 다른 클래스에서 재사용할 일이 없을때 유용하다.


 

 

예외

예외적인 일이 발생한 경우

잘못을 컴파일할 때 점검해주지 않으므로 예외처리 해야한다.

try{
...
}
catch (Exception e){
...
}

예외가 발생하는 부분만 묶어주면 된다.

try 블록 안에서 예외가 발생되면 그 이하의 문장은 실행되지 않고 바로 catch로 넘어간다.

그리고 try-catch 구문 밖에 잇는 문장이 실행된다.

 

try에서 선언한 변수를 catch에서 사용할 수 없다.

따라서 일반적으로 catch 문장에서 사용할 변수는 try 앞에 선언한다.

 

모든 예외 객체의 부모 클래스는 java.lang.Exception 클래스이다.

따라서 만약 catch가 여러개인 경우,

부모 예외 클래스가 잡고 자식 클래스가 잡도록 되어있으면 자식 클래스가 예외를 처리할 수 없다.

즉, 위에서 먼저 catch해버리므로 그 다음에서 catch할 수 없다.


 

Throw

모든 예외는 java.lang.Throwable 클래스를 상속받는다.

이러한 이유는 모두 동일한 이름의 메소드를 사용하여 처리할 수 있게 하기 위함이다.

 

예외를 발생시키기 위해서 Throw를 사용한다.

 

try{
	throw new Exception("wrong input");
	...
}

catch (Exception e){
	e.printStrackTrace();
}

try블록 내에서 throw라고 명시한 수 개발자가 예외 클래스의 객체를 생성하면 된다.

throw한 문장 이후에 있는 모든 try 블록 내의 문장들은 수행되지 않고 catch로 이동한다.

 

또한 예외가 발생된 메소드를 호출한 메소드로 던질수도 있다.

public class TestException {
	public void throwException(int num) throws Exception{

			if(num<0){
				throw new Exception("wrong");
			}

	}
}

try-catch로 묶지 않았지만,

throws가 선언되어 있기 때문에 throwException 메소드를 호출한 메소드에선 try-catch블록으로 감싸어서 예외를 받아서 처리해야한다.

 

try{
	test.throwException(-1);
}
catch(Exception e){
  ....
}

 

여러가지 예외를 던질수도 있다.

public void multiThrow() throws NullPointerException, ArrayIndexOutOfBoundsExceptioin{
	...
} 

 

예외를 만들수도 잇다.

public class MyException extends Exception{
	...
}

 

finally

어떠한 경우에도 반드시 실행

try{

}
catch (Exception e){

}
finally{

}

예외가 발생하면 catch가 실행되고 finally 블록이 실행되고 try-catch 이후 문장이 실행된다.

finally는 예외와 상관없이 실행된다.

코드의 중복을 피하기 위해서 반드시 필요하다.


 

어노테이션

클래스나 메소드 선언시 @를 사용함

메타데이터라고도 함

  • 컴파일러에게 정보를 알려줌
  • 컴파일할 때와 설치시의 작업을 지정
  • 실행시 별도의 처리가 필요할때

 

미리정해진 어노테이션은 3개

  • @Override즉, 메소드가 override되엇으니 잘못코딩되면 컴파일ㄹ러에게 알려달라고 한다.
  • 해당 메소드가 부모 클래스에 잇는 메소드를 override 했다고 명시적으로 선언
  • @Deprecated
  • 미리 만들어진 클래스나 메소드가 더이상 쓰이지 않을때 알려줌
  • @SuppressWarnings
  • 컴파일러에서 경고를 주는 경우, 일부러 이렇게 코딩햇으니 괜찮다고 알려줌

 

메타 어노테이션

어노테이션을 선언할때 사용

  • @Target
  • 어노테이션을 어떤 것에 적용할지 선언할때 사용
  • @Retention
  • 얼마나 오래 어노테이션 정보가 유지되는지 선언
  • @Documneted
  • 해당 어노테이션에 대한 정보가 javadocs 문서에 포함된다는 것을 선언
  • @Inherited
  • 모든 자식 클래스에서 부모 클래스의 어노테이션을 사용할 수 있다는 것을 선언
  • @interface
  • 어노테이션을 선언할때 사용

 

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
//이 어노테이션은 메소드에 사용할 수 있다고 지정

@Retention(RetentionPolicy.RUNTIME)
//실행시에 이 어노테이션을 참조하게 됨. 

//UserAnnotation이라는 어노테이션 선언
//@interface를 앞에 붙여서 사용시 @UserAnnotation으로 사용할 수 있다.
public @interface UserAnnotation {
	public int number();
	//메소드처럼 어노테이션 안에 선언해두면, 이 어노테이션을 사용할 때 해당항목에 대한 타입으로 값을 지정해야한다.
	public String text() default "This is first annotation";
	//default를 사용할 경우 뒤에 있는 값이 이 어노테이션을 사용할때 별도로 값을 지정해 주지 않을 때의 값이 된다.
}



 

사용시

만든 어노테이션의 target이 메소드였으므로 대상은 메소드 뿐이다.

public class Sample{
	@UserAnnotation(number=0)
	public static void main(String args[]){
		Sample sample = new Sample();
	}

	@UserAnnotation(number=3, text="Test")
	public void annotationexam(){
		
	}
}

 

 

 

 

728x90
반응형

'공부 > Spring' 카테고리의 다른 글

스프링 웹개발 기초  (0) 2021.10.20
자바 - Map  (0) 2021.10.19
자바 - Set  (0) 2021.10.18
자바 - 컬렉션(List)  (0) 2021.10.15
자바 - 제네릭  (0) 2021.10.14
블로그 이미지

아상관없어

,