`
ycysth
  • 浏览: 10059 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Thinking in Java 第五章 初始化与清理

阅读更多

用构造器初始化类:

构造器是一个很特殊的方法,方法名必须大写,并且没有返回类型(与返回void是不同的),没有参数的构造器称为无参构造器,例:

 

public class SimpleConstructor {

	// 默认无参构造器
	public SimpleConstructor() {
		
	}
	
	// 带参数的构造器
	public SimpleConstructor(String str){
		System.out.println(str);
	}
}

方法重载

每个重载的方法都必须有一个独一无二的参数类型列表,甚至参数顺序不同也可以,但这样不便于区分;例:

 

public class OverLoadingOrder {

	static void f(String str, int i){
		System.out.println("str:" + str + ",int:" + i);
	}
	
	static void f(int i, String str){
		System.out.println("int:" + i + ",str:" + str);
	}
	
	public static void main(String[] args) {
		f("abc", 1);
		f(1, "abc");
	}
}

 这样做是合法的,但并不便于区分两个方法的功能,所以一般重载的方法都有不同的类型或不同数量的参数。

基本类型的重载

如果传入的数据类型(实参)小于小于方法声明的参数类型(形参),实际数据类型就会被提升;如果形参类型范围小于实参,需要先进行窄化转换,例:

 

public class PrimitiveOverloading {

	// 该方法接收long类型参数
	static void f1(long x){
		System.out.println("f with param type long");
	}
	
	// 该方法接收int类型参数
	static void f2(int x){
		System.out.println("f with param type int");
	}
	
	public static void main(String[] args) {
		// 定义一个int类型的变量,在调用f1方式时,由于找不到有最佳匹配参数int形的方法,所以直接将int提升成了long型
		int x = 5;
		f1(x);
		
		long y = 5L;
		// 以下编译会报错,形参类型范围不能小于实参	
//		f2(y);
		// 进行窄化转换后可以使用,需要注意这样的转换是不安全的
		f2(Integer.parseInt(String.valueOf(y)));
	}
}

 

返回值是不能用来区分重载的,因为编译器无法区分你需要调用哪个方法。

默认构造器

在创建对象的时候,如果没有自定义构造器,编译器会自动创建一个无参的构造器;一旦自定义了构造器,不管有无参数,编译器都不会再自动创建构造器,例:

 

package com.test.tij4.initialization;

public class NoSynthesis {

	public static void main(String[] args) {
		// 编译器会报错,因为自定义了有参数的构造器,所以在创建对象时必须传递参数
		// new Car();
		// 成功创建对象,并将i的值传递给Car的属性number
		new Car(1);
	}
}

class Car {
	private int number;

	Car(int i) {
		this.number = i;
	}
}

 this 关键字

this所指代的是当前对象,操作方式和直接操作该对象的引用相同;在方法的调用时,在我们能见的参数之外,编译器还会将当前对象的引用作为第一个参数传递到被调用方法中,例:

 

public class Banana {
	public static void main(String[] args) {
		Person p = new Person();
		p.eat(1);
		// 上面一句的方法调用等同于下面一句,但无法编译通过,只需理解即可
		Person.eat(p, 1);
	}
}
class Person{ void eat(int count){} }

 如果有多个构造器,可以在构造器中调用构造器,但调用构造器必须放于当前构造器的第一句,并且一个构造器只能调用一个构造器

 

public class Flower {

	private int x;
	
	Flower(int x, int y){
		// 构造器中调用构造器
		this(x);
		// 编译错误,必须放置第一位,其实必须放置第一位已经明确一个构造器中是不可能调用两个构造器的
		this();
		// this的用法之一,用于区分同名的全局变量和局部变量
		this.x = x;
		System.out.println(y);
	}
	Flower(int x){
		
	}
	Flower(){
		
	}
	public static void main(String[] args) {
		new Flower(1, 2);
	}
}

static的含义

static的方法中不能使用this关键字,因为它本身就没有对象的实例,因此也不能调用非静态方法;仅仅通过类本身调用static方法,这也是static方法的主要作用之一;Java中没有全局方法的概念,但通过static方法可以做到互相访问。

finalize()方法

该方法用于垃圾回收中,可以理解为垃圾回收准备方法,因为finalize()方法一被调用,在下一次的垃圾回收时对象就会被回收,而不是说调用了该方法就直接进行回收。

在Java中对象并非总被回收或者说:

 

  1. 对象可能不被垃圾回收
  2. 垃圾回收并不等于c、c++中的析构(finalize())
  3. 垃圾回收只与内存有关
在Java中,需要记住垃圾回收不一定会发生,如果JVM未面临内存耗尽的情况,垃圾回收并不会执行。

 

成员初始化

对于局部变量,必须手动赋值初始化;对于成员遍历,如果不手动初始化,编译器会给出默认值;需要注意的是即使比如在构造器中给成员变量赋值,但其实在成员变量已经被自动初始了,这样也保证了成员变量的默认初始化。

初始化顺序:

 

class Window{
	Window(int count){
		System.out.println("new Window:" + count);
	}
}

class House{
	Window w1 = new Window(1);
	House(){
		System.out.println("new House");
		w2 = new Window(12);
	}
	void f(){
		System.out.println("execute method f");
	}
	Window w2 = new Window(2);
}
/**
 * 初始化顺序
 */
public class OrderOfInitialization {
	public static void main(String[] args) {
		House h = new House();
		h.f();
	}
}

/* result
new Window:1
new Window:2
new House
new Window:12
execute method f
*/

从以上例子结果可以看出,不论位置,变量的初始化先于构造方法,构造方法先于普通方法;w2被初始化了两次,一次是在Window w2 = new Window(2)时,第二次是在构造器中。

带有staic的初始化顺序:

class Table{
	public Table() {
		System.out.println("init table");
	}
	void f(){
		System.out.println("execute method f");
	}
}
class Cupboard{
	{
		System.out.println("cupboard area");
	}
	static {
		System.out.println("cupboard with static area");
	}
	public Cupboard() {
		System.out.println("init cupboard");
	}
	
}
public class StaticInitialization {
	public static void main(String[] args) {
		table.f();
		Cupboard cupboard = new Cupboard();
	}
	static Table table = new Table();
}
/* result
init table 静态成员变量初始化先于方法执行
execute method f
cupboard with static area 静态代码块执行现有构造器
cupboard area 非静态代码块执行次于静态代码块,但同样先于构造器
init cupboard
 */

可变参数列表

public class Varargs {
	static void f(Object... objects){
		for(Object obj : objects){
			System.out.println(obj);
		}
	}
	static void o(int... is){
		for(int i : is){
			System.out.println(i);
		}
	}
	static void o(String... strings){
		for(String str : strings){
			System.out.println(str);
		}
	}
	static void s(int size, int... is){
		for(int i : is){
			System.out.println(i);
		}
	}
	static void s(String c, String... strings){
		for(String str : strings){
			System.out.println(str);
		}
	}
	public static void main(String[] args) {
		f(1,2,3); // 可变参数的意义就在于可以输入任意长度的参数
		f(); // 即使一个也没有也是合法的
		o("1","2"); // 由此可见可变参数的重载和普通方法的没两样
//		o(); 但这样就不行了,因为编译器无法知道你调用的是那个o方法
		// 解决的办法就是分别给有可变参数的方法加上足以区分的其他参数列表
		s(1,2,3);
		s("1","2","3");
	}
}

枚举类型

定义一个枚举,完全可以看做是一个类来处理

public enum SimpleEnme {
	RED, BLUE, GREY, WHITE, BLACK
}

 使用枚举

public class UseEnum {
	public static void main(String[] args) {
		// 遍历值和查看顺序
		for(SimpleEnum e : SimpleEnum.values()){
			System.out.println(e + "ordinal:" + e.ordinal());
		}
		// 在Switch中使用
		s(SimpleEnum.RED);
		s(SimpleEnum.WHITE);
	}
	static void s(SimpleEnum e){
		switch(e){
			case RED : System.out.println("RED"); break;
			case BLACK : System.out.println("BLACK"); break;
			default : System.out.println("Deafult");
		}
	}
}
0
0
分享到:
评论

相关推荐

    Thinking in java4(中文高清版)-java的'圣经'

    4.4 Foreach语法 4.5 return 4.6 break和 continue 4.7 臭名昭著的“goto” 4.8 switch 4.9 总结 第5章 初始化与清理 5.1 用构造器确保初始化 5.2 方法重载 5.2.1 区分重载方法 5.2.2 涉及基本类型的重载 5.2.3 以...

    Thinking in Java Fourth Edition

    #### 第5章 隐藏实施过程 - **封装的重要性**:强调封装对于保护内部状态的重要性。 - **访问控制修饰符**:详解`public`、`private`、`protected`以及包访问权限的作用。 - **抽象类与接口**:对比抽象类与接口的...

    Thinking in Java.

    - **第4章:初始化与清理**:讨论对象的创建过程、初始化顺序以及资源释放的最佳实践。 ##### 第二部分:面向对象进阶 - **第5章:隐藏实现细节**:介绍抽象与封装的概念,学习如何设计具有良好隐藏机制的类。 - *...

    java基础补足和thinking In Java学习.rar

    第五章 初始化与清理 5.1 用构造器确保初始化 1.构造器命名必须与类名相同 2.构造器也是方法,满足方法的各种特征,无参数的构造器称为默认构造器,默认构造方法或者无参构造器。在没有其他构造方法的时候可以...

    对Java的思考(Thinking in Java) Java入门 java与C++对比 深入浅出

    第5章"隐藏实施过程"讲解了包作为组织代码的基本单位,以及访问控制修饰符如public、private和protected的作用。此外,还介绍了接口和类的访问控制,以及隐藏实现的具体策略。 第6章"类再生"即类的继承,是面向对象...

    Thinking in Java_all

    第五章“隐藏实施过程”引入了Java的包和访问控制机制。包是组织类的单元,提供了命名空间和访问控制。访问修饰符(public, private, protected, friendly)控制了类和成员的可见性。接口定义了方法签名,实现了抽象...

    thinking in java txt

    - **第5章:继承与多态** - **5.1 继承的概念**: - **5.1.1 一个简单的例子**:通过示例理解继承的基本概念。 - **5.1.2 远程工作**:继承的实际应用案例。 - **5.1.3 对象的转换**:子类对象与父类对象之间的...

    thinking in java

    第5章《隐藏实施过程》介绍了Java的包机制,用于组织和管理代码库,以及访问控制指示符,如public、private和protected。接口和实现的关系,以及类的访问控制,都是这一章的关键内容。 第6章《类再生》聚焦于类的...

    thinking in Java guide solutio

    根据提供的文件信息,我们可以将《Thinking in Java》第四版中的主要内容和知识点进行详细的解析与总结。本书由Bruce Eckel编写,是学习Java编程语言的经典教材之一。以下是对书中的几个关键章节及其涵盖的重要知识...

    Thinking in Java, 2nd edition

    《Thinking in Java》是Bruce Eckel的经典之作,第二版对初学者和经验丰富的开发者都具有极高的价值。这本书深入浅出地介绍了Java编程语言的核心概念和技术,帮助读者建立起扎实的面向对象编程思想。 1. 面向对象...

    thinking_in_java 第四版(英文)

    ### Thinking in Java 第四版 — 初始化与清理 #### 核心知识点概述 - **初始化的重要性**:在程序设计中,确保变量和对象被正确初始化至关重要,可以避免运行时错误和安全漏洞。 - **C 语言中的初始化问题**:C ...

    Thinking_in_java中文第4版

    ##### 第5章 隐藏实施过程 1. **包:库单元**:介绍Java包的概念,如何创建自定义包以及包的作用范围。 2. **Java访问指示符**:讨论四种不同的访问级别(public, protected, 默认, private)。 3. **接口与实现**...

    thinking in java 英文版第三版

    3. **初始化与清理**:详细介绍了Java中对象的创建过程以及如何有效地进行资源清理,确保程序的健壮性和安全性。 4. **隐藏实现细节**:强调了封装的重要性,展示了如何通过封装隐藏对象内部的具体实现,提供一个...

    Thinking_In_C#英文正式版

    第5章“Initialization & Cleanup”(初始化与清理)涉及对象的构造函数和析构函数,以及资源清理的重要性。第6章“Coupling and Cohesion”(耦合与内聚)则探讨了设计模块化程序的指导原则,这是编写可维护代码的...

    Thinking.in.Java第三版.第四版完整版

    4. **chap4 初始化与清理.pdf**:讨论了对象的生命周期,包括构造函数、初始化块、垃圾收集机制以及 finalize 方法,这些都是理解对象生命周期和内存管理的关键。 5. **chap7 多态性.pdf**:多态性是面向对象的重要...

    Thinking in CSharp

    - **第五章:初始化与清理**(Initialization & Cleanup):本章着重于C#中的对象生命周期管理,包括如何初始化对象以及在对象不再需要时如何进行适当的清理工作,这对于避免内存泄漏等问题至关重要。 - **第六章:...

Global site tag (gtag.js) - Google Analytics