修改最终公共类Java中的最终静态变量

修改最终公共类Java中的最终静态变量,java,reflection,apple-push-notifications,java-9,java-11,Java,Reflection,Apple Push Notifications,Java 9,Java 11,我有一个关于修改最后一个公共类的快速问题。根据一些研究,最终的公共类似乎无法继承或实现。我的目标是在最后一个公共类中更改最后一个静态变量 类名为:公共最终类Utils private static final Set<String> DISALLOWED_HEADERS_SET = Set.of( "authorization", "connection", "cookie", "content-length", "date", "expect", "from", "

我有一个关于修改最后一个公共类的快速问题。根据一些研究,最终的公共类似乎无法继承或实现。我的目标是在最后一个公共类中更改最后一个静态变量

类名为:公共最终类Utils

private static final Set<String> DISALLOWED_HEADERS_SET = Set.of(
    "authorization", "connection", "cookie", "content-length",
    "date", "expect", "from", "host", "origin", "proxy-authorization",
    "referer", "user-agent", "upgrade", "via", "warning");
private static final Set不允许\u HEADERS\u Set=Set.of(
“授权”、“连接”、“cookie”、“内容长度”,
“日期”、“预期”、“发件人”、“主机”、“来源”、“代理授权”,
“推荐人”、“用户代理”、“升级”、“通过”、“警告”);
我想从这个
不允许的\u头\u集
中去掉
授权
字段。有没有办法做到这一点

我听说反射是修改类的一种方法。这是github的一个例子,它似乎揭示了类的内部内容


此线程(问题)已确定为XY问题。我将尝试用更多的信息来解释我为什么想要解决上述问题。在深入探究促使我提出这个问题的原因之前,我将介绍到目前为止这个问题的现状

重要的是要理解,to已经提出了这个问题。如果您遵循Oracle链接,您可以看到此问题已被确认并更新到
Jdk 11
。Oracle很有希望将此固定源代码应用于即将推出的
Java10
,但鉴于
JDK9
代表
Java9
,这种可能性很小。话虽如此,唯一的解决办法是使用反射的建议

现在,我将简要说明我所取得的成就,并试图找出答案。我一直在开发一个使用Java语言向APN发送推送通知的框架。除了一个功能外,所有功能都正常工作

[我将在不久的将来通过GitHub为那些试图在不依赖第三方框架(如Jetty、Netty或okhttp)的情况下向APN发送通知的人共享此框架。]

当我尝试使用令牌作为身份验证的方式来发送通知时,问题就出现了。我已经按照提供的指令成功创建了令牌。我所要做的就是用
授权
键和
承载
值设置请求头。但是,当我使用从模块派生的
.setHeader
来设置这些值时,它会自动忽略此字段。如上所述,
授权
不允许的头集
的一部分,显然是不允许的。如果用户试图将“授权”设置为请求标头字段的键值,则会将其删除。如果你有任何解决这个问题的建议。这将是可怕的,并有助于其他人面临同样的问题


坏消息,伙计们
jdk 9.0.4
已删除
setSystemHeader
方法,因此如果要使用
reflection
,则需要使用
jdk 9.0.1



正如前面所承诺的,我使用纯java代码创建了用于发送通知的java库,并将其推送到服务器。对于我发布的应用程序,我使用了基于
jdk10
的旧版本。旧版本仅支持tls连接。现在,基于jdk11的当前版本支持tls和基于令牌的身份验证,以向APN发送推送通知

由于这个值是静态的,所以我不清楚通过继承可以实现什么。 但是,如果您可以重新编译应用程序,您是否考虑过对象组合?这可以是继承的替代方法,通常用于在最终类或“乘法”继承的情况下模拟多态行为。 如果您可以“注入”新类而不是原始类(最终类),则可以组成一个包含最终类实例的新类,并将其方法委托给它们。无需创建相同的最终静态变量。

如果需要,这可能有助于-

Class reqClz = request.getClass();

Method setHeaderMethod = reqClz.getDeclaredMethod("setSystemHeader", String.class, String.class);
setHeaderMethod.setAccessible(true);

setHeaderMethod.invoke(request, "authorization", "<token>");
Class reqClz=request.getClass();
方法setHeaderMethod=reqClz.getDeclaredMethod(“setSystemHeader”,String.class,String.class);
setHeaderMethod.setAccessible(true);
调用(请求,“授权”和“”);
为此,您可能必须使用VM arg打开孵化器模块的软件包:-

--add-opens jdk.incubator.httpclient/jdk.incubator.http=<your-package x.y.z>
--添加打开jdk.incubator.httpclient/jdk.incubator.http=

我也在想,这里的另一种方式可能是

——补丁模块=()*

对于jdk.incubator.http.internal.common.Utils类,建议不要超过测试或调试目的。

以下代码允许您更改专用静态字段(非最终字段)的值:

import java.lang.reflect.Field;
导入java.util.ArrayList;
导入java.util.Collections;
导入java.util.HashSet;
导入java.util.Set;
公共类SetFinalField{
@抑制警告(“未选中”)
公共最终静态void main(字符串[]args)引发异常{
System.out.println(“前面的元素:“+SetTarget.DISALLOWED\u HEADERS\u SET”);
字段f=SetTarget.class.getDeclaredField(“不允许的标题集”);
f、 setAccessible(true);
ArrayList l=新的ArrayList();
l、 addAll((Set)f.get(null));
l、 撤销(“授权”);
HashSet hs=新的HashSet();
hs.addAll(l);
f、 集合(null,Collections.unmodifiableSet(hs));
System.out.println(“以下元素:“+SetTarget.DISALLOWED\u HEADERS\u SET”);
}
公共最终静态类SetTarget{
私有静态集不允许\u头\u集;
静止的{
HashSet l=新的HashSet();
addAll(l,新字符串[]{“授权”、“连接”、“cookie”、“内容长度”,
“日期”、“预期”、“发件人”、“主机”、“来源”、“代理授权”,
“推荐人”、“用户年龄”
--patch-module <module>=<file>(<pathsep><file>)*
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class SetFinalField {

    @SuppressWarnings("unchecked")
    public final static void main(String[] args) throws Exception {
        System.out.println("elements before: " + SetTarget.DISALLOWED_HEADERS_SET);
        Field f = SetTarget.class.getDeclaredField("DISALLOWED_HEADERS_SET");
        f.setAccessible(true);
        ArrayList<String> l = new ArrayList<String>();
        l.addAll((Set<String>) f.get(null));
        l.remove("authorization");
        HashSet<String> hs = new HashSet<>();
        hs.addAll(l);
        f.set(null, Collections.unmodifiableSet(hs));
        System.out.println("elements after: " + SetTarget.DISALLOWED_HEADERS_SET);
    }

    public final static class SetTarget {
        private static Set<String> DISALLOWED_HEADERS_SET;

        static {
            HashSet<String> l = new HashSet<>();
            Collections.addAll(l, new String[]{"authorization", "connection", "cookie", "content-length",
                    "date", "expect", "from", "host", "origin", "proxy-authorization",
                    "referer", "user-agent", "upgrade", "via", "warning"});
            DISALLOWED_HEADERS_SET = Collections.unmodifiableSet(l);
        }
    }

}
        Field f = Utils.class.getDeclaredField("DISALLOWED_HEADERS_SET");
        f.setAccessible(true);

        @SuppressWarnings("unchecked")
        Set<String> headers = (Set<String>)f.get(null);        
        headers.remove("authorization");