疯狂java讲义第六章(面向对象(下))重点知识

1、对于java自动装箱和自动拆箱的理解:自动装箱和自动拆箱仅仅是针对8个基本类型的。因为java为8个基本类型提供了对应的包装类(也就是拆箱和装箱的箱子)。这些包装类让8个基本类型可以被当成java的类来使用。
自动装箱概念:可以把基本类型值直接赋给对应的包装类引用变量。
自动拆箱概念:可以把包装类对象直接赋给对应的基本类型变量。

2、因为java的缓存机制,对于-128到127的数字自动装箱成Integer对象,= =比较返回true,但是其他的数字自动装箱的对象
= =返回false。

3、Object类的方法
toString()自我描述方法,返回运行时类名+@+十六进制的hashCode;

== 和 equals方法:
= =用于数值类型的基本类型变量,只要值相同就返回true,对于两个引用类型变量,只有它们指向同一个对象时才会返回true,不可用于比较类型上没有父子关系的两个对象。编译时的就能确定的字符串= =后返回true,而运行时才确定的字符串= =后返回false。
equals方法,采用值相等的判断规则,除了String以外,其他引用类型使用equals和= =没区别,两个引用变量指向不同对象但是值相同,依旧返回false,只有引用类型变量指向同一个对象才会返回true。而String已经重写了Object的equals方法,String应该是重写了hashcode方法,根据字符序列计算hashcode而不是对象在内存中的地址,只要两个字符串的值相等就返回true,不需要是同一个对象。
其他类想要实现相同的效果甚至更极端的效果,让🐶和人相等都可以通过自己重写equals方法实现。

getClass()方法,用final修饰,子类无法重写。返回运行时类的类型。

hashCode()方法

finalize()方法

wait()、notify()、notifyAll()

clone()。protected修饰,因此只能被子类重写或调用。

访问控制符我真的应该自己尝试一下,弄清楚来。

自我克隆??,就是浅克隆,直接复制一个对象,但是引用变量指向的对象并不复制,只是复制引用变量指向的地址。

4、即使实例=null,也可以调用类方法或者类变量。

5、单例类,通过一个指向该类实例的类变量和无法用构造器新建实例的办法,保证jvm中只有该类的一个实例。

6、final严格说法是它修饰的变量不可以被改变,一旦获得了初始值,该final变量的值就不能被重新赋值。

7、final成员变量在显式初始化之前不能直接访问,但可以通过方法来访问。但是我们编程不要在final显式初始化之前用方法访问final成员变量。

8、系统只会初始化成员变量,不会对局部变量进行初始化,局部变量必须由程序员显式初始化。

9、final修饰的形参不能被赋值。

10、final修饰的引用类型变量不能被重新赋值,但可以改变引用类型变量所引用对象的内容。也就是final只对栈区的变量生效,不影响堆区的对象。

11、能在编译时确定的字符串会被放入常量池,而且不会重复,所以= =将返回true,而运行时创建出来的,将被保存在运行时内存区(即堆内存),不会放入常量池,不保证唯一。所以= =可能对值相同的字符串返回false。

12、能不能在编译时就确定初始值,可以依据如下结论:
如果使用了方法,或者非(final修饰并且直接在定义时就赋初始值,这种变量可以执行宏替换)的变量,就无法再编译时确定初始值,只能在运行时确定初始值。

13、final修饰的方法不能重写,但可以重载。final修饰的类无法被继承,也就是不可以有子类。

14、不可变类的意思是类的所有实例变量不可变,可变类的含义是该类的实例变量的值是可变的(只要有可变的实例变量就算可变类)。不可变类如果变量包含引用类型变量,则要按照书188页的机制来保护该成员变量所引用的对象不会被修改。否则创建的不可变类会失败的这么彻底。也就是用参数新建另一个对象的方式隔离不可变对象。

15、缓存实例的不可变类的实现。.valueOf()方法。

16、抽象方法存在的意义是什么?为什么无法调用方法多态不是可以吗?书191疑问❓,我搞错了,书上说的就是不用抽象类直接不管它的情况。

抽象类的意义,就是在多态的时候,可以使用子类扩展的方法,而抽象父类只需要设置一个方法签名就好了。就是在Object a = new Shape();的时候a可以使用shape扩展的方法就不用再多一步强制转换了。(也只是一个猜测。证实了在书193页下面。作者李刚说了。)
抽象类还有一个意义,模板模式,也就是多个类有相同的一个方法名,但是内部实现不同,就可以定义一个抽象类,比如Rectangle类和Circle类都要计算周长,则可以抽象出来一个Shape类,中包含一个calperimeter抽象方法,共子类继承和重写。
其实模板模式也是接口的意义吧?

17、有抽象方法的类只能被定义成抽象类,抽象类里可以没有抽象方法。继承了抽象父类但没有完全实现父类包含的抽象方法。或实现了一个接口,但没有完全实现接口包含的抽象方法三种情况,只能被定义成抽象类。

18、final和abstract永远不能同时使用。
static和abstract也不能同时修饰方法,也就是不存在所谓的类抽象方法。
private和abstract也不能同时修饰方法。194页

19、为什么没有抽象变量?
其实也是多态的问题,多态下,父类不能用子类的扩展方法,能用子类的扩展变量吗?这个要实验一下,猜测应该是可以,因为多态下,子类的扩展方法是存在也无法被调用,需要强制类型转换才能调用,所以提出了抽象类这个方法,来不用强制类型转换也能使用子类的扩展方法。如果子类的变量也有相同的问题,那也应该有抽象变量才对。

20、尝试使用抽象类实现一组模板模式实例。模板模式1.0和模板模式2.0(一个普通方法中包含抽象方法)

21、不理解接口,接口的意义是什么,为什么能够降低耦合性??
猜测,应该是把继承和实现进行对比来说的。其实接口我也经常用,android里面的onclicklistener,就是一个接口,而且还是一个函数式的接口,只有一个Onclick方法需要实现。
如果用类或者抽象类来代替接口,那么继承的位置就被占掉了,想要再继承一个父类得到它的方法,要么间接继承,要么组合,这两种耦合性确实更大。

然后接口有好多规则,书本196页。接口可以直接继承多个父类。implements必须放在extends之后(如果有extends的情况下)。接口好像是一种规范,只是规定了实现这个接口的普通类里一定包含这个接口规定的方法(也就是提供的服务),所以接口的目的是什么??为什么有那么多的限制?和抽象类又有什么区别??不理解,201页不理解。
我现在看来抽象类和接口最大的区别就是继承和实现的区别。

22、面向接口编程??
设计模式:简单工厂模式。
当Computer需要组合一个Printer对象的时候。最初始的思路是,直接在Computer类里面定义一个Printer成员变量。如果需要换成BetterPrinter对象,则要打开Computer的源码,把Printer p = new Printer();改成BetterPrinter p = new BetterPrinter();,如果有100个类这么组合Printer,则需要修改100次,10000个则需要修改10000次。如果采用在构造器里面传入的办法,每个类里面也需要声明Printer p;然后再构造器里通过传入的参数进行初始化。这样子根本无法解决问题,也需要对每个类中的声明和构造器中的声明进行修改。采用继承,也就是BetterPrinter继承Printer,好像就可以解决这个问题了,但是传入的时候其实也要显式声明类,不能彻底解决问题,因为多态情况下,BetterPrinter一定包含.getData()和.out()方法,但是实际上不好,因为继承的话,子类会包含很多父类的其他不需要的东西,比如成员变量,构造器,其他方法而且子类可以不重写父类的方法。那么换成继承抽象类,Printer和BetterPrinter继承同一个抽象类?。那么我们就应该思考如何解决这个问题。把继承父类的方法。。。。算了算了,我也不懂,不是说不清,而是我不懂。
说一下书上的思路,Printer和BetterPrinter实现同一个接口,保证了有相同的方法被旧的实例调用。使用工厂类创建类,这样做的目的是,不使用工厂类的话,每次传入都要写一个new Printer(),这样子都要修改,而用工厂类,传入Printer统一写成,工厂类的方法,并不出现Printer本身,这样就可以只修改工厂类的方法实现,就可以实现全部修改的效果。
使用工厂类的目的,用于传入时不需要直接写出new Printer(),后面也就不用修改了,只需要修改工厂类的方法这一个地方就好了。
类实现Output接口最主要的目的是,各个类中的Output output可以接收实现相同Output接口的类。这样的效果其实使用继承父类、继承抽象类也可以实现。
这样子只需要创建一个实现接口的BetterPrinter类,然后将工厂类方法中的new Printer改为new BetterPrinter。就可以实现修改全部使用Printer的地方了。

所以简单工厂模式的要点就是,
一、组合的时候,每个类中声明的是一个接口或者父类或者抽象类。
二、使用工厂类的方法return类给接受类,不显式写出具体类名。

用一个非常简单的比喻来说明简单工厂模式。
你是一个类要租房子,中介就是那个工厂方法,而房子就是你要组合的类。每当你要换房子的时候,都只需要找到同一个中介沟通,由中介帮你找不同的房子,这样不论换成什么房子,你都不需要关心,只需要住就好了。

23、面向接口编程,命令模式。
也就是利用接口,把继承接口的类当做实参,然后方法中已经写好了利用这个实参的某个方法。其实抽象类也可以实现,但是会占用继承的那个位置。

24、内部类可以访问外部类的私有数据,但是外部类不能直接访问内部类的数据,必须新建实例,通过实例才能访问。
原因其实和静态方法不能访问非静态成员变量一样,都是一个生命周期更长,一个更短,短的可以调用长的,因为它始终存在。长的调用短的就会出现问题,在你出生10年前,我打电话给你,肯定打不通,这就是问题所在。

25、非静态内部类不能拥有静态成员。为什么?要自己试一下。说不通,非静态内部类在外部类初始化的时候也会在堆区中创建一个引用变量,这样子好像并不会初始化非静态内部类。209。是不是声明引用变量,并不会初始化类,所以非静态内部类里面的静态变量也就不会创建,这个时候调用的话可能会报错?暂时也只能这样解释。

26、为什么外部类只有public和default两个访问控制符,因为外部类的上一级程序单元是包,所以它只有两个作用域。我发现我不理解protect访问控制符。很明显公开,包,子类,同一个类,
private应该这么解释:只有本类中可以调用。所以它只能用在一个类内。
protect应该这么解释:只有本类、同一个包内的和继承本类的类可以调用。由于可以被继承本类的类调用,所以它也只能用在一个类内。
default应该这么解释:同一个包下都可以调用,对于外部类来说,就是可以直接创建,而对于一个成员变量来说,就是可以通过变量名来调用。
public应该这么解释:可以被不同包下的类调用,
其实可以这么思考,全部都是公共的,当你不想让你的类被其他包下的类调用,才将这个类设置为default,也就是将它锁起来了。但是同一个包下,你没有锁可以将类锁起来。
然后如果同一个包下,有类想要调用你的类的成员变量,但是你不想让他调用,就可以把成员变量,设置为protect或者private,但是其实并没有这样的递进关系。

如果你是一个富翁,你有一栋别墅,你发现别墅外面有很多人想闯入你的别墅,于是你就建了一道围墙。这就是default。
default外部类,

另一个例子,和上面的例子无关,你有一栋别墅,也有人想闯进你的别墅,但是你很大方,不在乎他们进来花园采花采草,但是你并不想你的房子被他们闯入,所以你在门加了一道大铁门,开放花园但封闭你的房子。这就是public类中有protect和private变量和方法,但是只要类是public的,类中default的访问控制符是无效的,其他类可以通过实例来调用。

public外部类,

还有一个例子,你更大方了,你把你的房子都开放了,但是你给你的财宝加上了一个保险柜,只有你的儿子和你才有钥匙。
public外部类protect成员变量

大概就是上面那种意思。

你是一个富翁,你的房子(你的类),街坊领居(同一个包下的其他类)都可以进,但是外乡人进不进的来,由你决定(public/default)。
你的房子里,花园是能进来的人都能看的(类中public成员变量),你的房子只有你和你的儿子还有邻居可以进去default),你的卧室只有你和你的儿子可以进去(protect),你的保险箱只有你自己可以打开(private)。

外乡人只能看到public,你的邻居可以看到default和public,你的儿子可以看到
protect、default和public,你四个都可以看到。

27、内部类的方法中使用this.调用内部类中被覆盖后的成员变量。使用外部类类名.this.调用外部类被覆盖后的成员变量。内部类在堆区中不仅只有成员变量,默认还有一个指向外部类的引用变量。

28、使用外部类创建内部类。创建一个继承内部类的类的实例,并且调用父类的构造器。

29、匿名内部类必须继承一个父类或实现一个接口,但最多只能继承一个父类或实现一个接口。我的疑问是,可以不继承或者不实现吗?可以继承多个或者实现多个吗?
不能,匿名内部类本身就是直接用父类或者接口直接写的,没有给继承或者实现留下位置,没地方写extends或者implements

30、215页疑惑,接口确实可以写成匿名内部类,其实就像是有一个类实现了接口,不过名字直接用接口的,实际上是一个新类。

31、不理解匿名内部类。被匿名内部类访问的局部变量必须使用final修饰。虽然不用显式使用,但是也要遵守一次赋值以后不能重新赋值。那么实例变量和类变量要这样吗?不用,实例变量和类变量并不受这个规则制约

32、lambda语法,形参列表+箭头+代码块。lambda表达式实际上将会被当成一个“任意类型”的对象。到底需要当成何种类型的对象,这取决于运行环境的需要。
lambda表达式要结合函数式接口使用。
lambda表达式只能实现一个方法,因此它只能为只有一个抽象方法的接口(函数式接口)创建对象。只要求形参列表相同。

33、注释是什么?222 ,注释是后面的内容 @NotNull这类的东西

34、方法引用和构造器引用要记忆一下。
方法引用就是当lambda方法,只有行的时候的极简写法。222页有详细对应。要自己练习一下。练过了

35、了解通过定义类的方法来实现枚举227。

36、枚举类默认继承java.lang.Enum类,所以不能显式继承其他父类。尝试使用枚举类

37、switch和枚举类结合用法,228

38、尝试创建枚举类实例。还是不够理解枚举类,230

39、疑惑232,final和abstract不能同时使用,所以抽象枚举类可以创建子类,而非抽象枚举类,自动用final修饰,不能创建子类。

40、为什么,数据库连接和网络IO会被说成物理资源,和堆内存中的对象有什么区别吗?

41、垃圾回收机制233,

42、当某个对象被其他类的类变量引用时,只有该类被销毁后,该对象才会进入可恢复状态;当某个对象被其他对象的实例变量引用时,只有当该对象被销毁后,该对象才会进入可恢复状态;再补充一句:当某个对象被其他类的局部变量引用时,只有该局部变量所在的栈被销毁时,或者该局部变量被设置为null时,该对象才会进入可恢复状态。

43、runtime是什么?234,运行时环境。

44、finalize()是Object类的方法?是的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

细水长流cpu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值