目录
①ArrayList是list的主要实现类,Vector有很多缺点,不推荐使用。
重写(Override)与重载(Overload)的区别
Java确定一个方法的三要素:①调用者,类还是对象。②方法名。③ 形参列表。方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载主要发生在同一类的多个同名方法之间。重写主要发生在子类和父类的同名方法之间。
方法重载:在同一类中包含了两个或两个以上的方法,其方法名相同,但形参列表不同。重载要求两同一不同:同一个类中方法名相同,形参列表不同(参数的顺序,类型,个数不同)。至于方法的其他部分,如返回值类型、修饰符等,与方法重载无关。重载是让类以统一的方式处理不同类型数据的一种手段。重载是一个类中多态性的一种表现。
方法重写也叫方法覆盖,是一种子类包含与父类同名方法的现象。方法重写遵循“两同两小一大”的原则:“两同”指方法名相同,形参列表相同;“两小”指子类方法返回值类型应比父类方法返回值类型更小或相等,子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等。“一大”指子类方法的访问权限应比父类方法的访问权限更大或相等。有两点要注意:1、覆盖方法和被覆盖方法要么都是类方法,要么都是实例方法。2、如果父类方法是private权限,则该方法对子类方法是隐藏的,无法重写该方法。
接口和抽象类
抽象类是普通类上加abstract,是从多个具体类中抽象出来的父类。抽象类作用:当成父类来被继承。有抽象方法的类只能被定义为抽象类,抽象类中可以没有抽象方法。抽象类可以包含抽象方法,但不能用于创建实例。
接口是从多个相似类中抽象出来的规范,定义了多个类共同的公共行为。接口的好处:让规范和实现分离,降低各个模块的耦合性,为系统提供更好的扩展性和维护性。接口的主要用途:定义变量,可用于进行强制类型转换;调用接口中定义的常量;被其他类实现。接口只能继承接口不能继承类。
1、二者的区别:
①关键字。定义接口用interface,实现接口的关键字为implements,定义抽象类用abstract,继承抽象类的关键字为extends。
②继承和实现。一个类可以实现多个接口,但只能继承一个抽象类。接口可以继承多个接口。接口只能继承接口,不能继承类。接口支持多继承。
③构造器。抽象类可以有构造器。抽象类的构造器不能用于创建实例,主要用于被其子类调用,完成属于抽象类的初始化操作。接口没有构造器。
④成员变量和方法。接口的变量只能是静态常量,总是使用public static final修饰,只能在定义时指定默认值。接口的方法只能是抽象方法、类方法、默认方法。接口的抽象方法都是public abstract修饰,类方法都是public static修饰,默认方法都是default修饰。抽象类是普通类加abstract。所以抽象类的成员变量和方法的规则几乎与普通类相同,但多了一个抽象方法(用abstract修饰)。
⑤方法实现。接口中只能包含抽象方法、静态方法、默认方法,不能为普通方法提供方法实现。抽象类可以包含普通方法。
⑥main方法。抽象类可以有main方法并且可以运行它。接口没有main方法。
2、二者的共同点:
①都不能被实例化。他们都位于继承树的顶端,用于被其他类实现和继承。
②都可以包含抽象方法。实现接口或继承抽象类的普通子类都必须实现这些抽象方法。
3、接口的用途:
①定义变量,可用于强制类型转换。
②调用接口中定义的常量。
③被其他类实现。
4、抽象类必须要有抽象方法吗?
抽象类中是允许不包含抽象方法的。抽象类的特性并不是包含抽象方法,而是不允许实例化对象。如果想定义一个类不应该直接被使用,只能再次继承后才可以使用,这时就可以用抽象类了。
5、抽象类能使用final修饰吗?
不能。
定义抽象类就是让其他类继承的,如果定义为 final ,该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类。
面向对象的基本特征
封装:将对象的实现细节隐藏起来,然后通过一些共用的方法暴露该对象的功能。Java提供private、protected、public访问控制修饰符来实现良好的封装。
继承:是面向对象实现软件复用的重要手段,当子类继承父类后,子类作为一种特殊的父类,将直接获得父类的属性和方法,但不能获得父类的构造器。Java提供extends关键字来让子类继承父类。
多态:子类对象可以直接赋给父类变量,但运行时依然表现出子类的行为特征。Java的引用变量有编译时类型(声明变量时使用的类型)和运行时类型(实际赋给该变量的对象类型)。如果编译时类型和运行时类型不一致,就会出现多态。
String
1、Java的String类型为什么是不可变的
String类中的成员变量:
private final char value[];
private final int offset;
private final int count;
2、不可变的好处
因为字符串是不可变的,所以是多线程安全的,同一个字符串实例可以被多个线程共享。这样便不用因为线程安全问题而使用同步。字符串自己便是线程安全的。
3、比较两个字符串时使用“==”还是equals()方法?
当然是equals方法。==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符。equals方法是用于比较两个独立对象的内容是否相同。
如果一个类没有自己定义 equals 方法,它默认的 equals 方法(从 Object 类继承的)就是使用==操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals 和使用==会得到同样的结果,如果比较的是两个独立的对象则总返回 false。如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么就必须覆盖 equals方法,由你自己写代码来决定在什么情况即可认为两个对象的内容是相同的。
4、如何将字符串转化成int?
使用包装类Integer。Integer.valueOf("2");
5、为什么在Java中存储密码要使用char[],而不使用String。
因为String是不可变的,当String创建之后,就不会再改变了。而char[]是可变的,程序员在用完之后可以将其改变,不会留下任何原始数据。所以,在使用密码时,一般都是会用char数组。
6、如何将字符串用空白字符分割开
可以使用正则表达式来做到分割字符。“\s”代表空白字符” “, “\t”, “\r”, “\n”等等, String[] strArray = str.split("\\s+");
7、String常用方法
equals():字符串比较。
matches("正则表达式"):可以用这个方法加正则表达式来验证这个字符串是否有非法信息。
length():返回字符串长度。
indexOf():返回指定字符第一次出现的索引。
charAt():返回指定索引处的字符。
toLowerCase():将字符串转成小写字母。
toUpperCase():将字符串转成大写字符。
split():分割字符串,返回一个分割后的字符串数组。
substring():截取字符串。
replace():支持字符和字符串的替换。
replaceAll():基于正则表达式的字符串替换。
trim():去除字符串两端空白。
getBytes():返回字符串的 byte 类型数组。
8、Java中操作字符串都有哪些类?它们之间有什么区别?
Java中操作字符串的类有3个,String,StringBuilder,StringBuffer。在核心上字符串就是字符的数组,String、StingBuilder、StringBuffer的源代码中都有一个私有变量保存着字符数组。不同之处只在于性能和线程安全性问题。String的性能最差,StringBuilder的性能最好,StringBuffer相对StringBuilder慢一些。
String对象是不可变对象,所以性能最差。不可变对象的意思是对象的值是不可变的,你定义了一个String对象值为abc,就无法再改变值内容了,改变值内容其实是创建了一个新对象。
StringBuilder性能最好,但线程不安全.在StringBuilder内部管理一个字符数组来存储字符串内容,如果对字符串变更后的长度不大于字符数组长度,就直接在当前字符数组上进行操作;如果新的字符串长度超过数组长度的话,就用新创建的字符数组替换原有的字符数组,新字符数组的长度为当前字符数组的两倍,并将字符串内容写入到字符数组中。大多数情况下,都是在已经开辟的字符数组空间中进行内存操作,不会创建新的对象,性能得到极大提高。并且StringBuilder在设计的时候并不考虑多线程并发问题,因此代码更加精简,性能是最好的。
StringBuffer机制与StringBuilder基本一样,但性能略差,因为StringBuffer类的成员方法前面多了synchronized。StringBuffer相对StringBuilder性能差了一点点,但相应的对于多线程场景下,Stri