在Java中,可以创建包私有接口.用javap看着它们,你会发现它们缺乏"公共"可见性.
在Scala中,您可以将特征声明为私有[package]或protected [package],但是在使用javap时,它仍然是公共的.
那么如何在Scala中创建一个包私有特征呢?
虽然Scala编译器尊重可见性,但我的问题是我的API也可能从Java访问,我不想将我的内部实现暴露给Java.
我正在尝试在ProtoBuf中设计我的第一个文件格式,我不确定在某些情况下什么是最佳选择,因为内存/流布局对我来说并不完全清楚.
所以我实际上有几个问题,但都密切相关:
1)省略时,可选字段的成本是多少?
我认为它应该只花了一个位,因为位字段可以用来标记存在/不存在的字段,但我不知道.相反,它们可能会为每个可选字段使用整个字节.
2)当空的时候重复的字段成本是多少?是不是还一个位,如可选字段,或者是"场头" +一(varint)字节说,这是大小为0?
3)由于"字节"隐含的大小,是否有实际上是一个缺少的可选字节字段之间的尺寸差,和一个空所需要的字节字段?
[编辑]"存储器"是指文件系统或网络带宽上使用的空间; 我不是指RAM,因为这将依赖于编程语言.
我有一个Maven项目,我在Eclipse中编程.在Eclipse中,一切正常,但是当使用Maven构建它时,我在调用第三方jar时得到NoSuchMethodError.所以我怀疑Eclipse在编译时会使用不同版本的jar.我可以看到Maven使用的版本,但我想看看Eclipse使用的版本.我没有看到如何在Eclipse中执行"mvn dependency:tree",这样我就会看到结果形式为"Eclipse的观点".
该项目是使用"文件/导入... /现有Maven项目"创建的.
我正在使用"Eclipse IDE for Java Developers",版本:"Kepler Service Release 1"
要从Eclipse 执行任何 Maven命令,我刚刚发现了这个问题
如果我有以下Scala类:
abstract class MyOrdered extends Ordered[MyOrdered] {
def id: Int
def compare(that : MyOrdered) : Int =
if (that==null) 1 else (id-that.id)
}
Run Code Online (Sandbox Code Playgroud)
然后我只需要在Scala中定义id方法来获得具体的类.但是如果我尝试用Java扩展它,编译器会说Ordered的所有具体方法都缺失了.那么,这是否意味着Scala编译器只在具体的Scala类中实现了Ordered的具体方法?
这看起来非常浪费,因为我可以有几十个实现MyOrdered的具体类,并且它们都会得到相同代码的副本,实际上将它直接放在基类MyOrdered中就足够了.此外,这使得创建Java友好的Scala API变得非常困难.有没有办法强制Scala编译器将方法定义放在应该这样做的地方,除了通过使用虚方法实现使类具体化?
甚至更有趣的是在Scala特征中声明一个具体的方法final.在这种情况下,它仍然没有在扩展特征的抽象Scala类中实现,但它不能在扩展抽象Scala类的Java类中实现,因为它被标记为final.这绝对是一个编译器错误.最终的抽象方法毫无意义,即使它们在JVM中是合法的,显然也是如此.
如果我希望我的Scala项目与Java"兼容",那就是从Java代码调用Scala API(这样非Scala程序员也可以贡献)是否可行,是否可以在Java中使用Project Lombok码?或者他们俩相处得不好?
我将使用Scala IDE在Eclipse中进行开发.
编辑:我真正的意思是:Eclipse中的Scala 编辑器会看到Lombok生成的代码,还是我真正输入的Java代码?
如果你使用Java的原始数字类型,加上布尔值,并将它与C++等效类型进行比较,那么运算符有什么区别,例如优先级规则或位操作运算符的作用是什么?还是括号的影响?
问另一种方法,如果我使用Java表达式并尝试在C++中编译并运行它,它是否总是编译并始终给出相同的结果?
如果我运行"scalac -explaintypes"并看到类似的内容:
Nothing <: ThingManager?
<notype> <: ThingManager?
false
true
Run Code Online (Sandbox Code Playgroud)
行"<notype> <:ThingManager?"是什么?意思?
这是否意味着"没有类型可能符合ThingManager"?
我刚刚完成了Java 6编译器插件的第一个版本,它基于注释自动生成包装器(代理,适配器,委托,根据需要调用它).
由于我正在进行混合Java/Scala项目,我希望能够在我的Scala代码中使用相同的注释,并获得相同的生成代码(当然除了Scala).这基本上意味着从头开始.
我想做的,我还没有找到一个例子,我是如何以与Java编译器插件相同的方式在Scala编译器插件中生成代码.也就是说,我匹配/查找我的注释使用的位置,获取带注释的接口的AST,然后让API给我一个Stream/Writer,在其中我使用String操作输出生成的Scala源代码.
最后一部分是我找不到的.那么我如何告诉API创建一个新的Scala源文件,并给我一个Stream/Writer/File/Handle,所以我可以写进去,当我完成后,Scala编译器会编译它,在同一个插件被调用的运行?
我为什么要那样做?首先,因为两个插件都具有相同的结构,所以维护很容易.其次,我想开源它,并且没有办法支持任何人想要的每个选项,所以我希望潜在用户想要用他们自己的代码扩展生成.如果他们只需要做一些printf(),而不是学习AST API(这也适用于我),这对他们来说会容易得多.
为了在Scala编译器插件中生成新代码,我现在已经创建了工作类.下一个合乎逻辑的步骤是将这些类放在一个新的,不存在的包中.在Java中,包基本上是一个目录名,但在Scala中,包看起来要复杂得多.到目前为止,我还没有找到/识别编译器插件创建新包的示例.
根据我目前的理解水平,我认为我需要首先创建一个包符号:
parentPackage.newPackage(...)
// ...
Run Code Online (Sandbox Code Playgroud)
然后使用PackageDef为包创建一个Tree.但是PackageDef没有将符号作为参数,正如人们所期望的那样,并且搜索:
Scala newPackage PackageDef
Run Code Online (Sandbox Code Playgroud)
没有任何用处.所以我似乎不需要一起做这两个步骤.可能一个是由编译器为我完成的,但我不知道哪一个.到目前为止,我看起来像这样:
val newPkg = parentPackage.newPackage(NoPosition, newTermName(name))
newPkg.moduleClass.setInfo(new PackageClassInfoType(new Scope,
newPkg.moduleClass))
newPkg.setInfo(newPkg.moduleClass.tpe)
parentPackage.info.decls.enter(newPkg)
// ...
val newPkgTree = PackageDef(Ident(newPkg.name), List(ClassDef(...)))
Run Code Online (Sandbox Code Playgroud) 这有点奇怪,但代码说的多于单词,所以看看测试看看我在做什么.在我当前的设置(Windows 64位上的Java 7更新21)中,此测试因ArrayIndexOutOfBoundsException而失败,但是将测试方法代码替换为注释代码,它可以正常工作.我想知道Java规范中是否有任何部分可以解释原因.
在我看来,正如"michael nesterenko"建议的那样,在调用方法之前,数组字段的值被缓存在堆栈中,并且在从调用返回时不会更新.我不知道它是JVM错误还是记录在案的"优化".没有涉及多线程或"魔术".
public class TestAIOOB {
private String[] array = new String[0];
private int grow(final String txt) {
final int index = array.length;
array = Arrays.copyOf(array, index + 1);
array[index] = txt;
return index;
}
@Test
public void testGrow() {
//final int index = grow("test");
//System.out.println(array[index]);
System.out.println(array[grow("test")]);
}
}
Run Code Online (Sandbox Code Playgroud)