Saj*_*ani 236
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;
Run Code Online (Sandbox Code Playgroud)
取消引用null:
first.growl(); // ERROR, first is null.
third.growl(); // ERROR, third has not been initialized.
Run Code Online (Sandbox Code Playgroud)
别名问题:
third = new Tiger();
first = third;
Run Code Online (Sandbox Code Playgroud)
丢失细胞:
second = third; // Possible ERROR. The old value of second is lost.
Run Code Online (Sandbox Code Playgroud)
您可以通过首先确保不再需要旧值second或将另一个指针指定为second的值来使此安全.
first = second;
second = third; //OK
Run Code Online (Sandbox Code Playgroud)
请注意,以其他方式给出第二个值(NULL,new ...)同样是一个潜在的错误,并可能导致丢失它指向的对象.
OutOfMemoryError当您调用new并且分配器无法分配所请求的单元时,Java系统将抛出异常().这是非常罕见的,通常是由于失控递归造成的.
请注意,从语言的角度来看,将对象放弃到垃圾收集器根本不是错误.这只是程序员需要注意的事情.相同的变量可以在不同的时间指向不同的对象,并且当没有指针引用它们时将回收旧的值.但是如果程序的逻辑需要至少保持一个对象的引用,它将导致错误.
新手经常会出现以下错误.
Tiger tony = new Tiger();
tony = third; // Error, the new object allocated above is reclaimed.
Run Code Online (Sandbox Code Playgroud)
你可能想说的是:
Tiger tony = null;
tony = third; // OK.
Run Code Online (Sandbox Code Playgroud)
铸造不当:
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.
Run Code Online (Sandbox Code Playgroud)
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
}
Run Code Online (Sandbox Code Playgroud)
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
}
}
Run Code Online (Sandbox Code Playgroud)
更新:如评论中所建议的那样,必须注意C有指针算术.但是,我们在Java中没有这个.
Mic*_*ers 42
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;
}
}
Run Code Online (Sandbox Code Playgroud)
这可以在Ideone.com上运行.
您可以使用Unsafe类来使用地址和指针.然而顾名思义,这些方法是UNSAFE,通常是一个坏主意.不正确的使用可能导致您的JVM随机死亡(实际上同样的问题在C/C++中错误地使用指针)
虽然你可能习惯了指针,并认为你需要它们(因为你不知道如何编码任何其他方式),你会发现你没有,你会更好.