不可变对象:一旦对象被创建并初始化后,内部的状态数据就会保持不变
根本原因:
String类是被final修饰,并且内部得大部分属性都是final修饰得,除了字段hash是通过字符串内容计算并缓存起来的。这样的行为让String类无法被扩展,内部属性也无法被修改。
例如 :String a = "string1";
String b = "string2";
String b = a ;
System.out.println(a + "," + b);
此时的输出结果为 string1,string2,可以知道, String b = a ;
该语句并没有使b字符串发生改变
(1)overloading是一个类中多态性的一种表现,让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型。
(2)重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同,也可以不同。无法以返回值类型作为重载函数的区别标准。
(1) 父类与子类之间的多态性,对父类的函数进行重新定义。即在子类中定义某方法与其父类有相同的名称和参数。
(2)若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。
同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是多态性。简单的说:就是用基类的引用指向子类的对象。
比如有一个父类superClass,它有2个子类subClass1,subClass2。superClass有一个方法 func(),两个子类都重写了这个方法。那么我们可以定义一个superClass的引用obj,让它指向一个子类的对象,比如superClass obj = new subClass1();那么我们调用obj.func()方法时候,会进行动态绑定,也就是obj它的实际类型的func()方法,即subClass1的func()方法。同样你写superClass obj = new subClass2();obj.func()其实调用的是subClass2的func()方法。这种由于子类重写父类方法,然后用父类引用指向子类对象,调用方法时候会进行动态绑定,这就是多态。多态对程序的扩展具有非常大的作用,比如你要再有一个subClass3,你需要改动的东西会少很多。
多态的作用:
链接地址
封装继承多态
封装的优点
良好的封装能够减少耦合。
类内部的结构可以自由修改。
可以对成员变量进行更精确的控制。
隐藏信息,实现细节。
java 封装,说白了就是将一大坨公共通用的实现逻辑玩意,装到一个盒子里(class),出入口都在这个盒子上。你要用就将这个盒子拿来用,连接出入口,就能用了,不用就可以直接扔,对你代码没什么影响。
对程序员来说,使用封装的目的:
1.偷懒,辛苦一次,后面都能少敲很多代码,增强了代码得复用性
2.简化代码,看起来更容易懂
3.隐藏核心实现逻辑代码,简化外部逻辑,并且不让其他人修改,jar 都这么干
4.一对一,一个功能就只为这个功能服务;避免头发绳子一块用,导致最后一团糟
抽象类:
抽象方法必须用abstract关键字进行修饰。如果一个类含有抽象方法,则称这个类为抽象类,抽象类必须在类前用abstract关键字修饰。因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象。
抽象类可以拥有成员变量和普通的成员方法。
抽象类和普通类的主要有三点区别:
1)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法), 缺省情况下默认为public。
2)抽象类不能用来创建对象;
3)如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。
接口:
接口中的变量会被隐式地指定为public static final变量,并且只能是public static final变量,用private修饰会报编译错误,而方法会被隐式地指定为public abstract方法且只能是public abstract方法,用其他关键字,比如private、protected、static、 final等修饰会报编译错误,并且接口中所有的方法不能有具体的实现,也就是说,接口中的方法必须都是抽象方法。
抽象类和接口的区别:
语法层面上的区别:
1)一个类只能继承一个抽象类,而一个类却可以实现多个接口;
2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
4)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
5)抽象类的抽象方法可以是public,protected,default类型,而接口的方法只能是public。
设计层面上的区别:
1)抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括 属性、行为,但是接口却是对类局部(行为)进行抽象。 继承是一个 "是不是"的关系,而 接口 实现则是 "有没有"的关系。
2)设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。
为什么重写了equals方法就要重写hashcode
(没有吃透,难点)
帖子链接:https://blog.csdn.net/xl_1803/article/details/80445481
https://blog.csdn.net/qq_28051453/article/details/52701171(较为全面)
解释:
我们知道判断的时候先根据hashcode进行的判断,相同的情况下再根据equals()方法进行判断。如果只重写了equals方法,而不重写hashcode的方法,会造成hashcode的值不同,而equals()方法判断出来的结果为true。
在Java中的一些容器中,不允许有两个完全相同的对象,插入的时候,如果判断相同则会进行覆盖。这时候如果只重写了equals()的方法,而不重写hashcode的方法,Object中hashcode是根据对象的存储地址转换而形成的一个哈希值。这时候就有可能因为没有重写hashcode方法,造成相同的对象散列到不同的位置而造成对象的不能覆盖的问题。
现在有两个Student对象:
Student s1=new Student(“小明”,18);
Student s2=new Student(“小明”,18);
此时s1.equals(s2)一定返回true
假如只重写equals而不重写hashcode,那么Student类的hashcode方法就是Object默认的hashcode方法,由于默认的hashcode方法是根据对象的内存地址经哈希算法得来的,显然此时s1!=s2,故两者的hashcode不一定相等。
然而重写了equals,且s1.equals(s2)返回true,根据hashcode的规则,两个对象相等其哈希值一定相等,所以矛盾就产生了,因此重写equals一定要重写hashcode,而且从Student类重写后的hashcode方法中可以看出,重写后返回的新的哈希值与Student的两个属性有关。
为什么重写了equals方法就要重写hashcode
(没有吃透)
链接:https://www.jianshu.com/p/9be58ee20dee
三种获取Class对象的方式:(参考:https://www.cnblogs.com/Grand-Jon/p/10041859.html)
方式一:Object类中的getClass()方法
方式二:通过对象静态属性 .class来获取对应的Class对象
方式三:只要通过给定类的字符串名称就可以获取该类,更为拓展,forName
setAccessible 方法
链接:https://www.cnblogs.com/huaranmeng/p/12790752.html
setAccessible
为AccessibleObject
类中的一个方法,是它是 Field、 Method 和 Constructor 类的公共超类。这个特性是为调试、 持久存储和相似机制提供的。
因而想访问 Field、 Method 和 Constructor 的私有对象,均需 setAccessible
。
什么是深复制浅复制
链接:https://www.cnblogs.com/xingzc/p/9646923.html
1、浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝。
2、深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。
链接:https://www.cnblogs.com/leeego-123/p/10995975.html
静态代理:
1.可以做到在不修改目标对象的功能前提下,对目标功能扩展.
2.缺点:
如何解决静态代理中的缺点呢?答案是可以使用动态代理方式
动态代理:
1.代理对象,不需要实现接口
2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
3.动态代理也叫做:JDK代理,接口代理
上面的静态代理和动态代理模式都是要求目标对象是实现一个接口的目标对象,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候就可以使用以目标对象子类的方式类实现代理,这种方法就叫做:Cglib代理
try catch finaly
异常