Java中的默认值和初始化
Posted
技术标签:
【中文标题】Java中的默认值和初始化【英文标题】:Default values and initialization in Java 【发布时间】:2013-10-08 12:10:21 【问题描述】:基于my reference,原始类型具有默认值,而对象为空。我测试了一段代码。
public class Main
public static void main(String[] args)
int a;
System.out.println(a);
System.out.println(a);
行将是指向变量a
的错误,它表示variable a might not have been initialized
,而在给定的引用中,integer
将具有0
作为默认值。但是,使用下面给定的代码,它实际上会打印0
。
public class Main
static int a;
public static void main(String[] args)
System.out.println(a);
第一个代码可能出现什么问题?类变量的行为是否与局部变量不同?
【问题讨论】:
第二个打印的是什么? 0? @porfiriopartida 是的,0 打印在第二个代码上。 静态上下文在您的应用程序启动时初始化,它正在启动一个默认值。 0 表示 int,空字符串表示 String,我相信布尔值等为 false。但对于本地或实例目的,您可以控制它们;您无法保证何时或谁将访问静态属性。 这可能是Variable might not have been initialized error的副本。 【参考方案1】:我编写了以下函数来返回原始或数字的默认表示0 或 false:
/**
* Retrieves the default value 0 / false for any primitive representative or
* @link Number type.
*
* @param type
*
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T getDefault(final Class<T> type)
if (type.equals(Long.class) || type.equals(Long.TYPE))
return (T) new Long(0);
else if (type.equals(Integer.class) || type.equals(Integer.TYPE))
return (T) new Integer(0);
else if (type.equals(Double.class) || type.equals(Double.TYPE))
return (T) new Double(0);
else if (type.equals(Float.class) || type.equals(Float.TYPE))
return (T) new Float(0);
else if (type.equals(Short.class) || type.equals(Short.TYPE))
return (T) new Short((short) 0);
else if (type.equals(Byte.class) || type.equals(Byte.TYPE))
return (T) new Byte((byte) 0);
else if (type.equals(Character.class) || type.equals(Character.TYPE))
return (T) new Character((char) 0);
else if (type.equals(Boolean.class) || type.equals(Boolean.TYPE))
return (T) new Boolean(false);
else if (type.equals(BigDecimal.class))
return (T) BigDecimal.ZERO;
else if (type.equals(BigInteger.class))
return (T) BigInteger.ZERO;
else if (type.equals(AtomicInteger.class))
return (T) new AtomicInteger();
else if (type.equals(AtomicLong.class))
return (T) new AtomicLong();
else if (type.equals(DoubleAdder.class))
return (T) new DoubleAdder();
else
return null;
当底层 SQL 查询返回 null 而不是 0 时,我在休眠 ORM 投影查询中使用它。
/**
* Retrieves the unique result or zero, <code>false</code> if it is
* <code>null</code> and represents a number
*
* @param criteria
*
* @return zero if result is <code>null</code>
*/
public static <T> T getUniqueResultDefault(final Class<T> type, final Criteria criteria)
final T result = (T) criteria.uniqueResult();
if (result != null)
return result;
else
return Utils.getDefault(type);
Java 的许多不必要的复杂 事情之一,使其使用起来不直观。为什么实例变量用默认值 0 初始化但局部变量不是不合逻辑的。类似于为什么枚举没有内置标志支持和更多选项。与 C# 相比,Java lambda 是一场噩梦,不允许类扩展方法也是一个大问题。
Java 生态系统想出了为什么它不可能的借口,但我作为用户/开发人员我不关心他们的借口。我想要简单的方法,如果他们不解决这些问题,他们将来会松懈,因为 C# 和其他语言不会等待让开发人员的生活更简单。自从我每天使用 Java 以来,看到过去 10 年的衰落真是令人难过。
【讨论】:
【参考方案2】:在第一种情况下,您将“int a”声明为局部变量(在方法内声明)并且局部变量没有获得默认值。
但是静态和非静态的实例变量都被赋予了默认值。
实例变量的默认值:
int = 0
float,double = 0.0
引用变量 = null
char = 0(空格字符)
布尔 = 假
【讨论】:
【参考方案3】:仔细阅读your reference:
默认值
声明字段时并不总是需要赋值。 已声明但未初始化的 字段 将设置为 编译器的合理默认值。一般来说,这个默认 将为零或空,具体取决于数据类型。依靠这样的 然而,默认值通常被认为是糟糕的编程 风格。
下图总结了以上数据的默认值 类型。
。 . .
局部变量略有不同;编译器从不分配 未初始化的局部变量的默认值。 如果您不能 在声明它的地方初始化你的局部变量,确保 在您尝试使用它之前为其分配一个值。访问一个 未初始化的局部变量将导致编译时错误。
【讨论】:
我也读过这个,但是数组呢。在本地上下文中使用的数组被赋予了一个默认值,但在文档中没有提到它。 这里有一个很好的解释本地上下文中的数组作为接受的答案:***.com/questions/13511702/int-array-initialization【参考方案4】:在第一个代码示例中,a
是一个main
方法局部变量。方法局部变量在使用前需要初始化。
在第二个代码示例中,a
是类成员变量,因此它将被初始化为默认值。
【讨论】:
我注意到方法局部数组变量在使用时没有给出“变量 a 可能没有被初始化”。声明为数组的方法变量是否初始化为默认值,而独立变量则没有? 这种情况下的默认值是多少?某种空值? @PeterMortensen Primitives 不使用 null 作为默认值。他们使用原始值的合法值作为默认值,例如 0 表示 int。完整的细节可以在这里找到:docs.oracle.com/javase/tutorial/java/nutsandbolts/…【参考方案5】:在声明原始类型值时需要牢记一些事项。
他们是:
-
在方法中声明的值不会被赋予默认值。
声明为实例变量或静态变量的值将分配默认值为 0。
所以在你的代码中:
public class Main
int instanceVariable;
static int staticVariable;
public static void main(String[] args)
Main mainInstance = new Main()
int localVariable;
int localVariableTwo = 2;
System.out.println(mainInstance.instanceVariable);
System.out.println(staticVariable);
// System.out.println(localVariable); // Will throw a compilation error
System.out.println(localVariableTwo);
【讨论】:
【参考方案6】:局部变量没有默认值。如果没有通过某种方式分配值,它们的初始值是未定义的。在你可以使用局部变量之前,它们必须被初始化。
在类级别(作为成员,即作为字段)和方法级别声明变量时存在很大差异。
如果您在类级别声明一个字段,它们会根据其类型获得默认值。如果您在方法级别或作为块声明变量(表示 内的任何代码),则不会获得任何值并保持未定义,直到它们以某种方式获得一些起始值,即分配给它们的一些值。
【讨论】:
【参考方案7】:这些是涉及的主要因素:
-
成员变量(默认OK)
静态变量(默认OK)
final 成员变量(未初始化,必须在构造函数上设置)
最终的静态变量(未初始化,必须在静态块上设置)
局部变量(未初始化)
注意 1:您必须在每个实现的构造函数上初始化最终成员变量!
注意 2:您必须在构造函数本身的块内初始化 final 成员变量,而不是调用另一个初始化它们的方法。例如,这是无效有效的:
private final int memberVar;
public Foo()
// Invalid initialization of a final member
init();
private void init()
memberVar = 10;
注意 3:数组是 Java 中的对象,即使它们存储原语。
注意 4:当你初始化一个数组时,它的所有项目都设置为默认值,与成员或本地数组无关。
我附上一个代码示例,呈现上述案例:
public class Foo
// Static and member variables are initialized to default values
// Primitives
private int a; // Default 0
private static int b; // Default 0
// Objects
private Object c; // Default NULL
private static Object d; // Default NULL
// Arrays (note: they are objects too, even if they store primitives)
private int[] e; // Default NULL
private static int[] f; // Default NULL
// What if declared as final?
// Primitives
private final int g; // Not initialized. MUST set in the constructor
private final static int h; // Not initialized. MUST set in a static
// Objects
private final Object i; // Not initialized. MUST set in constructor
private final static Object j; // Not initialized. MUST set in a static
// Arrays
private final int[] k; // Not initialized. MUST set in constructor
private final static int[] l; // Not initialized. MUST set in a static
// Initialize final statics
static
h = 5;
j = new Object();
l = new int[5]; // Elements of l are initialized to 0
// Initialize final member variables
public Foo()
g = 10;
i = new Object();
k = new int[10]; // Elements of k are initialized to 0
// A second example constructor
// You have to initialize final member variables to every constructor!
public Foo(boolean aBoolean)
g = 15;
i = new Object();
k = new int[15]; // Elements of k are initialized to 0
public static void main(String[] args)
// Local variables are not initialized
int m; // Not initialized
Object n; // Not initialized
int[] o; // Not initialized
// We must initialize them before use
m = 20;
n = new Object();
o = new int[20]; // Elements of o are initialized to 0
【讨论】:
【参考方案8】:在Java中,默认初始化只适用于类成员的实例变量。
不适用于局部变量。
【讨论】:
【参考方案9】:所有成员变量都必须加载到堆中,因此在创建类实例时必须使用默认值初始化它们。
如果是局部变量,它们不会被加载到堆中。它们存储在堆栈中,直到它们被使用。这是在 Java 7 之前,所以我们需要显式地初始化它们。
【讨论】:
【参考方案10】:是的,实例变量将被初始化为默认值。对于局部变量,使用前需要初始化:
public class Main
int instaceVariable; // An instance variable will be initialized to the default value
public static void main(String[] args)
int localVariable = 0; // A local variable needs to be initialized before use
【讨论】:
以上是关于Java中的默认值和初始化的主要内容,如果未能解决你的问题,请参考以下文章