Java语言编写一个结构体的大小的判断程序,怎么采用 Java 语言的技术,实现对于结构体大小的准确的判断呢
Java哪来的结构体??Java有类,成员变量还有方法,,,,emm,没有结构体
今天下午跟着视频做了一下利用eclipse创建一个简单的双向循环链表,并在在类中写一些基础的方法,实现对链表的增加、插入、删除、输出等操作。这一次只是实现了几个最基础的方法,还有其他的一些方法并没有写出来,如果有错误的欢迎大佬指出~
public class Node {
Node previous;// 上一个节点
Node next;// 下一个节点
Object elem;// 元素数据
public Node(Node previous, Node next, Object elem) {
super();
this.previous = previous;
this.next = next;
this.elem = elem;
}
public Node(Object elem) {
super();
this.elem = elem;
}
}
public void add(E obj){
Node node = new Node(obj);//创建新的节点
if(first==null){//如果此时链表为空
first = node;
last = node;
}else{//链表不为空
node.previous = last;
node.next = first;
last.next = node;
last = node;
first.previous = last;//首尾相连保证循环
}
size++;
}
public Node getNode(int index){
if(index<0||index>size-1)
throw new RuntimeException("错误索引:"+index+",索引值不得小于0或大于链表长度!");
Node temp = first;
if(index>(size>>1)){//如果输入的索引值大于长度的一半,则从后往前遍历
for(int i=size-1;i>=index;i--){
temp = temp.previous;
}
}else{//否则从前往后遍历
for(int i=0;i<index;i++){
temp = temp.next;
}
}
return temp;
}
②通过调用方法来获取节点对应的值
public E get(int index){
Node temp = getNode(index);
return (E)temp.elem;
}
4.在指定的位置插入一个新的元素
public void insert(int index, E e) {
Node insertNode = new Node(e);
Node temp = getNode(index);
if (temp == first) {//待插入的位置是链表的第一个节点
first = insertNode;
first.next = temp;
first.previous = last;
size++;//长度加一
}else if(temp == last){//待插入的节点是链表的最后一个节点
add(e);//此时操作与直接加入元素时一样,直接调用
}else{//待插入的位置不在端点
Node preNode = temp.previous;//创建新的节点代表temp的前驱节点
preNode.next = insertNode;
insertNode.previous = preNode;
temp.previous = insertNode;
insertNode.next = temp;
size++;
}
}
//根据指定索引删除节点
public void remove(int index) {
Node temp = getNode(index);
if (temp == last) {//如果删除的节点是链表的最后一个节点
last = temp.previous;//将last标志前移一个位置
last.next = first;//将last的后继指向第一个节点,连成循环
first.previous = last;//将first的前驱指向最后一个节点
temp.previous = temp.next = null;//置空删除
}
else if(temp == first) {//如果删除的节点是链表的第一个节点
first = temp.next;//将first标志后移一个位置
last.next = first;//将last的后继指向第一个节点,连成循环
first.previous = last;//将first的前驱指向最后一个节点
temp.previous = temp.next = null;//置空删除
}
else {//如果删除的节点不在链表的两端
Node preNode = temp.previous;//创建新的节点代表待删除的前驱节点
Node nextNode = temp.next;//创建新的节点代表待删除的后继节点
preNode.next = nextNode;
nextNode.previous = preNode;
temp.previous = temp.next = null;//置空删除
}
size--;//长度-1
}
在删除节点时一般除了指定索引之外,还可以通过节点值来删除节点
public void remove(E e){
int i=0;
Node temp = first;
while(temp.elem!=e){//先找到该值在链表中第一次出现的位置
temp = temp.next;
i++;
}
remove(i);//调用remove(int index)
}
这个部分是先通过遍历来找到找待删除的节点的索引,然后再调用同名方法来删除
6. 重写toString方法
通过创建一个StringBuilder对象来存放链表的节点值
public String toString() {
StringBuilder sb = new StringBuilder("[");
Node temp = first;
for(int i=0;i<size;i++){
sb.append(temp.elem+",");
temp = temp.next;
}
sb.setCharAt(sb.length()-1, ']');
return sb.toString();
}
public class setLinkedList<E> {
private Node first;//首节点标志
private Node last;//尾节点标志
private int size;//长度
//获取节点
public E get(int index){
Node temp = getNode(index);
return (E)temp.elem;
}
//为了方便使用,将该部分封装成一个独立的方法,获取指定索引的节点信息
public Node getNode(int index){
if(index<0||index>size-1)
throw new RuntimeException("错误索引:"+index+",索引值不得小于0或大于链表长度!");
Node temp = first;
if(index>(size>>1)){//如果输入的索引值大于长度的一半,则从后往前遍历
for(int i=size-1;i>=index;i--){
temp = temp.previous;
}
}else{//否则从前往后遍历
for(int i=0;i<index;i++){
temp = temp.next;
}
}
return temp;
}
//尾插法添加元素
public void add(E obj){
Node node = new Node(obj);//创建新的节点
if(first==null){//如果此时链表为空
first = node;
last = node;
}else{//链表不为空
node.previous = last;
node.next = first;
last.next = node;
last = node;
first.previous = last;//首尾相连保证循环
}
size++;
}
// 指定位置插入节点
public void insert(int index, E e) {
Node insertNode = new Node(e);
Node temp = getNode(index);
if (temp == first) {//待插入的位置是链表的第一个节点
first = insertNode;
first.next = temp;
first.previous = last;
size++;//长度加一
}else if(temp == last){//待插入的节点是链表的最后一个节点
add(e);//此时操作与直接加入元素时一样,直接调用
}else{//待插入的位置不在端点
Node preNode = temp.previous;//创建新的节点代表temp的前驱节点
preNode.next = insertNode;
insertNode.previous = preNode;
temp.previous = insertNode;
insertNode.next = temp;
size++;
}
}
//根据指定索引删除节点
public void remove(int index) {
Node temp = getNode(index);
if (temp == last) {//如果删除的节点是链表的最后一个节点
last = temp.previous;//将last标志前移一个位置
last.next = first;//将last的后继指向第一个节点,连成循环
first.previous = last;//将first的前驱指向最后一个节点
temp.previous = temp.next = null;//置空删除
}
else if(temp == first) {//如果删除的节点是链表的第一个节点
first = temp.next;//将first标志后移一个位置
last.next = first;//将last的后继指向第一个节点,连成循环
first.previous = last;//将first的前驱指向最后一个节点
temp.previous = temp.next = null;//置空删除
}
else {//如果删除的节点不在链表的两端
Node preNode = temp.previous;//创建新的节点代表待删除的前驱节点
Node nextNode = temp.next;//创建新的节点代表待删除的后继节点
preNode.next = nextNode;
nextNode.previous = preNode;
temp.previous = temp.next = null;//置空删除
}
size--;//长度-1
}
//从链表中删除指定值
public void remove(E e){
int i=0;
Node temp = first;
while(temp.elem!=e){//先找到该值在链表中第一次出现的位置
temp = temp.next;
i++;
}
remove(i);//调用remove(int index)
}
@Override
//重写tostring方法
public String toString() {
StringBuilder sb = new StringBuilder("[");
Node temp = first;
for(int i=0;i<size;i++){
sb.append(temp.elem+",");
temp = temp.next;
}
sb.setCharAt(sb.length()-1, ']');
return sb.toString();
}
public static void main(String[] args) {
setLinkedList<String> list = new setLinkedList<>();
try {
list.add("a");
list.add("b");
System.out.println(list);
} catch (RuntimeException e) {
System.out.println(e);
}
}
}
输出结果为:
8.总结
在写这个双向链表的时候,由于是将首尾相连形成一个循环的链表,因此在写插入、删除等涉及索引的方法时,没有考虑到待操作的节点如果是首尾节点时的操作方式与不是首尾节点时的操作方式不同。所以调式的时候总是报错,最后才意识到这个问题。
这一次只是实现了一些小小的功能,还有很多没有实现。在已经实现了的方法中,如果有错误的,还麻烦各位大佬指正一下,谢谢啦!
Java是一种面向对象的编程语言,它没有提供类似C语言中的结构体的概念。在Java中,我们通常使用类来表示结构体的概念。在判断一个结构体的大小之前,我们首先需要确定该结构体的成员变量的类型和大小。
在Java中,基本数据类型的大小是固定的,如int类型的大小为4字节,double类型的大小为8字节等。对于类对象的大小,它取决于对象的成员变量和其他一些因素,如对象头(object header)、对齐等。由于Java的内存是自动管理的,我们无法直接获取一个对象的大小。
然而,我们可以通过Java的Instrumentation API来获取对象的大小。Instrumentation是一个Java代理(Java agent) API,它提供了在运行时检测Java程序状态和控制Java程序的能力。
下面是一个使用Instrumentation API来获取对象大小的示例:
import java.lang.instrument.Instrumentation;
public class ObjectSizeUtil {
private static Instrumentation instrumentation;
public static void premain(String args, Instrumentation inst) {
instrumentation = inst;
}
public static long getObjectSize(Object obj) {
if (instrumentation == null) {
throw new IllegalStateException("Instrumentation not initialized");
}
return instrumentation.getObjectSize(obj);
}
}
上述代码中的premain方法是一个特殊的方法名,用于定义一个Java代理,在程序启动时被调用。在这个方法中,我们将Instrumentation对象保存起来,以便后续使用。getObjectSize方法使用Instrumentation对象来获取指定对象的大小。
要使用这个工具类获取对象的大小,我们需要在应用程序启动时指定Java代理。可以通过在JVM启动参数中添加-javaagent:your-agent-jar.jar来指定Java代理。your-agent-jar.jar是包含ObjectSizeUtil类的jar文件。
下面是一个使用示例:
public class Main {
public static void main(String[] args) {
ObjectSizeUtil.getObjectSize(new Person("John", 25));
}
}
在上述示例中,我们创建了一个Person对象,并通过ObjectSizeUtil类获取它的大小。
请注意,由于Java的自动内存管理,对象的实际大小可能与预期不同。因此,获取对象大小只是一个近似值,并不精确。
希望这个解决方案能够帮助到您。如果您对这个问题有任何其他问题,请随时提问。