티스토리 뷰
1. 요약
- 참조 타입의 종류 : 배열타입, 열거타입, 클래스. 인터페이스, 레코드
- Staic은 지역변수나 매개변수에 사용할 수 없다.
- 매개변수는 지역변수로 간주하기에 지역변수와 같은 유효 범위를 갖는다.
- 패키지란 비슷한 기능을 가진 클래스끼리 묶은 것을 의미한다.
- 만약 다른 패키지에 있는 것을 사용하고 싶을 때는 import문을 사용해야 한다.
- import문은 컨트롤 + 쉬프트 + O를 사용하면 자동으로 입력되지만, 만약 같은 이름의 클래스를 모두 사용할 때에는 직접 패키지명.클래스명으로 직접적으로 입력해야 한다.
- Default 접근제한자는 접근제한자 중 아무것도 작성하지 않았을 때 자동으로 사용되는 접근제한자로, 같은 패키지에만 접근이 가능하다. (public과 같이 class에 사용가능)
- Getter와 setter의 이름을 지을 때에는 get/set + 필드명으로 주로 짓는다. 다르게 지어도 가능하다.
2. 어노테이션 ( Annotation )
- 어노테이션은 적용할 때, @AnnotationName을 작성하여 사용할 수 있다.
- 어노테이션에서 속성을 기술할 때에는 String value ( ) ; 처럼 ( )와 ;을 붙어야 한다.
- 또한 어노테이션에서는 속성에 무조건 값을 지정해 줘야한다.
- 어노테이션에서 값을 지정해서 정의할 때는 int elementName ( ) default 5;로 작성
- 다른 클래스에서 지정할 때에는 @AnnotationName(value = “값” , elementName =3);으로 작성해야 한다.
01. 어노테이션 1 - 위치고정
package org.zerock.myapp.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// ElementType[] value();
// Target에서 오른 클릭을 하면 이렇게 Element Type 배열에 있는 원소를 사용하라고 적혀 있다. (**)
// ElementType의 원소는 열거 상수(ex.Week)로 되어있기에 이 중에서 골라야 한다.
// 열거상수 는 ElementType temp = ElementType.TYPE; 처럼 사용해야 한다. (****)
// @Target은 { } 배열로 이루어져 있기에, 다양하게 위치를 고정시킬 수 있다. (**)
// ElementType 열거 상수 중 TYPE_USE는 모든 곳에서 사용할 수 있게 해준다는 것인데,
// 완전히 모두 가능하게 하는 것이 아니라 메소드와 페키지 선언부에는 적용이 안된다. (**)
// 기본속성에만 값을 지정하면 되기에 @Target({ElementType.TYPE, ElementType.FIELD}) 도 가능하다.
@Target(value = {
ElementType.TYPE,
ElementType.FIELD,
ElementType.METHOD,
ElementType.CONSTRUCTOR, // 생성자
ElementType.LOCAL_VARIABLE, // 지역변수
ElementType.PARAMETER, // 매개변수
ElementType.PACKAGE,
ElementType.ANNOTATION_TYPE
}) // 어노테이션 선언부 위치
// @Myannotation을 특정한 위치에만 적용할 수 있도록 위치를 제한시켰다. (****)
@Retention(RetentionPolicy.RUNTIME) // 배열이 아니기에 { }를 붙이지 않는다.
// 만약 어노테이션을 사용하고 import를 사용했을 때, 오류가 발생하면 값을 필요로 하는 경우가 많기에
// 컨트롤 + 오른쪽 클릭을 하여 어떤 값이 필요한지 파악해야 한다.
// @Retention은 어노테이션 붙였을 때, 어노테이션이 붙었다는 정보를 어디까지 유지하는 가를 결정하는 것이다.(***)
// 소스파일 내에서만 유지할 것인지, 클래스 내에서만 유지할 것인지, 런타임에서만 유지를 할 것인지 결정해야 한다.
// 대부분 런타임을 선택하여 사용한다. (***)
// ( ) 안에 들어가는 식별자는 컴파일러가 정확히 어떤 것을 의미하는지 출처를 알게 작성해야 한다.
@Myannotation // 기본적으로 어노테이션은 자기자신한테도 붙여줄 수 있다. 하지만 명확성을 위해 지양하자!
public @interface Myannotation {
// TYPE 선언부란?
// @Myannotation
// public class Service { } 를 의미한다.
// 속성 ( 정확히는 엘리먼트 ) 선언 ( like field )
String value() default "-"; // 기본속성 (**)
// 뒤에 ();를 붙어야 한다.
// Annotation은 default 값이 설정되어 있지 않으면, 반드시!!! 값을 줘야 한다!! (**)
int number () default 30; // 기본값 설정
} // end annotation
02. 어노테이션 2 - 위치
//@Myannotation - 1. 컴파일오류 발생 -패키지 선언문 위에는 어노테이션 사용이 불가능하다.
package org.zerock.myapp.annotation;
@Myannotation
public class Service2 { // 어노테이션의 위치 (***)
//@Myannotation public class Service2 { // OK!
//public @Myannotation class Service2 { // OK!! - @Myannotation을 사이에 작성하여도 사용가능하다.
//public class @Myannotation Service2 { // 3. 컴파일 오류 - class와 class명은 한 몸으로 생각하기에 class와 class명 사이에는 불가능하다.
@Myannotation
public String instanceField; // OK!
// @Myannotation public String instanceField; // OK!
// public @Myannotation String instanceField; // ok!
// public String @Myannotation instanceField; // 4. 컴파일 오류!! - 타입과 타입은 한 몸이기에 사이에 어노테이션을 사용할 수 없다.
@Myannotation
private static int staticField; // OK! 어노테이션은 정적이나 인스턴스 구분하지 않고 어디에서나 붙일 수 있다.
@Myannotation
public Service2(@Myannotation String instanceField, @Myannotation final double PI){ // OK!
;;
} // default constructor - 생성자 OK!
// public @Myannotation Service2(@Myannotation String instanceField, @Myannotation final double PI){
// ;;
// } // OK!!
// public @Myannotation Service2(@Myannotation String instanceField, final @Myannotation double PI){
// ;;
// } // OK! - final 뒤에도 사용이 가능하다. 단, double 뒤에는 사용이 불가능 하다.
// @Myannotation
// static {
//
// } //static initializer - 2. 컴파일 오류 발생 - static initializer에서는 JVM이 구동하는 것이기에 오류가 발생한다. (**)
@Myannotation
private static final double PI = 3.14159; // OK!
// @Myannotation private static final double PI = 3.14159; // OK!
// private @Myannotation static final double PI = 3.14159; // ok!
// private static @Myannotation final double PI = 3.14159; // ok!
// private static final @Myannotation double PI = 3.14159; // OK!
// private static final double @Myannotation PI = 3.14159; // 5. 컴파일 오류!! - 변수명을 2개로 인식해 버린다.
@Myannotation
public void staticMethod() {
@Myannotation
int temp; // OK! 이러한 지역변수에서도 어노테이션을 사용할 수 있다.
} // OK!
@Myannotation public void staticMethod2() { ;; } // OK!
// public @Myannotation void staticMethod2() { ;; } // OK!
// public void @Myannotation staticMethod2() { ;; } // 6. 컴파일 오류 - 타입과 이름이 한 몸이기에 사이에 어노테이션을 사용할 수 없다.
@Myannotation
public void instanceMethod(@Myannotation int age) { // OK! 매개변수에서도 어노테이션을 사용할 수 있다.
@Myannotation
int temp; // OK!
// @Myannotation int temp; // OK!
// int @Myannotation temp; // 7. 컴파일러 오류! - 타입과 변수 명 사이에는 불가능하다.
} // instanceMethod
// 어노테이션은 패키지 선언문과 static initializer, 그리고 타입과 변수 명 사이를 제외한 모든 곳에 사용이 가능하다.
} // end class
03. 어노테이션 응용 - clazz 객체
package org.zerock.myapp.annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MyAnnotationExample { // 어노테이션 - clazz 객체 (******)
// xxx.java ---> compile ----> xxx.class
// Java Reflection API를 이용하여, Service 클래스에 붙여놓은
// MYannotation 이름의 어노테이션 정보를 이용하여 무엇인가를 합시다!!
// Java Reflection API는 class 파일의 모든 정보를 반영/반사하는 것이다.
// clazz는 .class 파일을 클래스로더가 바이트를 읽어다가 class에 대한 모든 정보를 class타입의 clazz 객체를 넣은 것을 의미한다.
public static void main (String [] args ) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class clazz = Service.class; // (******)
// 이 말은 clazz라는 객체는 class 타입이며, service 클래스에 대한 모든 정보를 가지고 있다는 것이다.
// 그리고 그 정보를 모두 불러왔다는 의미이다.
// .class가 붙으면 clazz 객체이다.
// clazz는 메소드 영역에 저장된다.
// 이를 통해서 객체를 얻었기에 인스턴스멤버일지라도 new연산자를 사용하지 않아도 괜찮다.
// 메소드 영역에 아래의 Service 타입에 대한 정보를 모두 가지고 있는
// Clazz객체가 없으면, new 연산자로 객체를 생성할 수 없다!!
// 즉, classNotFoundException 이란 오류가 발생하게 된다.
System.out.println(clazz); // clazz가 가지고 있는 class파일의 위치를 출력
// 출력결과 : class org.zerock.myapp.annotation.Service
Method[] methods = clazz.getDeclaredMethods(); // 마우스를 올려 놓자 static이 없는 것을 보아 인스턴스멤버임을 알 수 있다.
// import문 주의하자!!
// getDeclaredMethods는 메소드를 뽑아 내라는 것이다.
for ( Method method : methods ) { // 메소드 출력 방법 (***)
System.out.println(method);
} // enhanced for - 메소드와 매개변수를 출력한다.
// enhanced for 출력결과
// public void org.zerock.myapp.annotation.Service.instanceMethod(int)
// public void org.zerock.myapp.annotation.Service.staticMethod()
// Service s = new Service(null, 10.0);
// ==========================================================================================================
// 0. 메소드 지정
Method instanceMethod = methods[0];
Method staticMethod = methods[1];
// ==========================================================================================================
// 1. 어노테이션의 존재 확인
// 어노테이션이 여러개 붙어있을 수 있으므로 어노테이션을 지정해줌으로써 확인하는데 도움을 준다.
boolean isPresent = instanceMethod.isAnnotationPresent(Myannotation.class);
// 마이어노테이션이 인스턴스메소드에 있는가 boolean 타입으로 확인해 준다.
System.out.println(isPresent); // true로 출력
// ==========================================================================================================
// 2. 어노테이션 정보 추출
Myannotation myAnnotation = instanceMethod.getAnnotation(Myannotation.class); // 어노테이션은 실행할 때 클레스처럼 쓰인다.
System.out.println(myAnnotation); // 출력 : @org.zerock.myapp.annotation.Myannotation(value="-", number=30)
// Myannotation의 완전한 이름이 나온 후에 속성이 나오게 된다.
// 잘 모르는 객체의 경우 출력을 하여 어떤 것인지 파악하는 것이 도움을 준다!!
// 어노테이션은 메타 데이터로 활용된다.
// ==========================================================================================================
// 3. 어노테이션 속성 추출하기
String value = myAnnotation.value();
int number = myAnnotation.number(); // 값을 리턴받을 때, 메소드처럼 시행되기에 ( );를 붙어야 한다.
System.out.println(String.format("value : %s, number : %d", value, number)); // (*****)
// 출력 결과 : value : -, number : 30
// format은 원하는 형식으로 출력하게 해준다.
// %s 와 %d는 포멧팅 기호라고 부른다.
// 그냥 " %s "를 붙이면 타입에 맞게 조절해준다. ( 만능 기호 ) ( **** )
// 이때 format은 클래스 명을 붙인 String.format으로 활용하였기에 static 정적멤버인 정적 메소드이다.
// ==========================================================================================================
// 5. 어노테이션 활용하기
// instanceMethod.invoke(value, args) // 메소드 호출시키기 - 매개변수에 주는 값을 전달인자(arg)라고 한다.
// ==========================================================================================================
// 6. object
// Myannotation이 붙어 있는 메소드가 호출될 때, 메소드 호출로그를 우리가 직접 코딩하는 것이 아니라.
// 자동으로 메소드 호출로그를 출력하는 기능을 구현하는데
// 어노테이션의 메타데이터를 사용하자!!
System.out.println("-- [" + instanceMethod.getName() + "] ----");
for ( int i =0 ; i< number; ++i) {
System.out.println(value); // vlaue의 값을 가져와 출력하게 함.
} // classical for(****)
instanceMethod.invoke(new Service("Yoseph", 23), 100); // 메소드 호출(?) - 오류뜰때는 노랑박스 클릭
// . 어노테이션 존재 확인
boolean isPresent2 = staticMethod.isAnnotationPresent(Myannotation.class); // Myannotation.class도 clazz에 해당한ㄷ다.
// 마이어노테이션이 스테이틱메소드에 있는가 boolean 타입으로 확인해 준다.
System.out.println(isPresent2); // true로 출력
} // main class
} // end class
04. String.format
package Practice;
import java.util.Arrays;
public class Sample01 { // format 출력 (*****)
public static void main (String[] args) {
String name = "조민주";
int age = 23;
double weight = 60.2;
double height = 162.0;
// String.format("formatting string", 가변인자); // 메소드를 사용할 때는 기능과 return 값을 알아야 한다.
// 가변인자에는 0개 이상의 값들을 넣을 수 있다.
// Object란?
// 1. class
// 2. 모든 클래스의 조상 클래스 - object란 이름의 클래스
String result1 = String.format("1. name : %s", name);
// 기호 : %s ( 문자열, 만능 ) , %d ( 정수 ) , %f ( 실수 )
System.out.println(result1); // 1. name : 조민주
String result2 = String.format("2. age : %s", age);
System.out.println(result2); // 2. age : 23
String result3 = String.format("3. weight : %s", weight);
System.out.println(result3); // 3. weight : 60.2
String result4 = String.format("4. height : %s", height);
System.out.println(result4); // 4. height : 162.0
// 한 번에 출력하기
String result = String.format(">>>> name : %s, age : %s, weight : %s, height : %s", name, age, weight, height);
System.out.println(result); // 출력 : >>>> name : 조민주, age : 23, weight : 60.2, height : 162.0
// 배열의 각 원소의 값을 하나의 문자열로 출력하라!
int [] arr = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
String intarr = String.format("int arr = %s, %s, %s, %s, %s, %s, %s, %s, %s", arr [0], arr [1], arr [2], arr [3],
arr [4], arr [5], arr [6], arr [7], arr [8]); // 배열의 인덱스는 0번 부터 시작한다!!
System.out.println(intarr); // int arr = 1, 2, 3, 4, 5, 6, 7, 8, 9
System.out.println(Arrays.toString(arr)); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
// String.format(intarr, args); (******)
/**
*
* 새로운 주석 방법!
*
* */
} // main
} // end class
'KH 정보교육원 [ Java ]' 카테고리의 다른 글
KH 15일차 - protected 접근제한자 및 프로모션 (0) | 2022.03.18 |
---|---|
KH 14일차 - 상속 (0) | 2022.03.17 |
KH 12일차 - 접근제한자 및 어노테이션 [ + 1차 시험 후기 ] (0) | 2022.03.14 |
KH 11일차 - 정적 초기화 블록과 상수 + 간단한 10일 후기 (0) | 2022.03.11 |
KH 10일차 - 생성자 및 인스턴스 / 정적 멤버 (0) | 2022.03.10 |