programing

Java 이름 숨기기:하드웨이

shortcode 2022. 12. 24. 21:42
반응형

Java 이름 숨기기:하드웨이

나는 이름 감추기에 매우 어려운 문제가 있다.다음은 이 문제를 설명하는 간략화된 버전입니다.

클래스가 있습니다.org.A

package org;
public class A{
     public class X{...}
     ...
     protected int net;
}

다음에 요.net.foo.X

package net.foo;
public class X{
     public static void doSomething();
}

.이러한계급은우리나라를 입니다.A하고 net.foo.X.doSomething()

package com.bar;
class B extends A {

    public void doSomething(){
        net.foo.X.doSomething(); // doesn't work; package net is hidden by inherited field
        X.doSomething(); // doesn't work; type net.foo.X is hidden by inherited X
    }
}

시시시, 시시이이이 이다다다할 수 .X상속된 유형에 의해 숨겨지기 때문입니다.할 수 .net.foo.X, 냐냐net는 상속된 필드에 의해 숨겨집니다.

B에 있다; ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」net.foo.X ★★★★★★★★★★★★★★★★★」org.A★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★!

유일한 솔루션은 다음과 같습니다. 할 수 .X.doSomething(); 하지만 이 클래스는 이름 충돌 때문에 존재할 뿐이고, 그것은 매우 지저분해 보인다!가 직접 할 수 있는 ?X.doSomething()부에서B.doSomething()????

글로벌 네임스페이스, 로, 임, 벌 스 정 는 할 : 있 언 in a예 namespace,수(,지ifyingg that the e spec어네를스이페 globalglobal::C# 또는 C# 는):: in C++, I could simply prefix C++에서는, 간단하게 프레픽스를 붙일 수 있습니다.net이 글로벌 접두사가 있지만 Java는 그것을 허용하지 않습니다.이 글로벌 프레픽스를 사용하는데 Java에서는 허용되지 않습니다.

You can cast a 캐스트 할 수 있습니다.null(타깃 오브젝트는 정적 메서드의 호출에 관여하지 않기 때문에 동작합니다).

((net.foo.X) null).doSomething();

이 방법에는 다음과 같은 메리트가 있습니다.

  • 없는 net.foo.X
  • 가 없다(을 알 수 )B '아까', '아까', '아까', '아까', '아까', '아까',import static것 같다'는 안 될 것 같아요.
  • (좋은 생각일 수도 있지만) 대표자 클래스의 도입은 필요 없습니다.
  • 리플렉션 API로 작업하는 데 따른 오버헤드나 복잡성이 필요하지 않습니다.

단점은 이 코드가 정말 끔찍하다는 거야!제게는, 경고가 생성되고, 그것은 일반적으로 좋은 일입니다.하지만 완전히 비현실적인 문제를 해결하기 위해,

@SuppressWarnings("static-access")

컴파일러를 셧다운합니다.

아마도 가장 간단한 방법(꼭 가장 쉬운 방법은 아님)은 위임 클래스를 사용하는 것입니다.

import net.foo.X;
class C {
    static void doSomething() {
         X.doSomething();
    }
}

그리고...

class B extends A {
    void doX(){
        C.doSomething();
    }
}

유연합니다. 하게 할 수 , 이 두 가지 같은 방식으로 합니다.이치게다가, 양쪽 모두에서, 거의 같은 방법으로 동작합니다.static메서드 및 인스턴스화된 객체

위임 객체에 대한 자세한 내용은 http://en.wikipedia.org/wiki/Delegation_pattern를 참조하십시오.

스태틱 Import를 사용할 수 있습니다.

import static net.foo.X.doSomething;

class B extends A {
    void doX(){
        doSomething();
    }
}

조심해B그리고.A명명된 메서드가 포함되어 있지 않습니다.doSomething

적절한 작업 방법은 정적 가져오기를 사용하는 것이지만, 최악의 경우 완전 수식 이름을 알고 있는 경우 반사를 사용하여 클래스의 인스턴스를 생성할 수 있습니다.

Java: 기본 생성자가 없는 클래스의 newInstance

그런 다음 인스턴스에서 메서드를 호출합니다.

또는 메서드 자체를 반영하여 호출합니다.리플렉션을 사용한 정적 메서드 호출

Class<?> clazz = Class.forName("net.foo.X");
Method method = clazz.getMethod("doSomething");
Object o = method.invoke(null);

물론 이것들은 분명히 최후의 수단이다.

정답은 아니지만 X의 인스턴스를 만들고 해당 인스턴스의 정적 메서드를 호출할 수 있습니다.그렇게 하는 것이 (더러운 것은 인정합니다) 당신의 방법일 것입니다.

(new net.foo.X()).doSomething();

캐스트하거나 이상한 경고를 억제하거나 중복 인스턴스를 생성할 필요가 없습니다.서브클래스를 통해 부모클래스의 스태틱메서드를 호출할 수 있다는 사실을 이용한 트릭입니다.(이쪽의 해킹 솔루션과 유사합니다.)

이런 클래스만 만들면 됩니다.

public final class XX extends X {
    private XX(){
    }
}

(이 최종 클래스의 프라이빗컨스트럭터는 실수로 이 클래스의 인스턴스를 만들지 않도록 합니다).

그럼 전화하셔도 됩니다.X.doSomething()경유:

    public class B extends A {

        public void doSomething() {
            XX.doSomething();
        }

모든 파일이 동일한 폴더에 있는 경우 gobal namespace를 가져오려고 하면 어떻게 됩니까?(http://www.beanshell.org/javadoc/bsh/class-use/NameSpace.html)

    package com.bar;
      class B extends A {

       public void doSomething(){
         com.bar.getGlobal().net.foo.X.doSomething(); // drill down from the top...

         }
     }

이것이 상속보다 구성이 더 나은 이유 중 하나이다.

package com.bar;
import java.util.concurrent.Callable;
public class C implements Callable<org.A>
{
    private class B extends org.A{
    public void doSomething(){
        C.this.doSomething();
    }
    }

    private void doSomething(){
    net.foo.X.doSomething();
    }

    public org.A call(){
    return new B();
    }
}

저는 Strategy 패턴을 사용합니다.

public interface SomethingStrategy {

   void doSomething();
}

public class XSomethingStrategy implements SomethingStrategy {

    import net.foo.X;

    @Override
    void doSomething(){
        X.doSomething();
    }
}

class B extends A {

    private final SomethingStrategy strategy;

    public B(final SomethingStrategy strategy){
       this.strategy = strategy;
    }

    public void doSomething(){

        strategy.doSomething();
    }
}

이제 의존 관계도 분리되었으므로 단위 테스트를 작성하기가 더 쉬워집니다.

언급URL : https://stackoverflow.com/questions/24572214/java-name-hiding-the-hard-way

반응형