/ JAVA

객체지향 프로그래밍 복습 (11) Reflection

[JAVA] 객체지향 프로그래밍 복습 (11) Reflection

자바(Java)는 C언어에 객체 지향적 기능을 추가하여 만든 C++과는 달리, 처음부터 객체 지향 언어로 개발된 프로그래밍 언어입니다. 자바는 자바 가상 머신(JVM, Java Virtual Machine)을 사용하여, 운영체제와는 독립적으로 동작할 수 있습니다. 따라서 자바는 어느 운영체제에서나 같은 형태로 실행될 수 있습니다. 바로 이러한 점이 수많은 개발자로 하여금 자바를 사용하게 하는 원동력이 되고 있습니다. 현재 자바는 전 세계에서 가장 많이 사용하는 프로그래밍 언어 중 하나입니다.

Reflection

reflection 은 자바의 특징입니다. 실행중인 자바프로그램 내부를 검사하고 내부의 속성을 수정할 수 있도록 합니다. 예를 들어, 어떤 자바클래스가 가진 모든 멤버의 이름을 얻거나 보여줄 수 있습니다. 자바에서 클래스가 그 자신을 조사하고 수정하는 것이 많다고 할수는 없으나 다른 언어에서는 볼수 없는 특징입니다.

DoubleOperator 클래스

연산자 함수를 가진 DoubleOperator 클래스를 구현하여 해당 클래스의 내부 멤버의 정보를 출력하고 switch 문을 활용하여 계산기 프로그램을 구현합니다.

DoubleOperator.java

// Class for operating 2 numeric operands whose type are double.
class DoubleOperator {
	private double result;
	public DoubleOperator() {result = 0.0; }
	public double getResult() {return result; }
	public void add(double operand) {result = operand + 1; } // Increments operand.
	public void add(double operand1, double operand2){ result = operand1 + operand2; }
	public void subtract(double operand) {result = operand - 1; } // Decrements operand.
	public void subtract(double operand1, double operand2) { result = operand1 - operand2; }
	public void multiply(double operand1, double operand2) { result = operand1 * operand2; }
	public void divide(double operand1, double operand2) {
		try { result = operand1 / operand2; }
		catch (ArithmeticException e) {result = 0;}
	}
	public void computeModulo(double operand1, double operand2){result = operand1 % operand2;}
}

test1. java

DoubleOperator 클래스 정보 출력

//소프트웨어학부 20201881 장환곤
//객체지향 프로그래밍 및 실습
//LAB12

import java.lang.reflect.*;

public class TestProgram1 {

	public static void main(String[] args) {
		try {
			Class cls = Class.forName("DoubleOperator");
			Class supercls = cls.getSuperclass();
			Field[] fd = cls.getDeclaredFields();
			Method methlist[] = cls.getDeclaredMethods();
			//클래스 이름
			System.out.println("Class Name:\t\t" + cls.getCanonicalName());
			//super 클래스 이름
			System.out.println("Super Class Name:\t" + supercls.getName());
			//attribute 출력
			System.out.println("Attributes:\t\t" + fd[0].getType() + " " + fd[0].getName());
			//메소드 출력
			System.out.println("Methods:\t\t");
			for(int i = 0; i < methlist.length; i++) {
				Method m = methlist[i];
				System.out.print("\t\t\t" + m.getReturnType() + " ");
				System.out.print(m.getName());
				
				//파라미터 타입 가져와서 가독성있게 출력하기
				Class pvec[] = m.getParameterTypes();
				System.out.print("( ");
				for(int j = 0; j < pvec.length; j++) 
					System.out.print(pvec[j] + " arg" + j + " ");
				System.out.println(")");		
			}

		}
		catch(Throwable e) {
			System.err.println(e);
		}
	}

}

결과

test1. java

DoubleOperator 클래스 정보 출력

//소프트웨어학부 20201881 장환곤
//객체지향 프로그래밍 및 실습
//LAB12

import java.lang.reflect.*;

public class TestProgram1 {

	public static void main(String[] args) {
		try {
			Class cls = Class.forName("DoubleOperator");
			Class supercls = cls.getSuperclass();
			Field[] fd = cls.getDeclaredFields();
			Method methlist[] = cls.getDeclaredMethods();
			//클래스 이름
			System.out.println("Class Name:\t\t" + cls.getCanonicalName());
			//super 클래스 이름
			System.out.println("Super Class Name:\t" + supercls.getName());
			//attribute 출력
			System.out.println("Attributes:\t\t" + fd[0].getType() + " " + fd[0].getName());
			//메소드 출력
			System.out.println("Methods:\t\t");
			for(int i = 0; i < methlist.length; i++) {
				Method m = methlist[i];
				System.out.print("\t\t\t" + m.getReturnType() + " ");
				System.out.print(m.getName());
				
				//파라미터 타입 가져와서 가독성있게 출력하기
				Class pvec[] = m.getParameterTypes();
				System.out.print("( ");
				for(int j = 0; j < pvec.length; j++) 
					System.out.print(pvec[j] + " arg" + j + " ");
				System.out.println(")");		
			}

		}
		catch(Throwable e) {
			System.err.println(e);
		}
	}

}

결과

test2. java

DoubleOperator 클래스 정보 출력 및 계산기 프로그램

import java.lang.reflect.*;
import java.util.Scanner;
import java.util.StringTokenizer;

public class TestProgram2 {

	public static void main(String[] args) {
		try {
			String methodName = "";
			Class cls = Class.forName("DoubleOperator");
			Field[] fd = cls.getDeclaredFields();
			Method methlist[] = cls.getDeclaredMethods();
			System.out.println("List of Methods for" + cls.getCanonicalName() + "Class: ");
			for(int i = 0; i < methlist.length; i++) {
				Method m = methlist[i];
				System.out.print("\t" + m.getReturnType() + " ");
				System.out.print(m.getName());

				Class<?> pvec[] = m.getParameterTypes();
				System.out.print("( ");
				for(int j = 0; j < pvec.length; j++) 
					System.out.print(pvec[j] + " arg" + j + " ");
				System.out.println(")");		
			}
			
			//quit 입력까지 루프
			while(methodName != "Quit") {
				double a, b;
				Scanner sc = new Scanner(System.in);
				System.out.print("\nEnter a method name or 'Quit' : ");
				methodName = sc.next();
				//switch-case문으로 각 메소드 호출
				switch(methodName) {
				case "add":
					Scanner sc2 = new Scanner(System.in);
					System.out.print("Enter a number or two numbers (Use spaces to distinguish two numbers) : ");
					String str = sc2.nextLine();
					//받은 입력에 공백이 있다면 둘로 나누어서 파라미터 입력
					if(str.indexOf(" ") != -1) {
						StringTokenizer st = new StringTokenizer(str);
						a = Double.parseDouble(st.nextToken());
						b = Double.parseDouble(st.nextToken());
						Class partypes[] = new Class[2];
						partypes[0] = Double.TYPE;
						partypes[1] = Double.TYPE;
						//add 메소드 호출
						Method meth = cls.getMethod("add", partypes);
						DoubleOperator methobj = new DoubleOperator();
						Object arglist[] = new Object[2];
						arglist[0] = new Double(a);
						arglist[1] = new Double(b);
						Object retobj = meth.invoke(methobj, arglist);
						//getResult 메소드 호출
						Method meth2 = cls.getMethod("getResult", null);
						//result 값 가져오기
						Object retobj2 = meth2.invoke(methobj, null);
						Double retval = (double)retobj2;
						System.out.println("The Computation Result is " + retval);
					}
					//받은 입력에 공백이 없다면 하나의 파라미터 입력
					else {
						a = Double.parseDouble(str);
						Method meth = cls.getMethod("add", Double.TYPE);
						DoubleOperator methobj = new DoubleOperator();
						Object retobj = meth.invoke(methobj, a);
						Method meth2 = cls.getMethod("getResult", null);
						Object retobj2 = meth2.invoke(methobj, null);
						Double retval = (double)retobj2;
						System.out.println("The Computation Result is " + retval);
					}
					break;

				case "subtract":
					Scanner sc21 = new Scanner(System.in);
					System.out.print("Enter a number or two numbers (Dividend Divisor) (Use spaces to distinguish two numbers) : ");
					String str1 = sc21.nextLine();
					if(str1.indexOf(" ") != -1) {
						StringTokenizer st = new StringTokenizer(str1);
						a = Double.parseDouble(st.nextToken());
						b = Double.parseDouble(st.nextToken());
						Class partypes[] = new Class[2];
						partypes[0] = Double.TYPE;
						partypes[1] = Double.TYPE;
						Method meth = cls.getMethod("subtract", partypes);
						DoubleOperator methobj = new DoubleOperator();
						Object arglist[] = new Object[2];
						arglist[0] = new Double(a);
						arglist[1] = new Double(b);
						Object retobj = meth.invoke(methobj, arglist);
						Method meth2 = cls.getMethod("getResult", null);
						Object retobj2 = meth2.invoke(methobj, null);
						Double retval = (double)retobj2;
						System.out.println("The Computation Result is " + retval);
					}
					else {
						a = Double.parseDouble(str1);
						Method meth = cls.getMethod("subtract", Double.TYPE);
						DoubleOperator methobj = new DoubleOperator();
						Object retobj = meth.invoke(methobj, a);
						Method meth2 = cls.getMethod("getResult", null);
						Object retobj2 = meth2.invoke(methobj, null);
						Double retval = (double)retobj2;
						System.out.println("The Computation Result is " + retval);
					}
					break;

				case "divide":
					Scanner sc22 = new Scanner(System.in);
					System.out.print("Enter two numbers (Use spaces to distinguish two numbers) : ");
					String str2 = sc22.nextLine();
					StringTokenizer st = new StringTokenizer(str2);
					a = Double.parseDouble(st.nextToken());
					b = Double.parseDouble(st.nextToken());
					Class partypes[] = new Class[2];
					partypes[0] = Double.TYPE;
					partypes[1] = Double.TYPE;
					Method meth = cls.getMethod("divide", partypes);
					DoubleOperator methobj = new DoubleOperator();
					Object arglist[] = new Object[2];
					arglist[0] = new Double(a);
					arglist[1] = new Double(b);
					Object retobj = meth.invoke(methobj, arglist);
					Method meth2 = cls.getMethod("getResult", null);
					Object retobj2 = meth2.invoke(methobj, null);
					Double retval = (double)retobj2;
					System.out.println("The Computation Result is " + retval);

					break;

				case "multiply":
					Scanner sc23 = new Scanner(System.in);
					System.out.print("Enter two numbers (Use spaces to distinguish two numbers) : ");
					String str3 = sc23.nextLine();
					StringTokenizer st2 = new StringTokenizer(str3);
					a = Double.parseDouble(st2.nextToken());
					b = Double.parseDouble(st2.nextToken());
					Class partypes1[] = new Class[2];
					partypes1[0] = Double.TYPE;
					partypes1[1] = Double.TYPE;
					Method meth1 = cls.getMethod("multiply", partypes1);
					DoubleOperator methobj1 = new DoubleOperator();
					Object arglist1[] = new Object[2];
					arglist1[0] = new Double(a);
					arglist1[1] = new Double(b);
					Object retobj1 = meth1.invoke(methobj1, arglist1);
					Method meth21 = cls.getMethod("getResult", null);
					Object retobj21 = meth21.invoke(methobj1, null);
					Double retval1 = (double)retobj21;
					System.out.println("The Computation Result is " + retval1);

					break;

				case "computeModulo":
					Scanner sc24 = new Scanner(System.in);
					System.out.print("Enter two numbers (Use spaces to distinguish two numbers) : ");
					String str4 = sc24.nextLine();
					StringTokenizer st3 = new StringTokenizer(str4);
					a = Double.parseDouble(st3.nextToken());
					b = Double.parseDouble(st3.nextToken());
					Class partypes11[] = new Class[2];
					partypes11[0] = Double.TYPE;
					partypes11[1] = Double.TYPE;
					Method meth11 = cls.getMethod("computeModulo", partypes11);
					DoubleOperator methobj11 = new DoubleOperator();
					Object arglist11[] = new Object[2];
					arglist11[0] = new Double(a);
					arglist11[1] = new Double(b);
					Object retobj11 = meth11.invoke(methobj11, arglist11);
					Method meth211 = cls.getMethod("getResult", null);
					Object retobj211 = meth211.invoke(methobj11, null);
					Double retval11 = (double)retobj211;
					System.out.println("The Computation Result is " + retval11);

					break;
				case "Quit":
					methodName = "Quit";
					break;
					
				default:
					System.out.println("잘못된 입력입니다.");
					break;
				}		
			}
		}
		catch(Throwable e) {
			System.err.println(e);
		}

	}

}

결과