抽象类与接口的的区别
抽象类:用关键字abstract修饰,存在抽象方法的类一定是抽象类,但抽象类不一定有抽象方法,抽象类可以存在成员变量,也可以存在构造器用于对属性的初始化,但是抽象类不能被实例化,继承抽象类的子类可以将父类的所有抽象方法实现,也可以选择性的实现而将子类继续设定为抽象方法,
接口:用关键字interface声明,接口中只存在抽象方法,并且存在的属性全部为public static final类型,且不存在构造器,一个子类可以实现多个接口,用implements关键字实现接口,要将接口中的全部方法实现,接口也可以存在继承关系,子类要将实现的接口的全部方法实现,包括该接口的父类接口中的方法
为什么要有get,set方法
set和get方法是面向对象编程中常用的种封装方式,用于对类的属性进行访问和修改。它们的用如下:
1.封装数据:set方法用于设置属性的值,get方法用于获取属性的值。通过使用set和get方法,可以将属性的访问限制在类的内部,避免直接对属性进行操作,提高了代码的安全性和可维护性。
2.控制访问权限:set和get方法可以对属性的访问进行控制。例如,可以在set方法中添加一些条件判断,对传入的值进行验证和处理,确保属性值的有效性。同时,get方法可以对属性的返回值进行处理,例如格式化输出或者进行计算。
3.实现数据封装:通过使用set和get方法,可以将属性的实现细节隐藏起来,只暴露必要的接口给外部使用。这样可以提高代码的封装性,减少对属性的直接访问,降低了类与类之间的耦合度。
4.可以添加额外逻辑:在set和get方法中,可以添加一些额外的逻辑操作。例如,在set方法中可以触发事件或者通知其他对象,实现更复杂的业务逻辑。
总结,set和get方法提供了一种良好的封装方式,使得类的属性访问更加安全、可控,并且提供了更好的代码封装性和可维护性。
向上转型与向下转型
1.向上转型:
父类 : class Fruit {}
子类 : class Apple extends Fruit{}
创建向上转型对象 fruit ;
Fruit fruit = new Apple();
Apple 向上转型为父类
如果 Apple 中有重写父类方法,fruit 对象默认调用子类中重写方法
注意 :
fruit 可以直接访问子类重写方法。
fruit 不能直接访问子类私有方法、子类所有属性。
fruit 可以通过重写方法调用子类私有方法和属性
fruit 重写方法中调用方法和属性顺序 : 子类 -> 父类
其他 : 关于重写的返回值类:如果方法的返回类型是 void和基本数据类型,则返回值重写时不可修改。但是如果方法的返回值是引用类型,重写时是可以返回该引用类型的子类的。
2.向下转型
注意 : 只有向上转型过的对象才能向下转型
向下转型为恢复子类所有功能。
Apple apple = (Apple) fruit;
有参构造与无参构造的存在情况
有参构造函数和无参构造函数是面向对象编程中常用的两种构造函数形式。
无参构造函数:指没有参数的构造函数,也称为默认构造函数。它在创建对象时不需要传入任何参数,可以直接使用默认的属性值进行对象的初始化。无参构造函数通常用于创建对象时不需要额外信息的情况。
有参构造函数:指带有参数的构造函数。它在创建对象时需要传入相应的参数,用于初始化对象的属性值。有参构造函数可以根据传入的参数不同,灵活地初始化对象的属性。有参构造函数通常用于创建对象时需要额外信息的情况。
有参构造函数和无参构造函数可以同时存在于一个类中,也可以只存在其中一种。如果一个类中没有定义任何构造函数,编译器会自动生成一个默认的无参构造函数。如果在类中定义了有参构造函数,但没有定义无参构造函数,那么在创建对象时必须显式地传入参数,否则会编译
错误。
总结:
无参构造函数:不需要传入参数,使用默认的属性值进行对象初始化。
有参构造函数:需要传入参数,根据参数的不同进行对象初始化。
在平时写代码的过程中,要么无参构造和有参构造都写,要么都不写。
方法的重写与重载
方法的重写是子类重新定义父类中已经存在的方法,方法名称、参数列表和返回类型必须相同,实现多态。
方法的重载是在同一个类中定义多个具有相同名称但参数列表不同的方法,根据参数类型和数量确定调用哪个方法。
重写与重载的区别:
1.方法重载是发生在同一个类中,而方法重写是发生在子类和父类之间;
2.方法重载要求:方法名相同、但参数类型或参数个数不同;方法重写:方法名、返回值类型和参数列表都相同
3.方法重载是用于相同的方法名称不同的问题;方法重写是因为父类的某个方法不满足子类的要求,所以对该方法进行重写
比较字符串用==还是equal
”==”是用来比较字符串的引用地址,而equals()才是比较字符串的值。两个值相同的字符串用”==”比较结果有可能是false,而用equals()则一定为true。除非两个字符串是同一个new出来的对象,不然比较字符串值是否相同应该要用equals()。
==是运算符,equal是方法
总结:
1.java基本类型(short,int,long,byte,char,float,double,boolean)
比较基本类型,只能用==,不能用equal,这里的==比较的是两个变量的值
2.比较包装类型
==比较的是内存地址,因为a和b是new出来的,是两个不同的对象,所以地址肯定是不同的,而equal比较的是值
3.比较String类型
==比较的是内存地址,equal比较的是值
4.比较对象
==和equal比较的都是内存地址,因为equal没有被重写,没有被重写的equal都是object的equal方法
创建字符串的2种方式的区别
1.采用直接赋值的方式赋值
eg: String str1 = "abc";
采用这种方法去创建字符串时,JVM会在方法区的字符串常量池中寻找这个字符串是否存在,如果存在则不去创建,让创建的对象直接引用其在字符串常量池中的地址;如果不存在则在字符串常量池中创建这个字符串并且返回这个字符串在常量池中的地址。
2.采用new关键字新建一个字符串对象
eg: String str2 = new String("abc");
采用new关键字新建一个字符串对象时,JVM首先在字符串池中查找有没有"abc"这个字符串如果有,则不在池中再去创建"abc"这个对象了,直接在堆中创建一个"abc"字符串对象,然后将堆中的这个"abc"对象的地址返回赋给引用str,这样,str就指向了堆中创建的这个"abc"字符串对象;如果没有,则首先在字符串池中创建一个"abc"字符串对象,然后再在堆中创建一个"abc"字符串对象,然后将堆中这个"abc"字符串对象的地址返回赋给str引用,这样,str指向了堆中创建的这个"abc"字符串对象。
注意:这种方法本质是在堆区引用字符串常量池中的地址,每次new的对象,在堆上都会创建一个新的对象指向常量池。
这两种方法创建出的字符串虽然内容是一样的,但指向是不一样的。str1和str3直接指向的是常量池的地址,str2指向堆的地址。
总结:new创建出的对象指向均不相等,字符串的创建无论是哪种方式,都需要先在字符串常量池中寻找该字符串是否存在。
数组的动态初始化与静态初始化
数组的初始化:数组元素类型[] 数组名=new 数组元素类型[]{元素1,元素2.....} ;
数组的初始化: 数组元素类型[] 数组名={元素1,元素2.....} ;
foreach
使用 for each 循环来遍历数组或集合中的元素。for each 循环也被称为增强型 for 循环。
for each 循环的基本语法:
for (元素类型 变量名 : 数组或集合) {
// 执行循环体操作
}
for each遍历二维数组:
for(元素类型 [ ] 过渡一维数组名 : 二维数组名){
for(元素类型 变量名 : 过渡一维数组名){
// 执行循环体操作
}
}
Arrylist是否有序
ArrayList:(有序、可重复的)
创建集合:ArrayList 集合名=new ArrayList();
获取元素:get(int index)
替换元素:set(int index,Object element)
添加元素:add(添加一个元素) addAll(将指定集合中的所有元素都添加到当前集合中)
删除元素:remove(删除集合中的指点元素) removeAll(删除指定集合中的所有元素)
将集合元素顺序翻转:reverse(List list)
将集合元素按自然顺序排列:sort(List list)
判断是否包含元素:contains(判断集合中是否包含某个元素) containsAll(判断集合中是否包含指定集合中所有元素)
HashSet:(无序、不可重复)
key value重复问题
