标签:建议 页面 形式 http 回收 没有 装包 准备 long
在 Java 中,通过提供构造器,类的设计者可确保每个对象都会得到初始化。Java 会保证初始化的进行。构造器采用与类相同的名称。
因为可以要用多种方式来创建并初始化一个对象,所以就需要多个构造器,而构造器的名称又需要和类名相同,所以必须允许方法名相同而形式参数不同的构造器存在,所以 Java 中有方法重载。
class Rock {
Rock() {
// 默认构造器
}
Rock(int i) {
// 带参数的构造器
System.out.println("i=" + i);
}
void print() {
System.out.println("i = null");
}
void print(int i) {
System.out.println("i = " + i);
}
}
// 初始化
Rock r1 = new Rock(); // 调用默认构造器
Rock r2 = new Rock(1); // 调用带参数的构造器
r2.print();
r2.print(1);
方法签名是由方法名和参数类型列表构成的,所以用参数类型列表区分重载方法。不能用返回值区分重载方法
由于基本类型可能会从一个“较小”的类型自动提升为一个“较大”的类型,所以在重载方法中需要特别注意:
int
处理由于同一类型的对象都可以调用相同的方法,为了在方法中区分不同的对象,会把对象的引用作为参数传递给方法,a.fun(1)
在编译器内部会被翻译成ClassName.fun(a, 1)
,我们可以通过this
关键字在方法中访问到对象的引用。
this
,直接调用即可。public class Flower {
int petalCount = 0;
String s = "initial value";
Flower(int petals) {
petalCount = petals;
System.out.println("int arg ,petalCount = " + petalCount);
}
Flower(String ss) {
s = ss;
System.out.println("string arg ,s = " + s);
}
Flower(String s, int petals) {
this(petals);
// this 只能调用一次构造器
this.s = s;
System.out.println("string & int arg, s = " + s + ", petalCount = " + petalCount);
}
Flower() {
this("hello", 24);
}
public static void main(String[] args) {
Flower flower = new Flower();
System.out.println("flower.petalCount = " + flower.petalCount);
System.out.println("flower.s = " + flower.s);
}
}
// int arg ,petalCount = 24
// string & int arg, s = hello, petalCount = 24
// flower.petalCount = 24
// flower.s = hello
static 方法就是没有 this 的方法,在 static 中不能调用非静态方法,但是反过来可以。
Java 中没有用于释放对象的 delete,因为垃圾回收器会自动帮你释放存储空间,因此 Java 中没有析构函数。但是垃圾回收不能完全代替析构函数,如果希望进行除释放存储空间之外的清理工作,我们需要明确调用某个 Java 方法。例如某个类打开了一个文件,垃圾回收不能自动帮我们关闭这个文件。为什么这个工作不能有 finalize() 方法来完成呢,原因其实在上面已经说明了,对象可能不会被垃圾回收,也就是说 finalize() 方法可能永远都不会被调用。
如果 JVM 没有面临内存耗尽的情况,它是不会浪费时间去执行垃圾回收以恢复内存的。
虽然我们不能用 finalize() 方法来进行“清理”,但是我们可以利用它验证某个对象的终结条件。还是刚才那个打开文件的例子,假设在文件没有关闭的时候,垃圾回收将对象回收了,这就会产生一些非常难找的 bug。而 finalize() 可以帮助我们发现这种 bug。
class Book {
boolean checkedOut = false;
Book(boolean checkOut) {
checkedOut = checkOut;
}
void checkIn() {
checkedOut = false;
}
protected void finalize() {
if (checkedOut) {
System.out.println("Error: checked out");
}
// super.finalize();
}
}
public class TerminationCondition {
public static void main(String[] args) {
Book novel = new Book(true);
novel.checkIn();
new Book(true);
System.gc();
}
}
// Error: checked out
如上面这个例子,我们希望 Book 在被回收前已经 checkIn 了,所以我们在 finalize() 中写了一个条件语句来判断。
System.gc()
强制 GCsuper.finalize();
垃圾回收器会提高对象在堆上创建的速度,这是因为 Java 的堆的实现与 C++ 的不同,其更像是一个传送带,每分配一个对象,它就往前移动一格,所以“堆指针” 只是简单的移动到尚未分配的空间,这意味 Java 中在堆上的分配速度非常快。当然,如果只是简单的像传送带一样工作的话,Java 的堆会占用大量的虚拟内存,进而导致频繁的页面调度,并可能会导致内存资源耗尽,因此需要有垃圾回收器的介入。垃圾回收会一边回收空间一边对堆进行“紧凑”操作。
几种常见的垃圾回收机制:
JVM 中采用的垃圾回收机制:
Java 中 JIT(Just-In-Time)技术:
这种技术可以把程序全部或部分翻译成本地机器码,而不是通过 JVM,进而提升程序的运行速度。
当需要装载某个类时(第一次创建这个类时),编译器会找到其.class 文件,然后将该类的字节码装入内存,此时有两种做法:
Java 尽力保证:所有变量在使用前都能得到适当的初始化。
局部变量没有默认初始值,如有在未初始化前使用它会报错编译错误,而类变量则有默认初始值。
Java 允许在定义类成员变量的时候为其赋值进行初始化。非基本类型也可以,同时可以使用已经函数或已经初始化好的变量进行初始化,但要保证初始化顺序的正确。
public class InitialValues {
boolean t = false;
char c = 'a';
byte b = 1;
short s = 2;
int i = func(s);
long l = 4 + i;
float f = (float)5.0; // 浮点数字面量是 double 类型的
double d = 6.0;
String reference = new String("hello world"); // 非基本类型也可以
int func(short s) {
return s*2;
}
}
public class InitialValues {
boolean t = false;
char c = 'a';
byte b = 1;
short s = 2;
int i = 3;
long l = 4;
float f;
double d;
String reference;
{
f = (float) 1.0;
d = 2*f;
reference = new String("hello");
reference = reference + f + d;
}
static {
System.out.println("hello");
}
static int a;
static {
System.out.println("A is " + a);
a = 2;
}
}
对象的创建过程:
数组是同类型的、用一个标识符名称封装到一起的一个对象序列或基本类型数据序列。
定义方式:
int[] a; //建议使用这种
int a[]; //这样也可以, 但是不能指定数组的类型。`int a[3];` 这样是不允许的
int[] a;
这样只是定义了一个数组的引用,我们可以使用new
来创建一个数组,也可以直接初始化数组:
int[] a = new int[3]; // 使用 new 来创建一个数组,这时真实数据会分配在堆中,所以默认值都为“零”
int[] b = {1, 2, 3}; // 直接初始化一个长度为3的数组
Integer[] c = new Integer[3]; // 创建一个对象数组,保存引用,这时初始值都为 null
Random rand = new Random(2);
int len = rand.nextInt(20);
int[] c = new int[len]; // 长度不一定要是一个字面值,可以是变量
数组初始化的坑点:
InitialValues initialValues = new InitialValues();
initialValues.printInitialValues();
String[] stringArray = {"hello", "world"};
// initialValues.printStringArrary({"hello", "world"}); // 编译错误
initialValues.printStringArrary(stringArray);
initialValues.printStringArrary(new String[]{"hello", "world"}); //正确打开方式
int[] intArray = {1, 2, 3, 4};
// initialValues.printIntArray({1, 2, 3, 4}); // 编译错误
initialValues.printIntArray(intArray);
initialValues.printIntArray(new int[]{1, 2, 3, 4});
在方法中,用ClassName... ArgName
的形式可以定义可变参数列表,在方法中,ArgName 本质上是一个数组。在可变列表中可以使用任何类型,包括基础类型。这里传入基本类型时,没有依赖自动装包和解包,这意味着,ClassName 为 int 时,ArgName 是一个 int[],而不是 Integer。在重载方法时,应该只在一个方法中使用可变参数列表
static void printArray(Object... args) {
for(Object arg: args) {
System.out.print(arg + " ");
}
System.out.println();
}
static void f(int required, int... args) {
System.out.println("Required: " + required);
for(int i: args) {
System.out.print(i + " ");
}
System.out.println();
}
public static void main(String[] args) {
printArray(1, 2, 3, 4, 5);
f(1);
f(1, 2, 3);
Integ
}
toString()
显示其名称,ordinal()
表示声明顺序enum EnumDemo {
HELLO, WORLD,
};
EnumDemo e1 = EnumDemo.HELLO;
System.out.println(e1); // 自动调用toString()
System.out.println(e1.ordinal());
for(EnumDemo e: EnumDemo.values()) {
System.out.println("EnumDemo: " + e + " ordinal " + e.ordinal());
}
// HELLO
// 0
// EnumDemo: HELLO ordinal 0
// EnumDemo: WORLD ordinal 1
首发与Code & Fun
标签:建议 页面 形式 http 回收 没有 装包 准备 long
原文地址:https://www.cnblogs.com/wuxiaobai24/p/12302173.html