这是关于编写java类以及它们如何实例化的一般性问题。
public class transaction
{
int amount;
char ref;
}
如果一个类是这样写的那么它可以像结构一样使用。然后,当数据作为数据报中的byte []通过网络传输时,它将转换为事务对象。一个地方是在一个单独的类中,比如说:
public class doStuff
{
static transaction t; // the int and the char are alloc'd onto the DataSegment
public static transaction fromByte(byte[] buf)
{
t = new transaction(); // make sure t is null to begin with (on the heap)
t.ref = ''; // initialise char (to avoid null bytes)
t.amount = ByteBuffer.wrap(buf).getInt();
t.ref = ByteBuffer.wrap(buf).getChar();
return t;
}
}
然后另一个类调用doStuff,如下所示:
import doStuff;
class otherClass extends Thread
{
static transaction x = new transaction();
... in the run method
x = doStuff.fromByte(buf);
...
}
但是现在我想把类数据和方法放在一个地方(据说应该是这样?)所以不要在doStuff类中使用fromByte(byte [] buf)方法,而是将它移到事务类中。所以事务类现在看起来像这样:
public class transaction
{
int amount;
char ref;
static transaction t;
public static transaction fromByte(byte[] buf)
{
t = new transaction(); // make sure t is null to begin with
t.ref = ''; // initialise char (to avoid null bytes)
t.amount = ByteBuffer.wrap(buf).getInt();
t.ref = ByteBuffer.wrap(buf).getChar();
return t;
}
}
然后在otherClass中我使用:
import transaction;
class otherClass extends Thread
{
static transaction x = new transaction();
... in the run method
x = fromByte(buf);
...
}
表面上它都具有与以前相同的效果。
我的问题是:在事务数据(amount和ref)上添加了操作fromByte(byte[] buf)
到transaction
类后,实例化transaction
对象的开销发生了变化。如果每秒有数百个来自网络的事务,那么将fromByte(byte[] buf)
方法添加到transaction
类意味着当它在doStuff
类中实例化时,将使用比之前。换句话说,每次int
类生成char
时,不是简单地生成doStuff
和foo
(作为数据段上的静态变量),而是在堆(我认为,而不是数据段),并且fromByte(buf)
方法被推送到堆栈然后transaction
类再次在数据段上递归调用自身(静态变量)...
答案 0 :(得分:1)
这将从buf开始两次读取。
t.amount = ByteBuffer.wrap(buf).getInt();
t.ref = ByteBuffer.wrap(buf).getChar();
我怀疑你的意思
ByteBuffer bb = ByteBuffer.wrap(buf);
t.amount = bb.getInt();
t.ref = bb.getChar();
将事务数据(amount和ref)上的操作fromByte(byte [] buf)添加到事务类中,然后实例化事务对象的开销发生了变化。
每次创建byte[]
和ByteBuffer
也是一种开销。
换句话说,每次doStuff类生成foo时,不是简单地生成int和char(作为数据段上的静态变量),而是在堆上生成(我认为,而不是数据段)将fromByte(buf)方法推送到堆栈然后事务类再次在数据段上递归调用自身(静态变量)......
如上所述,创建transaction
obejct可能只是您开销的一小部分。例如。从Socket读取最多只需要100倍。
好吧,看起来有点混乱。有没有更好的方法将数据和方法放在同一个类中并保持最大速度?
不要使用byte[]
,每次都不要创建新的ByteBuffer
,也不要每次都创建新的transaction
对象。您可以提前创建这些对象,也可以不创建它们。然后重复使用它们。
例如,考虑在建立连接(或回收一个连接)时创建一个 direct ByteBuffer并解码消息并调用一个监听器
interface TransactionListener {
public void onTransaction(int num, char status);
}
这样就不会在堆栈上创建任何对象。
在这种情况下,您的性能瓶颈将是从Socket读取,具体取决于您对此信息的处理方式。 ;)
答案 1 :(得分:1)
就性能而言,两种方法之间的唯一区别是调用静态方法的成本。这是一个非常微不足道的成本,并且由JIT编译器进一步降低。
就封装而言,问题在于您是否希望将transaction
类的知识放在doStuff
类中,或者是否要将字节流结构的知识放入{{1} } .class。无论如何都有争论。