"Class.forName()"과 "Class.forName().newInstance()"의 차이점은 무엇입니까?
Class.forName()
★★★★★★★★★★★★★★★★★」Class.forName().newInstance()
나는 그 차이를 이해할 수 없다(그들에 대해 뭔가 읽은 적이 있다!).도와주실 수 있나요?
두 가지 방법이 어떻게 사용되는지 보여주는 예가 상황을 더 잘 이해하는 데 도움이 될 수 있습니다.따라서 다음 클래스를 고려하십시오.
package test;
public class Demo {
public Demo() {
System.out.println("Hi!");
}
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("test.Demo");
Demo demo = (Demo) clazz.newInstance();
}
}
javadoc에서 설명한 바와 같이 calling은 지정된 문자열 이름의 클래스 또는 인터페이스와 관련된 개체를 반환합니다.즉, 반환됩니다.test.Demo.class
.clazz
「」의 Class
.
그런 다음 호출하면 이 객체가 나타내는 클래스의 새 인스턴스가 생성됩니다. 인수 목록이 비어 있는 식에 의해 클래스가 인스턴스화됩니다.즉, 이것은 실제적으로 1차적으로new Demo()
됩니다.Demo
.
이 실행 중.Demo
수업
Hi!
의 존존 의 큰 new
라는 것이다.newInstance
실행 시까지 알 수 없는 클래스를 인스턴스화하여 코드를 보다 역동적으로 만들 수 있습니다.
일반적인 예로는 실행 시 작업을 수행하는 데 필요한 정확한 드라이버를 로드하는 JDBC API가 있습니다.EJB 컨테이너, Servlet 컨테이너도 다른 좋은 예입니다. 즉, 동적 런타임 로딩을 사용하여 런타임 전에 아무것도 모르는 구성요소를 로드하고 생성합니다.
사실, 더 나아가고 싶다면 바로 위의 단락에서 설명한 Ted Neward 논문 Understanding Class.forName()을 참조하십시오.
EDIT(코멘트로 게시된 OP의 질문에 답변):JDBC 드라이버의 경우는 조금 특별합니다.JDBC API를 시작하기 위한 드라이버 매니저 장에서 설명한 바와 같이
(...) A
Driver
됩니다.DriverManager
두 중 즉 '두 가지'입니다
Class.forName
드라이버 클래스를 명시적으로 로드합니다.셋업에 에, 이 은, 「드라이버 로드 방법」을 합니다.DriverManager
를 참조할 수 있습니다.합니다.acme.db.Driver
:Class.forName("acme.db.Driver");
이 로드되면 인스턴스가 생성되고 해당 인스턴스가 파라미터(필요한 대로)로서 호출되도록 기술되어 있는 경우, 그 인스턴스는
DriverManager
접속 작성에 사용할 수 있는 드라이버 목록입니다.
- (...)
모두 입니다.
Driver
는 "class"를 호출하여 합니다.DriverManager.registerDriver
앞에서 설명한 바와 같이 이 작업은 클래스가 로드될 때 자동으로 수행되어야 합니다.
초기화중에 자신을 등록하기 위해서, 통상, JDBC 드라이버는 다음과 같은 스태틱 초기화 블록을 사용합니다.
package acme.db;
public class Driver {
static {
java.sql.DriverManager.registerDriver(new Driver());
}
...
}
" "Class.forName("acme.db.Driver")
는, 을 하는 원인이 됩니다.acme.db.Driver
아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 맞다. ★★★★★★★★★★★★★★★★★.Class.forName("acme.db.Driver")
는 실제로 인스턴스를 "작성"하지만 이는 (정상적인) JDBC 드라이버가 구현되는 방법의 결과일 뿐입니다.
참고로 JDBC 4.0(Java 7 이후 기본 패키지로 추가)과 JDBC 4.0 드라이버의 새로운 자동 로딩 기능에서는 이 모든 것이 더 이상 필요하지 않습니다.Java SE 6 의 JDBC 4.0 확장 기능을 참조해 주세요.
class.forName()은 Class.forName()을 사용합니다.이 객체의 메서드는 클래스를 작성하는 프로그래머가 아니라 Java에 의해 정의됩니다.이치노 "newInstance()"를 호출합니다.Class.forName("ExampleClass").newInstance()
라고 부르는 것과 new ExampleClass()
클래스 정의 메서드를 호출하여 표시되는 필드 등에 액세스 할 수 있습니다.
JDBC 세계에서는 (JDBC API에 따라) 일반적인 방법은Class#forName()
JDBC 드라이버를 로드합니다.JDBC 드라이버는 스태틱블록 내부에 등록해야 합니다.
package com.dbvendor.jdbc;
import java.sql.Driver;
import java.sql.DriverManager;
public class MyDriver implements Driver {
static {
DriverManager.registerDriver(new MyDriver());
}
public MyDriver() {
//
}
}
호출Class#forName()
는 모든 스태틱 이니셜라이저를 실행합니다.이쪽에서DriverManager
는, 접속 URL 에 의해서, 등록된 드라이버에 관련 붙여진 드라이버를 검색할 수 있습니다.이 기간 동안 대략 다음과 같습니다.
public static Connection getConnection(String url) throws SQLException {
for (Driver driver : registeredDrivers) {
if (driver.acceptsURL(url)) {
return driver.connect(url);
}
}
throw new SQLException("No suitable driver");
}
하지만 버그가 있는 JDBC 드라이버도 있었습니다.org.gjt.mm.mysql.Driver
잘 알려진 예로서, 이 예에서는 스태틱블록이 아닌 컨스트럭터 내에 잘못 등록됩니다.
package com.dbvendor.jdbc;
import java.sql.Driver;
import java.sql.DriverManager;
public class BadDriver implements Driver {
public BadDriver() {
DriverManager.registerDriver(this);
}
}
동적으로 동작시키는 유일한 방법은newInstance()
나중에!그렇지 않으면 첫눈에 설명할 수 없는 "SQLException: 적절한 드라이버 없음"에 직면하게 됩니다.이것은 JDBC 드라이버의 버그이며, 독자적인 코드가 아닙니다.현재 JDBC 드라이버에는 이 버그가 포함되어 있지 않습니다.그래서 당신은 (그리고 그래야 한다)newInstance()
떨어져.
1 : 클래스의 스태틱블록에만 관심이 있는 경우 클래스만 로드하면 스태틱블록이 실행됩니다.필요한 것은 다음과 같습니다.
Class.forName("Somthing");
2 : 클래스를 로드하고 스태틱블록을 실행하고 그 비 스태틱 부분에 액세스하려면 인스턴스가 필요하고 그 다음에 다음이 필요합니다.
Class.forName("Somthing").newInstance();
Class.forName()은 클래스, Class.forName()에 대한 참조를 가져옵니다.newInstance()는 클래스가 no-arg 컨스트럭터를 사용하여 새 인스턴스를 반환하려고 합니다.
"Class.forName()"은 지정된 이름의 클래스 유형을 반환합니다."new Instance()"는 이 클래스의 인스턴스를 반환합니다.
유형에서는 인스턴스 메서드를 직접 호출할 수 없고 클래스에 대한 반사만 사용할 수 있습니다.클래스의 오브젝트를 조작하려면 오브젝트의 인스턴스를 작성해야 합니다(「new MyClass()」를 호출하는 것과 같음).
Class.forName()의 예
Class myClass = Class.forName("test.MyClass");
System.out.println("Number of public methods: " + myClass.getMethods().length);
Class.forName().newInstance()의 예
MyClass myClass = (MyClass) Class.forName("test.MyClass").newInstance();
System.out.println("String representation of MyClass instance: " + myClass.toString());
위의 답변에 추가하기만 하면 메모리에 존재할 필요가 있는 정적 코드(즉, 코드 블록이 인스턴스에 의존하지 않음)가 있는 경우 클래스를 반환하여 Class.forname("someName")을 사용할 수 있습니다.그렇지 않으면 정적 코드가 없는 경우 Class.forname().New Instance("someName")는 객체 수준 코드를 메모에 로드하기 때문에 Class.forname("non"nonstatic memo")를 사용할 수 있습니다.라이
Class.forName() 메서드를 호출하는 횟수에 관계없이 스태틱블록이 실행된 후만 여러 번 호출하지 않습니다.
package forNameMethodDemo;
public class MainClass {
public static void main(String[] args) throws Exception {
Class.forName("forNameMethodDemo.DemoClass");
Class.forName("forNameMethodDemo.DemoClass");
Class.forName("forNameMethodDemo.DemoClass");
DemoClass demoClass = (DemoClass)Class.forName("forNameMethodDemo.DemoClass").newInstance();
}
}
public class DemoClass {
static {
System.out.println("in Static block");
}
{
System.out.println("in Instance block");
}
}
출력은 다음과 같습니다.
in Static block
in Instance block
이것.in Static block
세 번이 아니라 한 번만 인쇄됩니다.
Class.forName()
-->forName()은 Class의 스태틱메서드로 사용자 클래스 객체가 아닌 리플렉션에 사용되는 Class 클래스 객체를 반환하므로 클래스 메서드만 호출할 수 있습니다.getMethods()
,getConstructors()
기타.
(Runtime given) 클래스의 정적 블록만 실행하고 클래스의 메서드, 컨스트럭터, Modifier 등의 정보만 가져오는 경우 이 개체를 사용할 수 있습니다.Class.forName()
그러나 클래스 메서드(실행 시 지정한 클래스)에 액세스하거나 호출하려면 클래스 클래스의 newInstance 메서드가 대신 수행하도록 개체를 설정해야 합니다.그러면 클래스의 새 인스턴스가 생성되어 반환됩니다.너는 그것을 너의 반에 타이프 캐스팅하기만 하면 된다.
예: 종업원이 당신의 클래스라고 가정합니다.
Class a=Class.forName(args[0]);
//args[0]=cmd line argument to give class at runtime.
Employee ob1=a.newInstance();
a.newInstance()
를 사용하여 오브젝트를 작성하는 것과 비슷합니다.new Employee()
.
이제 클래스에 표시되는 모든 필드 및 메서드에 액세스할 수 있습니다.
언급URL : https://stackoverflow.com/questions/2092659/what-is-the-difference-between-class-forname-and-class-forname-newinstanc
'programing' 카테고리의 다른 글
Android에서 색 정수를 16진수 문자열로 변환하는 방법 (0) | 2022.09.15 |
---|---|
MySQL 프로세스 목록을 찾아서 프로세스를 종료하려면 어떻게 해야 합니까? (0) | 2022.09.15 |
MariaDB convert_tz maketime (0) | 2022.09.15 |
진행률 표시기를 순수 C/C++(cout/printf)로 표시하는 방법 (0) | 2022.09.15 |
Firebase Firestore 'Reference' 데이터 유형은 무엇에 유효합니까? (0) | 2022.09.15 |