1. 반사 메커니즘이란
간단히 말해서, 반사 메커니즘은 프로그램이 실행될 때 자체 정보를 얻을 수 있다는 의미입니다. 자바에서는 클래스 이름만 주어지면
그러면 리플렉션 메커니즘을 통해 클래스의 모든 정보를 얻을 수 있습니다.
2. 리플렉션 메커니즘은 어디에 사용합니까? "com.mysql.jdbc.Driver.class").newInstance(); 하지만 그 당시에는 해당 코드 줄이
드라이버 개체 인스턴스를 생성했다는 것만 알았습니다. , 그리고 그 구체적인 의미를 몰랐습니다. 리플렉션 메커니즘에 대한 강의를 듣고 나서 이것이 리플렉션이라는 것을 깨달았습니다. 요즘에는 많은 오픈 프레임워크가 리플렉션 메커니즘을 사용하여 구현됩니다.
3. 반사 메커니즘의 장점과 단점
반사 메커니즘을 사용하는 이유는 무엇입니까? 객체를 직접 생성하는 것만으로는 충분하지 않나요?
정적 컴파일: 컴파일 타임에 유형을 결정하고 객체를 바인딩합니다. 즉, 통과합니다.
동적 컴파일: 유형을 결정하고 런타임에 객체를 바인딩합니다. 동적 컴파일은 Java의 유연성을 극대화하고 다형성 애플리케이션을 구현하며 클래스 간의 결합을 줄입니다.
한마디로 리플렉션 메커니즘의 장점은 동적으로 객체를 생성하고 컴파일할 수 있다는 점인데, 특히 J2EE 개발에서 뛰어난 유연성을 보여줍니다.
그 유연성은 매우 분명합니다. 예를 들어, 대규모 소프트웨어의 경우 한 번에 완벽하게 설계하는 것은 불가능합니다.
프로그램이 컴파일되어 출시될 때 특정 기능을 업데이트해야 한다고 판단되면 사용자에게 제거를 요청할 수 없습니다. , 새 버전을 다시 설치하세요.
이렇다면 확실히 이 소프트웨어를 사용하는 사람은 많지 않을 것입니다. 정적이라면
함수의 업데이트를 실현하기 위해 전체 프로그램을 한 번 다시 컴파일해야 합니다. 리플렉션 메커니즘을 사용하는 경우에는 제거할 필요가 없으며 런타임에 동적으로 생성하고 컴파일하기만 하면 됩니다.
네.
성능에 영향을 미친다는 단점이 있습니다. 리플렉션을 사용하는 것은 기본적으로 해석된 작업이므로 JVM에 우리가 원하는 작업을 알릴 수 있으며
우리의 요구 사항을 충족합니다. 이러한 작업은 동일한 작업을 직접 수행하는 것보다 항상 느립니다.
4. 리플렉션 메커니즘을 사용하여 얻을 수 있는 정보는 무엇입니까? 먼저, 전달된 클래스의 전체 이름을 기반으로 클래스 개체를 만들어야 합니다.
Class c=Class.forName("className"); 참고: className은 전체 이름이어야 합니다. 즉, 패키지 이름을 포함해야 합니다(예: cn.netjava.pojo.UserInfo)
Object obj; =c.newInstance ();//객체의 인스턴스 생성
좋습니다. 일단 객체가 있으면 모든 작업이 쉽고 원하는 정보를 얻을 수 있습니다.
생성자를 구하는 방법
생성자 getConstructor(Class[] params)//지정된 매개변수에 따라 공용 생성자를 가져옵니다
Constructor[] getConstructors()//모든 공용 생성자를 가져옵니다
생성자 getDeclaredConstructor(Class[] params)//지정된 매개변수에 따라 공용 및 비공개 생성자 가져오기
Constructor[] getDeclaredConstructors()//모든 공용 생성자 가져오기
메소드 getMethod(문자열 이름, 클래스[] params), 메소드 이름 및 매개변수 유형에 따라 메소드 가져오기
메소드[] getMethods()//모든 공용 메소드 가져오기
메소드 getDeclaredMethod(String name, Class[] params)//메소드 이름과 매개변수 유형에 따라 공개 및 비공개 메소드를 가져옵니다.
메소드[] getDeclaredMethods()//공용 및 비공용 메소드를 모두 가져옵니다. -public 메서드
Field getField(String name)//변수 이름에 따라 해당 공용 변수 가져오기
Field[] getFields()//모두 가져오기 클래스의 공용 메소드
필드 getDeclaredField(문자열 이름)//메서드 이름에 따라 공용 및 비공개 변수 가져오기
Field[] getDeclaredFields()//클래스의 모든 공개 및 비공개 메소드를 가져옵니다.
일반적으로 사용되는 메소드입니다. 이것만 알면 나머지는 쉽습니다...
5. 리플렉션 메커니즘으로 무엇을 할 수 있나요?
처음 jdbc를 사용하기 시작했을 때 데이터베이스에 액세스하려고 작성하는 데 토할 것 같았습니다. 테이블이 8개 있었는데, 각 테이블마다 추가, 삭제, 수정, 확인 작업이 있었습니다. .
당시에는 반사 메커니즘이라는 개념이 있는지 몰랐습니다. 그래서 우리는 테이블마다 다른 dao 클래스를 생성하여 개발 속도를 높일 뿐만 아니라
코드를 매우 중복되게 만듭니다. 가장 끔찍한 점은 거의 똑같아 보이지만 직접 복사하고 수정한다는 것입니다. 왜냐하면 온갖 저급 실수(대문자나 소문자,
하나 더 또는 글자 하나 덜하기.. .), 하나의 실수를 찾는 데 오랜 시간이 걸릴 수 있습니다.
Java 리플렉션 메커니즘을 사용하면 dao 클래스, 4가지 메소드 작성, 추가, 삭제, 수정 및 확인, 다른 객체 전달만 하면 됩니다.
아니요. 각 테이블 dao 클래스에 대한 테이블을 생성해야 하며, 리플렉션 메커니즘이 나머지를 자동으로 완료하므로 이것이 장점입니다. 직설적으로 말하면, 반사 메커니즘은 특히
반복적이고 규칙적인 작업을 수행하는 데 도움이 되기 때문에 이제 자동으로 코드를 생성하는 많은 소프트웨어는 규칙에 따라 관련 매개변수를 입력하기만 하면 반사 메커니즘을 사용하여 코드를 완성합니다.
, 그럼 저수준 프로그래머들이 서서히 사라지고 있는 이유는 무엇일까요? 코드를 작성할 필요도 없고 누구나 개발할 수 있는데 왜 프로그래머가 필요한가? 그래서 우리가 나갈 수 있는 길은 단 하나, 열심히 일하고, 수석 프로그래머가 되어, 바보 소프트웨어 개발을 전문으로 하고, 다른 프로그래머들은 제쳐두고 식어가도록 두는 것뿐입니다, 하하~
6. 반사 메커니즘을 사용하여 다음을 수행합니다. 데이터베이스 데이터 추가 및 쿼리 예
기본 원칙; 데이터를 저장할 때 저장해야 하는 개체의 속성 값을 모두 꺼낸 다음 sql 문을 하나로 묶습니다.
쿼리할 때 모든 항목을 패키지합니다. Java 객체에 데이터를 쿼리했습니다.
게임의 규칙: 규칙 없이는 아무것도 없습니다. 특히 프로그램의 경우 규칙이 있어야만 할 수 있지만 규칙 없이는 할 수 없습니다. > 1) 데이터베이스의 각 테이블 개체에는 pojo 클래스가 있으며 테이블의 각 필드는 pojo 클래스의 속성에 해당합니다.
그리고 pojo 클래스의 이름은 테이블 이름과 동일하고, 속성 이름과 필드 이름도 동일합니다. 데이터베이스는 일반적으로 대소문자를 구분하지 않기 때문에 대소문자는 중요하지 않습니다.
2) 추가 표준 설정 및 가져오기 방법.
게임의 규칙에 따라 게임을 시작하겠습니다.
1. 먼저 데이터베이스에 테이블이 있습니다. 데이터베이스 이름이 blogsystem이고 테이블 이름 중 하나가 userinfo라고 가정합니다. 그림과 같이:
2. 해당 pojo 클래스를 생성합니다:
2.
package cn.netjava.pojo; public class UserInfo { private int id; private String name; private String pwd; private int age; @Override public String toString() { return "UserInfo [id=" + id + ", name=" + name + ", pwd=" + pwd + ", age=" + age + "]"; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
3. 재미가 시작됩니다. dao 클래스를 작성하여 데이터베이스를 운영합니다
package cn.netjava.factory; import java.sql.Connection; import java.sql.DriverManager; public class Connect2DBFactory { public static Connection getDBConnection() { Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/blogsystem"; String user = "root"; String password = "netjava"; conn = DriverManager.getConnection(url, user, password); } catch (Exception e) { e.printStackTrace(); } return conn; } }
4. 테스트 시작 효과는 어떻습니까:
package cn.netjava.session; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import cn.netjava.factory.Connect2DBFactory; import cn.netjava.pojo.UserInfo; public class NetJavaSession { /** * 解析出保存对象的sql语句 * * @param object * :需要保存的对象 * @return:保存对象的sql语句 */ public static String getSaveObjectSql(Object object) { // 定义一个sql字符串 String sql = "insert into "; // 得到对象的类 Class c = object.getClass(); // 得到对象中所有的方法 Method[] methods = c.getMethods(); // 得到对象中所有的属性 Field[] fields = c.getFields(); // 得到对象类的名字 String cName = c.getName(); // 从类的名字中解析出表名 String tableName = cName.substring(cName.lastIndexOf(".") + 1, cName.length()); sql += tableName + "("; List<String> mList = new ArrayList<String>(); List vList = new ArrayList(); for (Method method : methods) { String mName = method.getName(); if (mName.startsWith("get") && !mName.startsWith("getClass")) { String fieldName = mName.substring(3, mName.length()); mList.add(fieldName); System.out.println("字段名字----->" + fieldName); try { Object value = method.invoke(object, null); System.out.println("执行方法返回的值:" + value); if (value instanceof String) { vList.add("\"" + value + "\""); System.out.println("字段值------>" + value); } else { vList.add(value); } } catch (Exception e) { e.printStackTrace(); } } } for (int i = 0; i < mList.size(); i++) { if (i < mList.size() - 1) { sql += mList.get(i) + ","; } else { sql += mList.get(i) + ") values("; } } for (int i = 0; i < vList.size(); i++) { if (i < vList.size() - 1) { sql += vList.get(i) + ","; } else { sql += vList.get(i) + ")"; } } return sql; } public static List getDatasFromDB(String tableName, int Id) { return null; } /** * 将对象保存到数据库中 * * @param object * :需要保存的对象 * @return:方法执行的结果;1:表示成功,0:表示失败 */ public int saveObject(Object object) { Connection con = Connect2DBFactory.getDBConnection(); String sql = getSaveObjectSql(object); try { // Statement statement=(Statement) con.createStatement(); PreparedStatement psmt = con.prepareStatement(sql); psmt.executeUpdate(); return 1; } catch (SQLException e) { e.printStackTrace(); return 0; } } /** * 从数据库中取得对象 * * @param arg0 * :对象所属的类 * @param id * :对象的id * @return:需要查找的对象 */ public Object getObject(String className, int Id) { // 得到表名字 String tableName = className.substring(className.lastIndexOf(".") + 1, className.length()); // 根据类名来创建Class对象 Class c = null; try { c = Class.forName(className); } catch (ClassNotFoundException e1) { e1.printStackTrace(); } // 拼凑查询sql语句 String sql = "select * from " + tableName + " where Id=" + Id; System.out.println("查找sql语句:" + sql); // 获得数据库链接 Connection con = Connect2DBFactory.getDBConnection(); // 创建类的实例 Object obj = null; try { Statement stm = con.createStatement(); // 得到执行查寻语句返回的结果集 ResultSet set = stm.executeQuery(sql); // 得到对象的方法数组 Method[] methods = c.getMethods(); // 遍历结果集 while (set.next()) { obj = c.newInstance(); // 遍历对象的方法 for (Method method : methods) { String methodName = method.getName(); // 如果对象的方法以set开头 if (methodName.startsWith("set")) { // 根据方法名字得到数据表格中字段的名字 String columnName = methodName.substring(3, methodName.length()); // 得到方法的参数类型 Class[] parmts = method.getParameterTypes(); if (parmts[0] == String.class) { // 如果参数为String类型,则从结果集中按照列名取得对应的值,并且执行改set方法 method.invoke(obj, set.getString(columnName)); } if (parmts[0] == int.class) { method.invoke(obj, set.getInt(columnName)); } } } } } catch (Exception e) { e.printStackTrace(); } return obj; } }
5. 인쇄된 결과:
package cn.netjava.tester; import cn.netjava.pojo.UserInfo; import cn.netjava.session.NetJavaSession; public class Tester { public static void main(String args[]) { //获得NetJavaSession对象 NetJavaSession session = new NetJavaSession(); //创建一个UserInfo对象 UserInfo user = new UserInfo(); //设置对象的属性 user.setId(6988); user.setAge(44); user.setPwd("pwd"); user.setName("champion"); //将对象保存到数据库中 String sql = session.getSaveObjectSql(user); System.out.println("保存对象的sql语句:" + sql); //查找对象 UserInfo userInfo = (UserInfo) session.getObject( "cn.netjava.pojo.UserInfo", 6988); System.out.println("获取到的信息:" + userInfo); } }
7. 요약
일반적으로 Java 리플렉션 메커니즘은 매우 유용하며 많은 문제를 해결할 수 있습니다. , 반사 메커니즘이 매우 유연하기 때문에 데이터베이스를 작동하기 위해 코드를 작성하는 데 너무 많은 시간을 할애할 필요가 없지만 프로젝트의 논리적 기능에 더 많은 시간을 할애할 수 있습니다. 개발 시간을 단축하고 코드 가독성을 높입니다. 기존의 많은 오픈 소스 프레임워크는 리플렉션 메커니즘을 사용하여 파일을 구성한 다음 규칙에 따라 해당 메서드를 호출하기만 하면 됩니다.