我已经阅读了Apple的Swift文档,并且没有找到关于如何创建模块或如何将类或结构成员定义为私有或公共的任何内容.
语法中有对import语句的引用,但我找不到有关它的用途或如何使用它的信息.
有谁知道我在哪里可以找到这个?
record
JDK 14 中引入的预览功能 (JEP 384) 是一项伟大的创新。它们使创建简单的不可变类变得更加容易,这些类是纯粹的值集合,而不会丢失各种库中通用元组类中固有的上下文。
由 Brian Goetz ( https://openjdk.java.net/jeps/384 )编写的 JEP 描述很好地解释了意图。然而,我期待与最终引入的值类型有更密切的联系。值类型的最初目标是相当广泛的:通过消除这些类型的对象不需要的所有开销(例如引用间接、同步),本质上允许对那些值最重要的对象进行潜在的显着性能改进。此外,它还可以提供句法细节,例如myPosition != yourPosition
代替!myPosition.equals(yourPosition)
.
似乎记录的限制与潜在值类型所需的限制类型非常接近。然而,JEP 在动机中没有提及这些目标。我试图找到有关这些审议的任何公开记录,但没有成功。
所以我的问题是:记录是否旨在成为可能向值类型转变的一部分,还是这些完全不相关的概念和未来的值类型可能看起来完全不同?
我提出这个问题的动机是:如果记录成为语言的永久部分,那么如果在未来的版本中可能会带来显着的性能优势,那么在代码中采用它们将是一个额外的动力。
下面的代码分别调用两个简单的函数100亿次.
public class PerfTest {
private static long l = 0;
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b");
long time1 = System.currentTimeMillis();
for (long i = 0; i < 1E10; i++) {
func1("a", "b");
}
long time2 = System.currentTimeMillis();
for (long i = 0; i < 1E10; i++) {
func2(list);
}
System.out.println((time2 - time1) + "/" + (System.currentTimeMillis() - time2));
}
private static void func1(String s1, String s2) { l++; }
private static void func2(List<String> sl) …
Run Code Online (Sandbox Code Playgroud) 我经常在我的代码中使用访问者模式.当类层次结构实现了访问者时,我将其用作替代instanceof
和转换.然而,它导致一些非常尴尬的代码,我想改进.
考虑一下人为的案例:
interface Animal {
void accept(AnimalVisitor visitor);
}
class Dog implements Animal {
void accept(AnimalVisitor visitor) {
visitor.visit(this);
}
}
class Cat implements Animal {
void accept(AnimalVisitor visitor) {
visitor.visit(this);
}
}
interface AnimalVisitor {
default void visit(Cat cat) {};
default void visit(Dog dog) {};
}
Run Code Online (Sandbox Code Playgroud)
在大多数情况下,只做一些特定于狗的事情(例如)我实现了一个在其visit
方法中实现逻辑的访问者- 就像模式一样.
但是,有一种情况,我希望从访客那里返回一只可选的狗以便在外面使用.
在这些情况下,我最终得到了一些非常丑陋的代码:
List<Dog> dogs = new ArrayList<>();
animal.accept(new AnimalVisitor() {
void visit(Dog dog) {
dogs.add(dog);
}
}
Optional<Dog> possibleDog = dogs.stream().findAny();
Run Code Online (Sandbox Code Playgroud)
我不能possibleDog
直接在访问者内部分配,因为它不是最终变量,因此列表.
这是非常丑陋和低效的,只是为了满足有效终结的要求.我对替代品的想法感兴趣.
我考虑的替代方案:
将访问者转变为可以给予返回值的泛型 …
我想有一个有限的固定目录的某个复杂接口的实例.标准的multiton模式有一些很好的功能,比如延迟实例化.但是它依赖于一个像String这样的键,它看起来很容易出错并且很脆弱.
我想要一个使用枚举的模式.它们有很多很棒的功能,非常强大.我试图找到一个标准的设计模式,但已经画了一个空白.所以我想出了自己的,但我对它并不十分满意.
我正在使用的模式如下(这里的界面高度简化,使其可读):
interface Complex {
void method();
}
enum ComplexItem implements Complex {
ITEM1 {
protected Complex makeInstance() { return new Complex() { ... }
},
ITEM2 {
protected Complex makeInstance() { return new Complex() { ... }
};
private Complex instance = null;
private Complex getInstance() {
if (instance == null) {
instance = makeInstance();
}
return instance;
}
protected void makeInstance() {
}
void method {
getInstance().method();
}
}
Run Code Online (Sandbox Code Playgroud)
这种模式有一些非常好的功能:
说过这样一个简单的要求似乎非常复杂和"hacky",并以一种我不确定语言设计者的意图的方式覆盖枚举方法.
它还有另一个显着的缺点.在我的用例中,我希望扩展Comparable的界面.不幸的是,这与Comparable的枚举实现冲突并使代码无法编译.
我考虑过的一个替代方案是使用标准枚举,然后是一个单独的类,它将枚举映射到接口的实现(使用标准多重模式).这是有效的,但是枚举不再实现界面,在我看来这不是对意图的自然反映.它还将接口的实现与枚举项分开,这似乎是不良的封装. …
我喜欢 Java 8流.它们直观,强大而优雅.但它们确实有一个主要的缺点IMO:它们使调试更加困难(除非你可以通过调试lambda表达式来解决你的问题,这在这里得到解答).
考虑以下两个等效片段:
int smallElementBitCount = intList.stream()
.filter(n -> n < 50)
.mapToInt(Integer::bitCount)
.sum();
Run Code Online (Sandbox Code Playgroud)
和
int smallElementBitCount = 0;
for (int n: intList) {
if (n < 50) {
smallElementBitCount += Integer.bitCount(n);
}
}
Run Code Online (Sandbox Code Playgroud)
我发现第一个更清晰,更简洁.但是请考虑结果不符合您预期的情况.你是做什么?
在传统的迭代样式中,您totalBitCount += Integer.bitCount(n);
在行上放置一个断点并逐步浏览列表中的每个值.您可以看到当前列表元素是什么(监视n),当前总计(监视totalBitCount),以及根据调试器,Integer.bitCount的返回值是什么.
在新的流式中,所有这一切都是不可能的.您可以在整个语句中放置断点并逐步执行该sum
方法.但总的来说这是无用的.在我测试的这种情况下,我的调用堆栈是11深,其中10个是我不感兴趣的java.util方法.不可能单步执行代码测试谓词或执行映射.
在调试流问题的答案中注意到,迭代调试器可以很好地破坏内部lambda表达式(例如n < 50
谓词).但在许多情况下,最合适的断点不在lambda中.
显然,这是一段简单的调试代码.但是,一旦添加了自定义缩减和集合,或者更复杂的过滤器和映射链,它就会成为调试的噩梦.
我在NetBeans和Eclipse上试过这个,但两者似乎都有同样的问题.
在过去的几个月里,我习惯于使用.peek调用来记录临时值或将临时步骤移动到他们自己的命名方法中,或者在极端情况下,重构为迭代,直到任何错误被整理出来.这可以工作,但它让我想起了在使用集成交互式调试器的现代IDE之前的许多糟糕的旧时代,当你不得不通过代码分散printf语句时.
当然有更好的方法.
具体来说,我想知道:
您发现成功的任何技术都将非常感激.
在Java 8中,我越来越多地用Collection
返回值替换Stream
.
那么我曾经拥有过的地方:
public List<Element> getElementList() {
return elements;
}
Run Code Online (Sandbox Code Playgroud)
我现在正在使用:
public Stream<Element> streamElements() {
return elements.stream();
}
Run Code Online (Sandbox Code Playgroud)
我的论点是:
事实上,现在,在我的代码中,返回一个List
或一些其他集合明确地认识到用户可能认为该集合是可变的并且期望能够改变它.
显然,使用不可变集合可以实现其中一些.
我的问题是:任何人都可以看到这种设计的任何缺点吗?返回一个不可变集合有什么优势Stream
吗?
说我有一个简单的interface
,我希望Comparable
基于一些功能:
interface Organism extends Comparable<Organism> {
String getName();
int getComplexity();
@Override
default int compareTo(Organism other) {
return this.getComplexity() - other.getComplexity();
}
}
Run Code Online (Sandbox Code Playgroud)
每个实现类必须返回唯一的复杂性,因此类的任何两个实例将具有相同的复杂性,并且不同类的任何两个实例将具有不同的复杂性.自然排序将所有类的实例"组合"在一起.
我现在想要在一个类中实现此接口,该类重写默认比较,专门用于比较该类的实例组中该类的两个实例.我使用以下模式:
class Bacteria implements Organism {
enum Shape {ROD, ROUND, SPIRAL};
private final Shape shape;
@Override
public int compareTo(Organism other) {
if (other instanceof Bacteria)
return this.shape.compareTo((Bacteria)other.shape);
else
return Organism.super.compareTo(other);
}
}
Run Code Online (Sandbox Code Playgroud)
我对这种代码模式并不是特别满意:一旦实现接口的类集变得很大,维护变得非常复杂并且需要大量重复的代码并依赖于"复杂性"的隐含属性.我更喜欢Comparator
定义订单的风格.我想是能够实现Comparable
在Bacteria
使用的东西,看起来像:
return Comparator
.comparingInt(Organism::getComplexity)
.thenComparing(Bacteria::getShape);
Run Code Online (Sandbox Code Playgroud)
为了清楚起见,我意识到比较器不能像这样工作:它们被设计成在一个集合中使用一个比较器,而不是根据每个对象使用不同的比较器.我在这里提到它们并不是因为它们是一种潜在的解决方案,而是因为比较器的链式风格优雅而透明.我感兴趣的是,是否有一种类似的优雅方式来定义,compareTo
以允许集合中的不同排序取决于类.
正如这里指出的,lambdas提供了一种非常优雅的方式来指定单个枚举值的行为.
在Java 8之前,我通常将其实现为:
enum Operator {
TIMES {
public int operate(int n1, int n2) {
return n1 * n2;
}
},
PLUS {
public int operate(int n1, int n2) {
return n1 + n2;
}
};
public int operate(int n1, int n2) {
throw new AssertionError();
}
}
Run Code Online (Sandbox Code Playgroud)
现在我倾向于使用:
enum Operator {
TIMES((n1, n2) -> n1 * n2),
PLUS((n1, n2) -> n1 + n2);
private final BinaryOperator<Integer> operation;
private Operator(BinaryOperator<Integer> operation) {
this.operation = operation;
}
public int …
Run Code Online (Sandbox Code Playgroud) 我有以下几点:
class Foo implements Inter {
void doSomething();
}
Optional<Inter> getPossible() {
Optional<Foo> possible = ...;
possible.ifPresent(Foo::doSomething);
return possible.map(f -> f);
}
Run Code Online (Sandbox Code Playgroud)
getPossible
需要返回 anOptional<Inter>
因为它覆盖了超类的实现。
方法末尾的映射纯粹是为了转换类型。有没有更优雅的选择?
java ×9
java-8 ×4
enums ×2
java-stream ×2
comparison ×1
debugging ×1
java-14 ×1
java-record ×1
module ×1
optional ×1
performance ×1
swift ×1