三、java的创建与销毁

宏观来看,任何语言都不能回避的两个问题:初始化和清理

一、初始化

1. java中初始化是和创建对象绑定在一起的

首先要明确一点,java中更普遍的类型是引用类型,虽然每本java的书籍里面都会先介绍八种基本数据类型,但是这八种实际上是特例。

一个值如果是属于某个类本身,那么它叫做成员变量;如果是在某个方法中定义的,那么它叫做局部变量。关于成员变量,java在新建对象的时候,会默认地给其成员变量自动初始化(这是出于安全性的考虑,避免程序员创建对象的时候忘记初始化)

自动初始化规则是:(后面介绍数组的时候,数组也会自动初始化,同样遵循下面的规则)
short,byte,int ,long :0
float,double :0.0
char: 空格
boolean :false
引用类型:null

事实上,自动初始化甚至发生在构造函数赋值之前,比如:

 1 public class Test {
 2     public static void main(String[] args) {
 3         A a = new A(1);
 4     }
 5 }
 6
 7 class A {
 8     int i;
 9     public A() {}
10     public A(int i) {
11         this.i = i;
12     }
13 }

上面这段简单的代码, 在new A的时候,首先执行自动初始化i赋值为0,然后才执行的this.i=i,把i的值变为1.

2. 函数重载

上面的小例子中,A()和 A(int i)方法构成重载,这里就顺便提一点:区分重载的方式

参数的个数或者类型(顺序不同也可以作为重载的区分,但是不推荐)
-----注意两点:不能根据返回值来区分重载; 不能根据权限区分符public ,protected来区分;
这个地方这么来理解:因为你调用方法,肯定是要在方法执行之前就能够确定你要执行的是哪个方法, java也是这样的, “必须在执行前”这一点,就决定了不能够根据返回值来确定重载,因为能够得到返回值了,方法都执行完了;

3. 关于构造函数,主要提两点:

-----自定义一个类,最好是显式定义其无参构造方法;

-----this可以用于调用构造方法

普通方法里面不能通过this来调用构造方法,只有构造方法里面才可以;
一个构造方法里面只能运用一次this的方式来调用构造方法;
this调用构造方法,必须写在调用this的构造方法的第一句;

4.涉及到static的初始化:牢记一点,优先静态

 1 public class Test{
 2     static Bowl bowl = new Bowl(1);
 3     Test() {
 4         bowl.f1(1);
 5         bowl2.f1(2);//注意哦,bowl2的创建语句写在Test()之后
 6     }
 7     static Bowl bowl2  = new Bowl(2);
 8
 9     public static void main(String[]args) {
10         Test t = new Test();
11     }
12 }
13
14 class Bowl {
15     Bowl(int i) {
16         System.out.println("bowl:"+i);
17     }
18     void f1(int i) {
19         System.out.println("f1:"+i);
20     }
21 }

对象中的静态数据,会比构造方法还要先执行,因此上面调用Test()方法的时候bowl2已经执行完了,所以虽然bowl2的new语句写在后面,但是编译和运行都不会出问题。如果是非静态,这里编译就会报错。

关于static再看一个例子:

 1 public class Test{
 2     static int i=1;
 3     void nor() {
 4         System.out.println("普通方法执行:"+i);
 5     }
 6     static void  f() {
 7         i++;
 8         System.out.println("静态方法执行"+i);
 9     }
10     Test() {
11         i++;
12         System.out.println("构造方法执行:"+i);
13     }
14     public static void main(String[]args) {
15         System.out.println(Test.i);
16         Test.f();
17         new Test().nor();
18     }
19 }

结果如下:

第一行结果为1,因为只执行 Test.i,在编译期间就能知道值,java不需要加载Test.class ,所以此时i还是1;
第二行调用f(),虽然它是静态的,但是还是需要加载Test.class ,所以i 变成 2;
第三行执行普通方法,要先建对象,更需要加载Test.class,i 变成 3;
并且,静态变量只会初始化一次

5.数组初始化

1)这里注意一下数组初始化的三中写法(面试常考)

int[] a = {1,2,3};
int[] a = new int[]{1,2,3};
int[] a = new int[3]; a[0]= 1,a[1]= 2,a[2]=3; //注意不要加 () ,就是 new int[3]

2)这里顺便提一下可变参数列表(貌似比较少看到有人用它),见下例:

 1 public class Test{
 2     public static void main(String[]args) {
 3         Object[] objs = {"String类型测试",1,1.1};
 4         new Test().printArray(objs);
 5         System.out.println("********");
 6         new Test().printArray2(objs);
 7         System.out.println("********");
 8         new Test().printArray2("我是String",2,2.2);
 9         System.out.println("********");
10         new Test().printArray2();
11     }
12
13     public void printArray(Object[] objs) {
14         for(Object obj : objs) {
15             System.out.println(obj.toString());
16         }
17     }
18
19
20     public void printArray2(Object... objs ){
21         for(Object obj:objs) {
22             System.out.println(obj.toString());
23         }
24     }
25 }

结果如下:

可以看到 ... 这个符号的含义,就是可变参数列表
上面printArray2中,如果传入普通参数,它会自动把获得的参数组装成为数组,然后自动放到objs中, 所以就可以直接用for-each循环打印了
而如果传入的本身就是数组形式,那么就不会再进行自动转换。
并且最后一行显示,表明,可变参数列表,即使什么都不传入也是可以的。

使用可变参数类型的时候,就需要注意一下重载的时候的一个小问题:

之前介绍重载的时候讲到区分重载的方式是参数类型不同,这个例子可以认为是一个例外(也可以认为不是例外,因为可变参数列表底层最终也是转换成为数组来处理的)

二、清理

1)finalize()

finalize()方法可以用来做一些清理前的工作,但是它不是类似于C++中的析构函数, 并不是写了就马上会被执行,这点一定要注意。
关于这一点的设计,也是java中一个比较智能的设计,因为去执行这些清理操作本身,就会要浪费你的内存,所以java设计的是没有必要写了finalize()马上就调用它(就像你被蚊子咬了一下,并不需要去住院一样)

关于finalize()方法不一定什么时候执行,必须要注意的是比如你写了数据库连接的语句,在执行完后要记得关闭流,这个关闭的操作要写在fanally中,而不是写在finalize()中。

2)finalize()的另一点

java中是可以调用C,C++的,但是java的清理机制并不能够自动销毁C,C++产生的内存消耗(比如java不能操作寄存器,但是C,C++却可以),那么常见的就是在finalize()里面写对应的C,C++的析构函数,来清理它们产生的垃圾。

时间: 2024-12-26 10:12:08

三、java的创建与销毁的相关文章

Java进阶 创建和销毁对象

最近准备写点Javase的东西,希望可以帮助大家写出更好的代码. 1.给不可实例化的类提供私有构造器 比如:每个项目中都有很多工具类,提供了很多static类型的方法供大家使用,谁也不希望看到下面的代码: TextUtils textUtils = new TextUtils(); if(textUtils.isDigitsOnly("123")) { //doSometing }else { //doSomething } 自己写个工具类,总有人喜欢先初始化个实例在调用方法,然后还附

【Effective Java】创建和销毁对象

一.考虑用静态工厂方法代替构造器 构造器是创建一个对象实例的最基本最常用的方法.开发者在使用某个类的时候,通常会使用new一个构造器来实现,其实也有其他方式可以实现的,如利用发射机制.这里主要说的是通过静态类工厂的方式来创建class的实例,如: public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; } 静态工厂方法和构造器不同有以下主要优势: 1.有意义的名称. 可能有多个构造器,

【读书笔记】《Effective Java》——创建和销毁对象

Item 1. 考虑用静态工厂方法替代构造器 获得一个类的实例时我们都会采取一个公有的构造器.Foo x = new Foo(): 同时我们应该掌握另一种方法就是静态工厂方法(static factory method). 一句话总结,静态工厂方法其实就是一个返回类的实例的静态方法. 书中给出的例子是Boolean的valueOf方法: 通过valueOf方法将boolean基本类型转换成了一个Boolean类型,返回了一个新的对象引用. 除valueOf外,像Java中的getInstance

Effective Java:创建和销毁对象

前言: 读这本书第1条规则的时候就感觉到这是一本很好的书,可以把我们的Java功底提升一个档次,我还是比较推荐的.本博客是针对<Effective Java>这本书第2章所写的一篇读书笔记.博客中也有会一些个人对某个模块的理解和深入探究,希望与大家一起进步. 概述: 本章的主题是创建和销毁对象:何时以及如何创建对象,何时以及如何避免创建对象,如何确保它们能够适时地销毁,以及如何管理对象销毁之前必须进行的各种清理动作. 相关内容: 1.考虑用静态工厂方法代替构造器 思路解析: 如果有人问你,如何

effective java读书笔记1——创建和销毁对象

今天刚开始读effective java,中文版的读起来很拗口,但感觉收获很多. 另外,这本书的内容是针对Java 1.5和1.6的. 在这里整理一下第2章:创建和销毁对象 的内容. 第一条:考虑用静态工厂方法代替构造器 这一条针对的情景是要获得类的实例时.一般说来,想要获得类的实例,都是通过构造函数(书里叫做构造器). 最常见的构造函数是这样的,没有返回参数,名字和类名相同. public class A{ public A(int a){ //构造函数内容 ... } } 而所谓的静态工厂,

[Effective Java]第二章 创建和销毁对象

第一章      前言 略... 第二章      创建和销毁对象 1.            考虑用静态工厂方法代替构造器 创建对象方法:一是最常用的公有构造器,二是静态工厂方法.下面是一个Boolean的简单示例: public static Boolean valueOf(boolean b) { return (b ? Boolean.TRUE : Boolean.FALSE); } l  静态工厂方法与构造器不同的第一大优势在于,它们有名称. 作用不同的公有构造器只能通过参数来区别(因

《Effect Java》学习笔记1———创建和销毁对象

第二章 创建和销毁对象 1.考虑用静态工厂方法代替构造器 优势: 1.有名称 2.不必在每次调用它们的时候都创建一个新的对象:   3.可以返回原返回类型的任何子类型的对象: JDBC(Java Database Connectivity) 服务提供者框架(Service Provider Framework) 服务接口.提供者注册API.服务访问API.服务提供者接口(负责创建其服务实现的实例): 4.在创建参数类型实例的对象,它们使代码变得更加简洁 2.遇到多个构造器参数时,要考虑使用构造器

Effective Java 读书笔记(2创建和销毁对象)

第一章是引言,所以这里不做笔记,总结一下书中第一章的主要内容是向我们解释了这本书所做的事情:指导Java程序员如何编写出清晰.正确.可用.健壮.灵活和可维护的程序. 2.1考虑用静态工厂方法代替构造器 静态工厂方法与构造器相比有四大优势: (1)静态工厂方法有名称,具有适当名称的静态工厂方法易于使用.易于阅读: (2)不必每次在调用它们的时候都创建一个新的对象: (3)可以返回原返回类型的任何子类型的对象: (4)在创建参数化类型实例的时候,它们使代码变得更加简洁. 同时静态工厂方法也有两大缺点

java:session的创建与销毁

创建session: ServletActionContext.getRequest().getSession().setAttribute("update", model); DutiesScienceEndowScore update = (DutiesScienceEndowScore) ServletActionContext.getRequest().getSession().getAttribute("update"); 销毁session: Servl