리플렉션을 통해 내부 클래스 객체 생성
먼저 javalang 패키지 아래에 내부 클래스를 포함하는 클래스를 작성합니다.
package javalang; public class Outer { public static class Inner1{} }
이 클래스는 공개 정적이므로 천천히 추가할 예정입니다. 나중에 이 수정자를 제거하세요.
Reflection을 통해 Inner1 객체를 생성하려면 먼저 Inner1의 Class 객체를 얻어야 합니다. Outer에 메인 메소드를 작성합니다:
public class Outer { public static class Inner1{} public static void main(String[] args) { System.out.println(Inner1.class); } }
출력 결과:
class javalang.Outer$Inner1
그런 다음 클래스 이름이 올바른지 확인합니다:
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1")); }
Run 잠시만요, 그렇죠. 그런 다음 이를 사용하여 개체를 만듭니다. 객체 생성은 생성자에 의존합니다. 이 클래스에 생성자 메서드가 있나요? 다음과 같이 쓸 수 있습니다:
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1").getConstructors().length); }
실행하고 1을 출력합니다. 있는 것 같습니다. 그런 다음 이 구성 방법이 어떻게 보이는지 살펴보세요.
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1").getConstructors()[0]); }
출력 결과: public javalang.Outer$Inner1(). 이것이 기본 구축 방법입니다. 따라서 다음과 같이 작성할 수 있습니다.
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1") .getConstructors()[0].newInstance(); }
출력 결과: javalang.Outer$Inner1@ca0b6. 이는 실행이 성공했음을 나타냅니다.
다음으로 Inner의 public 키워드를 제거하고 다시 실행합니다. 결과는 오류였습니다:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
이는 구성 방법을 찾을 수 없음을 의미합니다. 정말 그렇지 않나요? 기본 메소드를 다시 변경합니다:
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1") .getConstructors().length); }
출력 결과: 0. 정말 생성자가 없나요? 사실 아니죠. 단지 공법이 공개되지 않았을 뿐입니다. 이때 getDeclaredConstructors()를 사용하여 다음을 얻어야 합니다.
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1") .getDeclaredConstructors().length); }
출력 결과: 1. 시공방법을 찾아드립니다. 그런 다음 계속해서 이 생성자를 호출합니다.
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1") .getDeclaredConstructors()[0].newInstance()); }
출력 결과: javalang.Outer$Inner1@ca0b6. 이제 리플렉션을 사용하여 비공개 내부 클래스의 개체를 생성할 수 있습니다.
다음으로 static 키워드를 삭제해 보겠습니다. 이때 오류가 보고되었습니다:
스레드 "main" java.lang.IllegalArgumentException: 잘못된 인수 개수
이것은 무엇을 의미합니까? 우리는 호출했을 때 매개 변수를 전달하지 않았으며 오류 내용은 매개 변수 수가 잘못되었다는 것입니다. 그러면 이 생성자에는 어떤 매개변수가 있습니까? 코드를 변경하여 살펴보겠습니다.
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1") .getDeclaredConstructors()[0]); }
출력 결과: javalang.Outer$Inner1(javalang.Outer)
생성자에는 Outer 유형 매개변수가 필요한 것으로 나타났습니다. 이는 쉽습니다:
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1") .getDeclaredConstructors()[0].newInstance(new Outer())); }
출력 결과:
javalang.Outer$Inner1@ca0b6
그렇습니다. 비정적 내부 클래스에는 기본 생성 방법이 없고 생성 중에 외부 클래스의 인스턴스를 매개변수로 전달해야 하는 것 같습니다.
Java: 객체에 액세스하는 방법
Java 초보자의 고민은 객체를 메소드 변수로 정의할지 아니면 멤버 변수로 정의할지 결정하는 것입니다.
초보자는 처음에는 이런 것에 신경 쓰지 않습니다. 하지만 작성된 프로그램이 점점 더 커지고 클래스가 많아지면 이런 고민도 생깁니다.
하지만 여기서 쓰고 싶은 것은 객체를 원하는 대로 배열하여 언제든지 접근할 수 있도록 하는 방법입니다. 이것을 마스터하면 개체를 배치할 위치를 자유롭게 결정할 수 있습니다.
다음은 간단한 예입니다.
public class AccessingObject { public static void main(String[] args) { Date date = new Date(); } // 获得 date 对象一小时后的时间 private static void anHourLater() { // 这里如何获得 main() 方法中的 date 变量? } }
anHourLater() 메서드에 설명된 대로 1시간 후의 날짜를 가져오려고 합니다. 무엇을 해야 할까요? 아래에는 여러 가지 방법이 있습니다.
(1) 매개변수 전달
public class AccessingObject { public static void main(String[] args) { Date date = new Date(); anHourLater(date); } // 获得 date 对象一小时后的时间 private static void anHourLater(Date d) { Date anHourLater = new Date(d.getTime() + 3600000); } }
(2) 멤버로 정의됩니다. 멤버는 모든 메서드에서 액세스할 수 있으며 멤버 초기화는 멤버가 정의된 위치나 모든 메서드에 배치될 수 있습니다.
rree
(3) 다른 클래스에 넣어보세요. 다음 예제에서 DateHolder.date는 AccessingObject 클래스뿐만 아니라 동일한 패키지의 모든 클래스에서 액세스할 수 있습니다.
public class AccessingObject { private static Date date; public static void main(String[] args) { date = new Date(); anHourLater(); } // 获得 date 对象一小时后的时间 private static void anHourLater() { Date anHourLater = new Date(date.getTime() + 3600000); } }
이 세 가지 예를 비교해 보면 처음 두 개는 클래스 내부에서만 사용할 수 있고 비교적 안전합니다. 이 객체를 다른 클래스에서 직접 수정하지 않으려면 세 번째 방법을 사용하지 마세요.
첫 번째 방법과 두 번째 방법의 차이점은 객체를 메소드에서만 사용하면 해당 메소드가 실행될 때 객체를 쉽게 재활용할 수 있다는 점입니다. (참고, 즉시 재활용되지는 않습니다.) . 클래스의 멤버로 정의된 경우 객체는 해당 객체가 위치한 클래스가 재활용된 후에만 재활용됩니다. 분명히 첫 번째 방법이 자원을 가장 많이 절약하므로 첫 번째 방법을 사용하도록 노력해야 합니다.
이 세 가지 예를 살펴보면 main() 메서드가 anHourLater() 메서드에서 얻은 1시간 후의 시간을 얻으려는 경우에도 이에 상응하는 여러 가지 방법이 있습니다. 마지막 두 예제는 변경할 필요가 없습니다. 날짜 개체에 직접 액세스할 수 있습니다. 첫 번째 예제에는 두 가지 수정 방법이 있습니다.
(1) 반환 값
public class AccessingObject { public static void main(String[] args) { DateHolder.date = new Date(); } // 获得 date 对象一小时后的时间 private static void anHourLater() { Date anHourLater = new Date(DateHolder.date.getTime() + 3600000); } } class DateHolder { public static Date date; }
(2) 매개변수의 내용을 직접 수정
public class AccessingObject { public static void main(String[] args) { Date date = new Date(); Date anHourLater = anHourLater(date); } // 获得 date 对象一小时后的时间 private static Date anHourLater(Date d) { return new Date(d.getTime() + 3600000); } }
뭔가 잘못되었습니다. 메소드 호출자가 좋아하는지 알 수 없습니다.
Java에서 내부 클래스 객체를 구성하고 객체에 액세스하는 방법을 설명하는 더 많은 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!