我最近花了几分钟调试生产代码中的问题,最终结果是由在其构造函数中调用抽象方法的类引起的,并且该方法的子类实现尝试使用尚未生成的子类字段已初始化(下面列出了一个说明这一点的例子)
在研究这个问题时,我偶然发现了这个问题,并对Jon Skeet的回答很感兴趣:
一般来说,在构造函数中调用非final方法是一个坏主意,正是因为这个原因 - 子类构造函数体还没有被执行,所以你有效地在一个尚未完全调用的环境中调用一个方法初始化.
这让我感到疑惑,是否有合理的理由从构造函数中调用非final或抽象方法?或者它几乎总是设计糟糕的迹象?
public class SSCCE {
static abstract class A {
public A() {
method(); // Not good; field arr in B will be null at this point!
}
abstract void method();
}
static class B extends A {
final String[] arr = new String[] { "foo", "bar" };
public B() {
super();
System.out.println("In B(): " + Arrays.toString(arr));
}
void method() {
System.out.println("In method(): " + Arrays.toString(arr));
}
}
public static void …Run Code Online (Sandbox Code Playgroud) 当装载系统类,该<clinit>方法实例化in,out以及err PrintStream变量null使用nullPrintStream()方法:
private static PrintStream nullPrintStream() throws NullPointerException {
if (currentTimeMillis() > 0) {
return null;
}
throw new NullPointerException();
}
Run Code Online (Sandbox Code Playgroud)
我明白为什么会这样,以及为什么变量在加载过程中无法实例化,但我感到困惑的是该方法的内容.
为什么比较currentTimeMillis()来0?在什么情况下,这种比较会回归false?
我正在尝试放置一个JList内部JScrollPane并按字母顺序列出垂直列中的条目,如下所示:
A D G
B E H
C F
Run Code Online (Sandbox Code Playgroud)
但是当JList空间用完以显示更多条目时,我希望仅在垂直方向JScrollPane上滚动.
这在我使用时有效VERTICAL_WRAP.然而,似乎当我使用垂直包装时,我得到一个水平滚动条,当我使用时,HORIZONTAL_WRAP我得到我想要的滚动条,但是项目按照我不喜欢的顺序放置.我可以吃蛋糕吗?这是我正在尝试做的一个简单的例子.
这是我能得到的最接近的,但我希望能够在保持垂直字母顺序的同时垂直滚动.
public class ScrollListExample {
static List<String> stringList = new ArrayList<String>();
static {
for (int i = 0; i < 500; i++) {
stringList.add("test" + i);
}
}
public static void main(final String[] args) {
final JFrame frame = new JFrame();
final Container contentPane = frame.getContentPane();
final JList list = new JList(stringList.toArray());
list.setLayoutOrientation(JList.VERTICAL_WRAP);
list.setVisibleRowCount(0);
final …Run Code Online (Sandbox Code Playgroud) 我有一个JPanel(黄色)放入JScrollPane.

当我输入一些文本时JTextPane,它会调整大小,但垂直滚动条仍然不活动.yelowPanel.getSize()返回与之前相同的值.(您可以在redPanel上看到它).

那我怎么刷新yellowPanel?我想垂直滚动面板.我试过了:
panelCreating.revalidate();
panelCreating.invalidate();
panelCreating.repaint();
Run Code Online (Sandbox Code Playgroud)
仅适用,panelCreating.setPreferredSize(new Dimension(333, 777));但我不知道要设置的大小.这取决于内容.
有一个小例子:
package swingtest;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
public class SwingTest extends JFrame {
public SwingTest() {
initComponents();
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new SwingTest().setVisible(true);
}
});
} …Run Code Online (Sandbox Code Playgroud) 以下代码段(从实际代码中抽象出来)在Eclipse中编译和运行.
包1/Outer.java:
package package1;
import package1.Outer.Mid.Inner;
import package2.Bar;
public class Outer {
final Mid mid = new Mid();
public Outer() {
mid.setInner(new Inner() {
@Override public void foo() {
System.out.println("In Outer.foo()");
}
});
}
public static class Mid implements Bar {
private Inner inner;
public void setInner(Inner inner) {
this.inner = inner;
}
public Inner getInner() {
return this.inner;
}
@Override
public void bar() {}
interface Inner {
void foo();
}
}
}
Run Code Online (Sandbox Code Playgroud)
包2/Bar.java:
package package2;
public interface Bar { …Run Code Online (Sandbox Code Playgroud) 我已经在http://mergedoc.sourceforge.jp/ eclipse 3.7上下载了一个副本,但是这个IDE是日文的,我想把它改成英文,有人可以帮帮我吗?

换句话说:我-keep应该用什么命令告诉Proguard避免混淆代表本机库的类?(因为JNA要求名称与等效的本机函数,struct等匹配)
使用Java 8 Streams,是否可以以某种方式封装和重用中间流操作,而不会破坏流管道?
考虑来自Java Tutorial on streams的这个例子:
double average = roster
.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.mapToInt(Person::getAge)
.average()
.getAsDouble();
Run Code Online (Sandbox Code Playgroud)
假设我需要在整个代码中的不同位置使用filter和mapToInt操作.我可能想尝试并封装该逻辑,以便可以重复使用,例如:
IntStream maleAges(Stream<Person> stream) {
return stream
.filter(p -> p.getGender() == Person.Sex.MALE)
.mapToInt(Person::getAge)
}
Run Code Online (Sandbox Code Playgroud)
这很好,但要使用它我可能不得不弄乱流管道.例如,如果我想要名叫Bob的男性的平均年龄:
double averageBob =
maleAges(roster
.stream()
.filter(p -> "Bob".equals(p.getName()))
)
.average()
.getAsDouble();
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法呢?我正在考虑这些方面的事情:
double averageBob = roster
.stream()
.filter(p -> "Bob".equals(p.getName()))
.apply(this::maleAges) // Doesn't compile
.average()
.getAsDouble();
Run Code Online (Sandbox Code Playgroud) Android是否会从深度睡眠中唤醒以进行广播ACTION_TIME_TICK?从实验来看,我认为不是,但我正在寻找一个明确的答案.
我的实验涉及注册一个简单BroadcastReceiver的更新TextView接收:
registerReceiver(new BroadcastReceiver() {
int ctr = 0;
@Override
public void onReceive(Context context, Intent intent) {
testView.setText("Time ticks: " + ++ctr);
}
}, new IntentFilter(Intent.ACTION_TIME_TICK));
Run Code Online (Sandbox Code Playgroud)
在4个刻度处,我关闭了屏幕大约5分钟,然后将其重新打开,它读取了6个刻度.在13个刻度时,我将屏幕旋转了10分钟,然后将其重新打开,并且刻度数读数为14.无论我多长时间离开手机,这似乎只会增加1-2个刻度,这就是为什么我怀疑它不会在深度睡眠期间播放动作.
基本设置是这样的:我有一个垂直的JSplitPane,我希望有一个固定大小的底部组件和一个调整大小的顶部组件,我通过调用完成setResizeWeight(1.0).在此应用程序中,有一个用于恢复"默认"窗口配置的按钮.窗口的默认高度是桌面高度,默认分隔符位置距离拆分窗格底部100个像素.
要将分隔符位置设置为100px,我将采用JSplitPane高度 - 100.问题是,在此之前我调整了JFrame的大小,并且由于代码处于按钮回调中,因此JSplitPane已失效但尚未调整大小.因此分配器位置设置不正确.
这是一个SSCCE.单击按钮两次以查看问题.第一次单击将调整窗口大小,但分隔符位置保持不变(相对于窗口底部).第二次单击正确移动分隔符,因为窗口大小没有改变.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSplitPane;
public class SSCCE {
/**
* @param args unused
*/
public static void main(String[] args) {
new SSCCE();
}
private final JFrame f = new JFrame("JSplitPane SSCE");
private final JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT,true);
public SSCCE() {
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
sp.add(new JLabel("top"));
sp.add(new JLabel("bottom"));
sp.setResizeWeight(1.0);
f.getContentPane().add(sp);
f.getContentPane().add(new JButton(new AbstractAction("Resize to Default") …Run Code Online (Sandbox Code Playgroud) java ×8
swing ×3
jscrollpane ×2
android ×1
eclipse ×1
inheritance ×1
java-8 ×1
java-api ×1
java-stream ×1
javac ×1
jlist ×1
jna ×1
jsplitpane ×1
jvm ×1
proguard ×1