相关疑难解决方法(0)

可以显式删除lambda的序列化支持

由于已经知道它很容易地添加序列化支持lambda表达式时,目标接口已经不继承Serializable,只是喜欢(TargetInterface&Serializable)()->{/*code*/}.

我问,是一种反其道而行之,明确删除支持串行当目标接口继承Serializable.

由于您无法从类型中删除接口,因此基于语言的解决方案可能看起来像(@NotSerializable TargetInterface)()->{/* code */}.但据我所知,没有这样的解决方案.(纠正我,如果我错了,这将是一个完美的答案)

即使在类实现时拒绝序列化是Serializable过去的合法行为,并且程序员控制下的类,模式看起来如下:

public class NotSupportingSerialization extends SerializableBaseClass {
    private void writeObject(java.io.ObjectOutputStream out) throws IOException {
      throw new NotSerializableException();
    }
    private void readObject(java.io.ObjectInputStream in)
      throws IOException, ClassNotFoundException {
      throw new NotSerializableException();
    }
    private void readObjectNoData() throws ObjectStreamException {
      throw new NotSerializableException();
    }
}
Run Code Online (Sandbox Code Playgroud)

但是对于lambda表达式,程序员没有对lambda类的控制.


为什么有人会费心去除支持?好吧,除了生成包含Serialization支持的更大代码之外,它还会产生安全风险.请考虑以下代码:

public class CreationSite {
    public static void main(String... arg) {
        TargetInterface f=CreationSite::privateMethod;
    } …
Run Code Online (Sandbox Code Playgroud)

java lambda serialization java-8

35
推荐指数
1
解决办法
2423
查看次数

java.lang.ClassCastException使用远程服务器上的spark作业中的lambda表达式

我正在尝试使用sparkjava.com框架为我的apache spark作业构建一个web api.我的代码是:

@Override
public void init() {
    get("/hello",
            (req, res) -> {
                String sourcePath = "hdfs://spark:54310/input/*";

                SparkConf conf = new SparkConf().setAppName("LineCount");
                conf.setJars(new String[] { "/home/sam/resin-4.0.42/webapps/test.war" });
                File configFile = new File("config.properties");

                String sparkURI = "spark://hamrah:7077";

                conf.setMaster(sparkURI);
                conf.set("spark.driver.allowMultipleContexts", "true");
                JavaSparkContext sc = new JavaSparkContext(conf);

                @SuppressWarnings("resource")
                JavaRDD<String> log = sc.textFile(sourcePath);

                JavaRDD<String> lines = log.filter(x -> {
                    return true;
                });

                return lines.count();
            });
}
Run Code Online (Sandbox Code Playgroud)

如果我删除lambda表达式或将其放在一个简单的jar而不是web服务(不知何故是一个servlet)中,它将运行而没有任何错误.但是在servlet中使用lambda表达式将导致此异常:

15/01/28 10:36:33 WARN TaskSetManager: Lost task 0.0 in stage 0.0 (TID 0, hamrah): java.lang.ClassCastException: cannot assign instance …
Run Code Online (Sandbox Code Playgroud)

java lambda java-8 spark-java

22
推荐指数
2
解决办法
1万
查看次数

确保Function参数可序列化的最佳方法是什么?

我正在编写一个可序列化的类,它带有几个参数,包括Function:

public class Cls implements Serializable {
    private final Collection<String> _coll;
    private final Function<String, ?> _func;

    public Cls(Collection<String> coll, Function<String, ?> func) {
        _coll = coll;
        _func = func;        
    }
}
Run Code Online (Sandbox Code Playgroud)

func存储在成员变量中,因此需要可序列化.如果它们被分配的类型是可序列化的,则 Java lambdas 是可序列化的.Function如果使用lambda创建,那么确保我在构造函数中传递的最佳方法是可序列化的?

  1. 创建一个SerializableFunction类型并使用它:

    public interface SerializableFunction<F, R> implements Function<F, R>, Serializable {}
    ....
    public Cls(Collection<String> coll, SerializableFunction<String, ?> func) {...}
    
    Run Code Online (Sandbox Code Playgroud)

    问题:

    • 现在,collfunc参数之间存在不匹配,在func签名中声明为可序列化,但coll不是,但两者都需要可序列化才能工作.
    • 它不允许其他实现Function可序列化.
  2. 在构造函数上使用类型参数:

    public <F extends Function<String, …
    Run Code Online (Sandbox Code Playgroud)

java lambda serializable java-8

13
推荐指数
1
解决办法
1145
查看次数

序列化的lambda和没有serialVersionUID?

我正在尝试学习序列化如何与Java及其最新版本一起使用.我正在尝试序列化这样的lambda:

Runnable r = (Runnable & Serializable)() -> {System.out.println("This is a test");};
Run Code Online (Sandbox Code Playgroud)

但我注意到我没有关于缺少serialVersionUID变量的警告.这是正常的吗?

我知道它将在运行时生成,但强烈建议您定义它:https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html

如果可序列化类未显式声明serialVersionUID,则序列化运行时将基于类的各个方面计算该类的默认serialVersionUID值,如Java(TM)对象序列化规范中所述.但是,强烈建议所有可序列化类显式声明serialVersionUID值,因为默认的serialVersionUID计算对类细节高度敏感,这些细节可能因编译器实现而异,因此在反序列化期间可能导致意外的InvalidClassExceptions.因此,为了保证跨不同java编译器实现的一致的serialVersionUID值,可序列化类必须声明显式的serialVersionUID值.强烈建议显式serialVersionUID声明尽可能使用private修饰符,因为此类声明仅适用于立即声明的类 - serialVersionUID字段作为继承成员无用.数组类不能声明显式的serialVersionUID,因此它们始终具有默认的计算值,但是对于数组类,不需要匹配serialVersionUID值.

我该怎么办 ?如何在Lambda中定义它?

谢谢

java lambda serialization serialversionuid java-8

6
推荐指数
1
解决办法
764
查看次数

lambda的序列化

我正在搞乱lambdas的Java序列化.

我有两个完全独立的项目,其中包含一个类.

项目1:

class TestMain {

    public static void main(String[] args) {
        Runnable r = (Runnable & Serializable) () -> {};

        // Serialize r to C:/file.ser;
    }
}
Run Code Online (Sandbox Code Playgroud)

项目2:

class TestMain2 {

    public static void main(String[] args) {
        // Deserialize C:/file.ser to runnable;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,在尝试反序列化runnable时,它会抛出一个异常,说它无法找到 TestMain

......有什么办法可以避免这种情况吗?

java lambda serialization java-8

3
推荐指数
1
解决办法
1109
查看次数

使用 Infinispan Cache 和 computeIfAbsent 进行无效的 lambda 反序列化

我正在一个基本的 infinispan 集群,但遇到了一个令人费解的错误。

我基本上是在实现一个共享地图,只持有一个整数

这是我的服务代码

package sandbox.infinispan.test.service;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;

import org.infinispan.Cache;

@Named("useThisOne")
@ApplicationScoped
public class CounterService implements ICounterService {

    private static final String KEY = "key";

    @Inject
    private Cache<String, Integer> cache;

    @Override
    public void inc(final int amount) {
        this.cache.put(KEY, Integer.valueOf(this.get() + amount));
    }

    @Override
    public int get() {
        return this.cache.computeIfAbsent(KEY, k -> Integer.valueOf(0)).intValue();
    }
}
Run Code Online (Sandbox Code Playgroud)

缓存由以下内容生成:

package sandbox.infinispan.test.config;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Produces;

import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import …
Run Code Online (Sandbox Code Playgroud)

jgroups infinispan wildfly

2
推荐指数
1
解决办法
442
查看次数

lambda用于接口实现时,“无效的lambda反序列化”

我有一个带有lambda表达式的检票口项目。在用户单击后退按钮的一页上,我的应用程序崩溃:

java.lang.IllegalArgumentException: Invalid lambda deserialization
at x.y.z.MyPage$3.$deserializeLambda$(MyPage.java:1)
Run Code Online (Sandbox Code Playgroud)

在页面类(我返回的地方)中,我使用lambda表达式实现此接口:

public interface Localizator extends Serializable {
    String getLocalizedString(String key);
}
Run Code Online (Sandbox Code Playgroud)

和lambda:

protected void someMethod() {
    localize((String key) -> getString(key));
}
Run Code Online (Sandbox Code Playgroud)

当我将lambda更改为匿名类时,一切正常。在这种情况下应如何使用lambda?

信封:Java 1.8.0_25,Netbeans 8.0.2,Wicket 6.17.0。

编辑:这是带有lambda的真实(但简化)方法:

@Override
protected DataLoader createDataLoader() {

    return new DataLoader(){

        @Override
        public List loadData() {
            ...
        }

        @Override
        public List convertToTableRows(List data) {
            return Converter.asRowList(
                data, 
                (Record record) -> {...}, // this lambda is OK
                (String key) -> getString(key)); // this lambda is crashing
        }

        @Override
        public List …
Run Code Online (Sandbox Code Playgroud)

lambda wicket java-8

1
推荐指数
1
解决办法
2815
查看次数