《java编程思想》读书笔记(一)开篇&第五章(1)

时间:2023-03-08 23:22:58
《java编程思想》读书笔记(一)开篇&第五章(1)

2017 ---新篇章  今天终于找到阅读《java编程思想》这本书方法了,表示打开了一个新世界。

第一章:对象导论

内容不多但也有20页,主要是对整本书的一个概括。因为已经有过完整JAVA se的基础,看起来压力不大。全书概括就不做记载了

第五章:初始化与清理

初始化:

1.JAVA构造器:

命名:必须与类名相同

作用:保证在操作对象之前已经进行了对象初始化操作,没有返回值(new 表达式确实返回了对新建对象的引用,但构造器本身没任何返回值)

2.方法的重载:

相同方法名 ,不同的方法 和功能

3.如何区别方法的重载?

每个重载的方法都必须有一个独一无二的参数类型列表。通过参数类型列表区分(甚至顺序的不同也可以区分,一般不这么做)

注意:不能通过返回值区别重载。

比如对于

		test()
		{
			a();
		}
		 int  a()
		{
			System.out.println("a");
			return 1;
		}
		 void a()
		{
			System.out.println("b");
		}

我怎么知道调用的是哪个a方法呢?还有就是,这样连编译都过不了,编译器会认为你写了两个一样的方法

4.基本类型的重载:

基本类型能从一个“较小”的类型提升到一个”较大“的类型。比如说有一个方法

public void a(double x)//传 int 型 比如5 进去是可以的

{

}

如果传入的参数大于里面的 就得通过类型转换 进行窄化操作 ,否则编译器就会报错

public void a(int x)//传 double型 比如5.2222 进去是不行的。得先类型转换 窄化 再传

{

}

5.默认构造器:

即无参构造器。如果你写的类里没有构造器,编译器则会帮你自动创建一个无参构造器。

但是,如果你已经定义了一个构造器 ,编译器就不会给你生成了!比如,你写了一个有参构造器然后写一句

Person p = new Person(); //这是会报错的!因为并没有这个构造器

6.this 关键字

	class Banana { void peel(int i) { /* ... */ } }

	public class BananaPeel {
  	public static void main(String[] args) {
 	   Banana a = new Banana(),
	           b = new Banana();
	    a.peel(1);
	    b.peel(2);
	  }
	} ///:~

其实在a.peel(1)和b.peel(2)内部是这样的----

Banana.peel(a,1);

Banana.peel(b,2);

这是内部的形式 ,我们不能这么写。这样就把a,b传给了方法内部的this

7.在构造器中调用构造器

这是一个很有意思的东西,利用this指针在构造器里再调用构造器

	public class test {
		public static void main(String[] args) {
			test t = new test();
		}
		test()
		{
			this(1);
			//this();这里会报错,说“构造函数必须是构造函数的第一句”,这说明了两点!1.必须是第一句 2.一个构造器不能this构造两次
			System.out.println("0");
		}
		test(int a)
		{
			this(1,2);

			System.out.println("1");
		}
		test(int a,int b)
		{
			this(1,2,3);
			System.out.println("2");
		}
		test(int a,int b,int c)
		{
			this(1,2,3,4);
			System.out.println("3");
		}
		test(int a,int b,int c,int d)
		{
			this(1,2,3,4,5);
			System.out.println("4");
		}
		test(int a,int b,int c,int d,int e)
		{
			System.out.println("5");
		}
}

然后依次输出
5
4
3
2
1

0

这说明了

(1.利用this指针构造器里调用构造器 (2.得写在第一行 (3.一个构造器里最多一次

8.static含义。静态。没有this。所以static方法内部不能调用非静态方法。因为JAVA禁止使用全局方法,就用这个一定上替代作用

9. 清理:终结处理和垃圾回收(翻阅P89页即可)

10.finalize()方法

摘自知乎的一段回答非常好

问:

为什么java编程思想上说“如果需要进行清理,最好是编写你自己的清理方法,但不要使用finalize?

答:

作者:木女孩
链接:https://www.zhihu.com/question/50883321/answer/123140231
来源:知乎
著作权归作者所有。
其实你写了或者你用了“自己的清理方法”,只是没感觉到。比如InputStream的close方法就是。
现在的问题是为什么要自己写方法去释放资源,而不是直接写在finalize里面。
  • 这个破玩意儿不能保证及时的被执行

你说你都没用了,你还来个:哥们,我过一会儿再去释放你的资源。

  • 不能保证这玩意儿一定会被执行

这似乎没什么说的,这都不能保证,要你何用。

  • 这个玩意儿对性能影响很大,有没有这个玩意儿对于一个对象的创建和销毁性能差距能达到数十倍甚至更高

所以你写的类要释放资源,你就自己写个像InputStream的close一样的东西,该释放的时候让人家手动调用一下。你要去释放资源,记得往finally里面放就是。当然,Java7还有个try-with-resources可以用。
问题来了,finalize有什么*用?这玩意儿的特点就是不靠谱,你不知道它到底有没有执行,但不是说它一定不执行,它是有可能会被执行的对吧。
所以,你的程序应该做到对于正常跑有没有finalize都一样,换句话说,你一定要做的事情就别放到finalize里面了,别离了它就死了。
然后呢,finalize可以构成最后一道防线,虽然他不可靠,但毕竟还是有可能的吧,换句话说比没有还是要好一点吧。还说这个InputStream的close方法,这本来是应该由你来调用这个方法去释放资源的,结果你忘了或者傻逼了没有调这个方法,这个是不是就释放不了了,但是假如这个finalize的实现就是调用close方法,这就造成还是有一定概率会释放了对吧,这比没有强吧。假如你自己写的让别人使用的类也有一个类似的释放资源的方法,但是使用你的类的人没有调用你的释放资源的方法,你是不是可以在你的finalize方法里面看一下他是不是释放了资源,如果没有就给它搞点日志啥的提醒一下:**个**,会不会用啊。至于这个提醒能不能出来,你管它啊。
最后,这是FileInputStream的部分源代码

protected void finalize() throws IOException {
        if ((fd != null) &&  (fd != FileDescriptor.in)) {
            /* if fd is shared, the references in FileDescriptor
             * will ensure that finalizer is only called when
             * safe to do so. All references using the fd have
             * become unreachable. We can call close()
             */
            close();
        }
    }

作者:木女孩
链接:https://www.zhihu.com/question/50883321/answer/123140231
来源:知乎
著作权归作者所有,已联系作者获得授权。