我知道 Java 没有指针,但我听说可以使用指针创建 Java 程序,并且这可以由少数 Java 专家来完成。这是真的吗?
15 回答
Java 中的所有对象都是引用,您可以像使用指针一样使用它们。
abstract class Animal
{...
}
class Lion extends Animal
{...
}
class Tiger extends Animal
{
public Tiger() {...}
public void growl(){...}
}
Tiger first = null;
Tiger second = new Tiger();
Tiger third;
取消引用空值:
first.growl(); // ERROR, first is null.
third.growl(); // ERROR, third has not been initialized.
别名问题:
third = new Tiger();
first = third;
丢失细胞:
second = third; // Possible ERROR. The old value of second is lost.
您可以通过首先确保不再需要 second 的旧值或将 second 的值分配给另一个指针来确保这一点。
first = second;
second = third; //OK
请注意,以其他方式(NULL、new...)给第二个值同样是一个潜在的错误,并可能导致丢失它指向的对象。
OutOfMemoryError
当您调用 new 并且分配器无法分配请求的单元格时,Java 系统将抛出异常 ( )。这是非常罕见的,通常是由失控递归引起的。
请注意,从语言的角度来看,将对象丢弃给垃圾收集器根本不是错误。这只是程序员需要注意的事情。同一个变量可以在不同的时间指向不同的对象,当没有指针引用它们时,旧值将被回收。但是如果程序的逻辑需要维护至少一个对象的引用,就会产生错误。
新手经常会犯以下错误。
Tiger tony = new Tiger();
tony = third; // Error, the new object allocated above is reclaimed.
你可能想说的是:
Tiger tony = null;
tony = third; // OK.
铸造不当:
Lion leo = new Lion();
Tiger tony = (Tiger)leo; // Always illegal and caught by compiler.
Animal whatever = new Lion(); // Legal.
Tiger tony = (Tiger)whatever; // Illegal, just as in previous example.
Lion leo = (Lion)whatever; // Legal, object whatever really is a Lion.
C中的指针:
void main() {
int* x; // Allocate the pointers x and y
int* y; // (but not the pointees)
x = malloc(sizeof(int)); // Allocate an int pointee,
// and set x to point to it
*x = 42; // Dereference x to store 42 in its pointee
*y = 13; // CRASH -- y does not have a pointee yet
y = x; // Pointer assignment sets y to point to x's pointee
*y = 13; // Dereference y to store 13 in its (shared) pointee
}
Java中的指针:
class IntObj {
public int value;
}
public class Binky() {
public static void main(String[] args) {
IntObj x; // Allocate the pointers x and y
IntObj y; // (but not the IntObj pointees)
x = new IntObj(); // Allocate an IntObj pointee
// and set x to point to it
x.value = 42; // Dereference x to store 42 in its pointee
y.value = 13; // CRASH -- y does not have a pointee yet
y = x; // Pointer assignment sets y to point to x's pointee
y.value = 13; // Deference y to store 13 in its (shared) pointee
}
}
更新:正如评论中所建议的,必须注意 C 具有指针算法。但是,我们在 Java 中没有。
由于 Java 没有指针数据类型,因此无法在 Java 中使用指针。即使是少数专家也无法在 java 中使用指针。
另请参阅:Java 语言环境中的最后一点
Java确实有指针。任何时候在 Java 中创建对象时,实际上都是在创建指向该对象的指针。然后可以将此指针设置为不同的对象或null
,并且原始对象仍将存在(等待垃圾回收)。
在 Java 中你不能做的是指针运算。您不能取消引用特定的内存地址或增加指针。
如果您真的想获得低级,唯一的方法是使用Java Native Interface;即便如此,低级部分也必须用 C 或 C++ 完成。
Java 中有指针,但您不能像在 C++ 或 C 中那样操作它们。当您传递一个对象时,您传递的是一个指向该对象的指针,但与 C++ 中的含义不同。该对象不能被取消引用。如果你使用它的本地访问器设置它的值,它会改变,因为 Java 通过指针知道它的内存位置。但是指针是不可变的。当您尝试将指针设置到新位置时,您最终会得到一个与另一个同名的新本地对象。原始对象不变。这是一个演示差异的简短程序。
import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone {
public static void main(String[] args) throws java.lang.Exception {
System.out.println("Expected # = 0 1 2 2 1");
Cat c = new Cat();
c.setClaws(0);
System.out.println("Initial value is " + c.getClaws());
// prints 0 obviously
clawsAreOne(c);
System.out.println("Accessor changes value to " + c.getClaws());
// prints 1 because the value 'referenced' by the 'pointer' is changed using an accessor.
makeNewCat(c);
System.out.println("Final value is " + c.getClaws());
// prints 1 because the pointer is not changed to 'kitten'; that would be a reference pass.
}
public static void clawsAreOne(Cat kitty) {
kitty.setClaws(1);
}
public static void makeNewCat(Cat kitty) {
Cat kitten = new Cat();
kitten.setClaws(2);
kitty = kitten;
System.out.println("Value in makeNewCat scope of kitten " + kitten.getClaws());
//Prints 2. the value pointed to by 'kitten' is 2
System.out.println("Value in makeNewcat scope of kitty " + kitty.getClaws());
//Prints 2. The local copy is being used within the scope of this method.
}
}
class Cat {
private int claws;
public void setClaws(int i) {
claws = i;
}
public int getClaws() {
return claws;
}
}
这可以在 Ideone.com 上运行。
Java 没有像 C 那样的指针,但它确实允许您在堆上创建由变量“引用”的新对象。缺少指针是为了阻止 Java 程序非法引用内存位置,也可以让 Java 虚拟机自动执行垃圾收集。
您可以使用 Unsafe 类来使用地址和指针。然而,顾名思义,这些方法是不安全的,通常是个坏主意。不正确的使用可能会导致您的 JVM 随机死机(实际上,在 C/C++ 中错误地使用指针也会出现同样的问题)
虽然您可能习惯于使用指针并认为自己需要它们(因为您不知道如何以任何其他方式编写代码),但您会发现自己不需要,而且您会因此而变得更好。
从技术上讲,所有 Java 对象都是指针。但是,所有原始类型都是值。无法手动控制这些指针。Java 只是在内部使用传递引用。
不是真的,不。
Java没有指针。如果你真的想要,你可以尝试通过围绕反射之类的东西来模拟它们,但它会具有指针的所有复杂性而没有任何好处。
Java 没有指针,因为它不需要它们。您希望从这个问题中得到什么样的答案,即您内心深处是希望您可以将它们用于某事还是只是出于好奇?
Java中的所有对象都通过引用副本传递给函数,除了原语。
实际上,这意味着您发送的是指向原始对象的指针的副本,而不是对象本身的副本。
如果您想要一个示例来理解这一点,请发表评论。
Java 引用类型与 C 指针不同,因为在 Java 中不能有指向指针的指针。
正如其他人所说,简短的回答是“不”。
当然,您可以编写使用 Java 指针的 JNI 代码。取决于你想要完成的事情,也许这会让你到达某个地方,也许它不会。
您始终可以通过创建数组并使用数组中的索引来模拟点。同样,这取决于您要完成的工作,这可能有用也可能没用。
来自Godfrey Nolan的《反编译Android》一书
安全性规定在 Java 中不使用指针,因此黑客无法突破应用程序并进入操作系统。没有指针意味着其他东西——在这种情况下,JVM——必须负责分配和释放内存。内存泄漏也应该成为过去,或者理论上是这样的。一些用 C 和 C++ 编写的应用程序因像筛子一样泄漏内存而臭名昭著,因为程序员不注意在适当的时间释放不需要的内存——并不是说任何阅读这篇文章的人都会犯这种罪。垃圾收集还应该使程序员更有效率,花在调试内存问题上的时间更少。
你也可以有文字的指针。你必须自己实现它们。这对专家来说是非常基础的;)。使用一个 int/object/long/byte 数组,瞧,您已经具备了实现指针的基础知识。现在任何 int 值都可以是指向该数组 int[] 的指针。你可以增加指针,你可以减少指针,你可以乘指针。你确实有指针算术!这是实现 1000 个 int 属性类并拥有适用于所有属性的通用方法的唯一方法。您还可以使用 byte[] 数组而不是 int[]
但是,我确实希望 Java 可以让您通过引用传递文字值。沿线的东西
//(* telling you it is a pointer)
public void myMethod(int* intValue);
所有java对象都是指针,因为保存地址的变量称为指针,对象保存地址。所以对象是指针变量。
通过知道数组名称是指向第一个索引的指针,java 可以轻松地获得指针。这就是为什么当我们将数组传递给函数时,我们不写它的方括号。因为数组是参考
public class Main
{
public static void func ( int ptr1[] , int ptr2[] )
{
int temp;
temp = ptr1[0];
ptr1[0] = ptr2[0];
ptr2[0] = temp;
}
public static void main(String[] args) {
int x = 5; int y = 8;
// in c language
// int *p = &x; int *q = &y;
// in Java
int p[] = new int[1];
int q[] = new int[1];
p[0] = x; // same as pointer
q[0] = y; // same as pointer
func( p , q ); // passing address ( refrence )
System.out.println( " After Swap " );
System.out.println( "x = " + p[0] + " " + "y = " + q[0] );
}
}