博主是某大厂的测试开发工程师,经历了校招和社招。以下是博主的吐血整理,全部学会一定能在各种招聘中披荆斩棘!手握多家大厂offer!
欢迎大家点个关注! 以后会更新高阶测试开发的路线和教程!
该文档的特点有:
1. 非常全面: 无论是java基础,JVM,数据结构,操作系统,计算机网络,Spring知识点,部分中间件,测试知识点,都有总结,涵盖阿里,百度,字节,美团的面试知识点。
2. 非常正确: 博主本硕都是CS专业,所有的知识点都来自专业的课本和知名博客。并且通过这份面经获得了多份offer.
3.标注重点: 目前市面上相关总结鱼目混杂,大家时间也很宝贵,所以每个地方都有标注重点!方便大家高效率学习相关知识点!
一、JAVA基础
java 是一种面向对象的语言,它对象中的类、对象、继承、封装、多态...
1.1 面向对象的理解
在我理解,面向对象是向现实世界模型的自然延伸,这是一种“万物皆对象”的编程思想。在现实生活中的任何物体都可以归为一类事物,而每一个个体都是一类事物的实例。面向对象的编程是以对象为中心,以消息为驱动,所以程序=对象+消息。
面向对象有三大特性,封装、继承和多态。
封装就是将一类事物的属性和行为抽象成一个类,使其属性私有化,行为公开化,提高了数据的隐秘性的同时,使代码模块化。这样做使得代码的复用性更高。
继承则是进一步将一类事物共有的属性和行为抽象成一个父类,而每一个子类是一个特殊的父类--有父类的行为和属性,也有自己特有的行为和属性。这样做扩展了已存在的代码块,进一步提高了代码的复用性。
如果说封装和继承是为了使代码重用,那么多态则是为了实现接口重用。多态的一大作用就是为了解耦--为了解除父子类继承的耦合度。如果说继承中父子类的关系式IS-A的关系,那么接口和实现类之之间的关系式HAS-A。简单来说,多态就是允许父类引用(或接口)指向子类(或实现类)对象。很多的设计模式都是基于面向对象的多态性设计的。
总结一下,如果说封装和继承是面向对象的基础,那么多态则是面向对象最精髓的理论。掌握多态必先了解接口,只有充分理解接口才能更好的应用多态。
1.2 JAVA不支持多继承
javare认为,一个物体的本质只能有一个。多继承是一种很少使用,并且很容易混淆的特性,所以Java语言就像删除操作符重载特性一样删除了多继承这种特性。
多继承指一个子类能同时继承于多个父类,从而同时拥有多个父类的特征,但缺点是显著的。
- 若子类继承的父类中拥有相同的成员变量,子类在引用该变量时将无法判别使用哪个父类的成员变量。(成员变量)
- 若一个子类继承的多个父类拥有相同方法,同时子类并未覆盖该方法(若覆盖,则直接使用子类中该方法),那么调用该方法时将无法确定调用哪个父类的方法。(成员方法)
1.3 标识符
在程序当中自己定义的内容:比如各种名字
-
命名规范:
软性建议- 类名规范:(大驼峰式)HelloWord
- 变量名规范:(小驼峰式)helloWord
1.4 常量
字符串常量:双引号引起来的字符串,叫做字符串常量
整数常量
浮点数常量
字符常量:单引号引起来的单个字符,叫做字符常量:'a','中'
布尔常量:只有两种true,false
空常量:null,代表没有任何数据
1.5 数据类型
基本数据类型
-
基本数据类型(4类8种):
- byte short int long float double char boolean(1,2,4,8,)
-
引用数据类型:类,
-
注意事项:字符 char,字符串String.
类型转换
-
强制类型转换(显示)
小的类型 小的变量名 = (小的类型) 范围大的数据
对byte/short/char三种类型来说,如果右侧赋值的数值没有超过范围,那么javac编译器将会自动隐含地为我们补上一个(byte)(short)(char)|,因为会提升为
int -
自动类型转换(隐式)
特点: 数据范围从小到大 大=小(long = int, float = long)(不然就会报错)
转换时的注意事项:
-
数据溢出,精度损失。
-
byte/short/char这三种类型都可以发生数学运算,例如加法“+”
char zifu1 = 'A'; //这是一个字符型变量,里面是大写字母A System.out.println(zifu1 +1); // 66,也就是大写字母A被当做65进行处理 -
byte/short/char这种类型在运算的时候,都会首先提升为int类型,然后再计算。
-
Boolean不能发生数据类型转换
ASCII码
48 -- '0'
65 -- 'A'
97 -- 'a'
运算符
-
算数运算符
四则运算:+ - * /取模:%注意事项:
- 一旦运算当中有不同类型的数据,那么结果将会是数据类型范围大的那种。
- 对于字符
char来说,+意味着int的相加,最终返回int - 对于字符串来说,
+意味着字符串的连接。 - String + int --- > String
-
数值运算符
-
赋值运算符
基本赋值运算符
=复合赋值运算符
+=-=....... -
比较运算符
-
逻辑运算符
&&||!&&:具有短路效果(False && B)B 是什么都无所谓,也不会执行。因为A已经是false了 -
三元运算符
数据类型变量名称 = 条件判断?表达式A:表达式B;
方法
-
方法名称的命名规则和变量一样,使用小驼峰。hello World
-
方法的结构:
修饰符返回值类型方法名称()
方法的重载(overload)
方法的重载(Overload):多个方法的名称一样,但是参数列表不一样。
方法重载与下列因素相关:
- 参数个数不同
- 参数类型不同
- 参数的多类型顺序不同
数组
两种常见的初始化方式:
-
动态初始化(指定长度)
int[] arrayA = new int[300]; -
静态初始化(指定内容)
int[] arrayB = new int[]{5, 10, 500};或者:
int[] arrayB = {5, 10, 500};
直接打印数组名称,得到的是数组对应的:内存地址哈希值
使用动态初始化数组的时候,其中的元素将会自动拥有一个默认值。规则如下: 如果是整数类型,那么默认为e;
如果是浮点类型,那么默认为e.e;
如果是字符类型,那么默认\u0000
如果是布尔类型,那么默认为false;
如果是引用类型,那么默认为nulL
长度: 数组.length
传参: 其实是地址的传递,传的是地址
返回值: 一个方法可以有0、1、多个参数;但是只能有0或者1个返回值,不能有多个返回值。 如果希望一个方法当中产生了多个结果数据进行返回,怎么办? 解决方案:使用一个数组作为返回值类型即可。
泛型
ArrayList:指定了类型。
泛型:也就是装在集合当中的所有元素,全都是统一的什么类型。 注意:泛型只能是引用类型,不能是基本类型。
String
创建字符串的3+1种方式
字符串的特点:
1.字符串的内容永不可变。【重点】
2.正是因为字符串不可改变,所以字符串是可以共享使用的。
3.字符串效果上相当于是char[]字符数组,但是底层原理是byte[]字节数组。
字符串常量池:
(JDK1.7之后,字符串常量池在堆中)
【解析:】
- 直接“”的字符串,存放在常量池当中。
- char[]=这一行代码,会在堆中开辟一块内存空间,新存储地址
- char[]转为String的时候会变成byte[]
常用方法:
public int length():
public String concat(String str):将当前字符串和参数字符串拼接成为返回值新的字符串。
public char charAt(int index):获取指定索引位置的单个字符。(索引从开始。)
public int indexof(String str):查找参数字符串在本字符串当中首次出现的索引位置,如果没有返回-1值。
public String substring(int index):截取从参数位置一直到字符串末尾,返回新字符串。
public String substring(int begin,int end):截取从begin开始,一直到end结束,中间的字符串。
备注:[begin,end),包含左边,不包含右边。
public char[] tocharArray():将当前字符串拆分成为字行数组作为返回值。
public bytel]getBytes():获得当前字符串底层的字节数组。
public String replace(CharSequence oldString,Charsequence newString):将所有出现的老字符串替换成为新的字符串,返回替换之后的结果新字符串。
分割子行串的方法:
public String[]split(String regex):按照参数的规则,将字符串切分成为若干部分。 (注意转移字符的使用)
1.6 equals:
System.out.printin(strl.equals(str2));//true
System.out.printin(str2.equals(str3));//true
System.out.printin(str3.equals("Hello"));//true
System.out.println("Hello".equals(str1));//true
equals的特点:
最好是常量.equals(变量),不要调到过来
System.out.println("Hello".equals(str1));//true 推荐 System.out.printin(str3.equals("Hello"));//true 不推荐
1.7 Static关键字
定义:
关键字修饰的数据,多个对象共享同一份数据
特点:
修饰成员变量:
修饰方法:方法不属于对象,是属于类的
注意事项:
-
对于静态方法来说,可以通过对象名进行调用,也可以直接通过类名称来调用。(推荐)类名称.方法名
-
无论是成员变量,还是成员方法。如果有了static,都推荐使用类名称进行调用。 静态变量:类名称,静态变量 静态方法:类名称.静态方法()
-
静态的方法不能访问非静态的成员变量。
-
静态的内容总是优于非静态的内容。
-
静态代码初始化:
5.1 当第一次用到本类时,静态代码块唯一执行一次(只一次) 静态内容总是优先于非静态,所以静态代更比构造方法先执行。
5.2 静态代码块
static { System.out.println("静态代码执行"); }
静态变量的内存图:
静态的变量存放在方法区的静态区
1.8 Arrays
定义:
java.util.Arrays是一个与数组相关的工具类,里面提供了大量静态方法,用来实现数组常见的操作。
使用方法:
# 将int数组转为String
String s = Arrays.toString(a);
# 字符串的排序
void sort();
Arrays.sort(a);
System.out.println(Arrays.toString(a));
[]:字符串括来的
{}:数组
sort注意事项:
- 如果是数值,sort默认按照升序从小到大
- 如果是字符串,sort默认按照字母升序
- 如果是自定义的类型,那么这个自定义的类需要有Comparable或者Comparator接口的支持。(今后学习)|
1.9 Math
常用方法:
public static double abs(double num):获取绝对值。
public static double ceil(double num):向上取整。
public static double floor(double num):向下取整。
public static double round(double num):四舍五入。
1.10 JDK5新特性
自动装箱--自动将基本数据类型, 变成对象 自动拆箱--自动将对象转成回基本数据类型
public static void method(){
//编译后 Integer i = Integer . value0f(10)
//value0f源码中new Intger()
Integer i = 10;
=i+ 1;//i还原回基本数据类型+1
System. out . println(i);
##1.11 反射
-
反射:框架设计的灵魂
-
框架:半成品软件。可以在框架的基础上进行软件开发,简化编码
-
反射:将类的各个组成部分封装为其他对象,这就是反射机制
反射技术:其实就是动态加载一个指定的类,并获取该类中的所有的内容。而且将字节码文件封装成对象,这样便于操作这些成员。简单说:反射技术可以对一个类进行解剖。
-
好处: 1.可以在程序运行过程中,操作这些对象。 2.可以解耦,提高程序的可扩展性。
-
获取class对象的方式:
-
Class. forName("全类名") :将字节码文件加载进内存,返回class对象
-
多用于配道文件,将类名定义在配试文件中。读取文件,加载类
-
类名.class :通过类名的后性class获取
- 多用于参数的传递
-
对象,getClass() : getClass()方法在object类中定义着。
- 多用于对象的获取字节码的方式
”结论: 同一个字节码文件(* .class)在一-次程序运行过程中, l只会被加载-次, 不论通过哪一种方式获取的Class对象都是同一 个。以上三种方法都是同一个返回结果。
-
相关面试题
1. JDK和JRE的区别
- JDK:Java Development Kit 的简称,java 开发工具包,提供了 java 的
开发环境和运行环境。 - JRE:Java Runtime Environment 的简称,java 运行环境,为 java 的
运行提供了所需环境。
2. ==和equals的区别
equals:
比较对象的地址是否相等,无论是基本数据类型还是引用数据类型。
只有String和integer的对象,是比较其值的大小。
==:
基本数据类型:比较的是存储的值是否相等
引用数据类型:比较的是对象的地址是否相等
java内存
在java中 ,把对象放在堆,把对象的引用放在栈。
str1 == str2: (引用)比较对象的地址是否相同false
str1 == str3: (引用)比较对象的地址是否相同false
str2 == str3: (引用)比较对象的地址是否相同true
str1.equals( str2): (string)比较对象的值是否相同true
str1.equals( str3): (string)比较对象的值是否相同true
str1.equals( str2): (string)比较对象的值是否相同true
baijiahao.baidu.com/s?id=165244…
3. 两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?
不对,两个对象的 hashCode()相同,equals()不一定 true。
4. final 在 java 中有什么作用?
- final 修饰的类叫最终类,该类不能被继承。
- final 修饰的方法不能被重写。
- final 修饰的变量叫常量,常量必须初始化,初始化之后值就不能被修改。
5. java 中的 Math.round(-1.5) 等于多少?
等于 -1,向上取整
6.基本数据类型:
byte,short,int ,long ,float, double,char, boolean
引用数据类型:
String 属于对象。
7. java 中操作字符串都有哪些类?它们之间有什么区别?
操作字符串的类有:String、StringBuffer、StringBuilder。
String 和 StringBuffer、StringBuilder 的区别在于
String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,
StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。
8. StringBuffer 和 StringBuilder 最大的区别在于**,
StringBuffer 是线程安全的,
而 StringBuilder 是非线程安全的(builder房子是不安全的),但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。
9.String str="i"与 String str=new String("i")一样吗?
不一样,因为内存的分配方式不一样。
String str="i"的方式,java 虚拟机会将其分配到常量池中;
String str=new String("i") 则会被分到堆内存中。
10. 如何将字符串反转?
使用 StringBuilder 或者 stringBuffer 的 reverse() 方法
## 面向对象
《Java编程思想》中提到“万物皆为对象”的概念。它将对象视为一种奇特的变量,它除了可以存储数据之外还可以对它自身进行操作。它能够直接反映现实生活中的事物,例如人、车、小鸟等,将其表示为程序中的对象。每个对象都具有各自的状态特征(也可以称为属性)及行为特征(方法),java就是通过对象之间行为的交互来解决问题的。
面向对象就是把构成问题的事物分解成一个个对象,建立对象不是为了实现一个步骤,而是为了描述某个事物在解决问题中的行为。
类是面向对象中的一个很重要的概念,因为类是很多个具有相同属性和行为特征的对象所抽象出来的,对象是类的一个实例。
类具有三个特性:封装、继承和多态。
- 封装:核心思想就是“隐藏细节”、“数据安全”,将对象不需要让外界访问的成员变量和方法私有化,只提供符合开发者意愿的公有方法来访问这些数据和逻辑,保证了数据的安全和程序的稳定。
- 继承:子类可以继承父类的属性和方法,并对其进行拓展。
- 多态:同一种类型的对象执行同一个方法时可以表现出不同的行为特征。通过继承的上下转型、接口的回调以及方法的重写和重载可以实现多态。
局部变量和成员变量:
-
定义的位置不一样【重点】 局部变量:在方法的内部 成员变量:在方法的外部,直接写在类当中
-
作用范围不一样【重点】 局部变量:只有方法当中才可以使用,出了方法就不能再用成员变量:整个类全都可以通用。
-
默认值不一样【重点】 局部变量:没有默认值,如果要想使用,必须手动进行赋值成员变量:如果没有赋值,会有默认值,规则和数组一样
-
内存的位置不一样(了解)局部变量:位于栈内存成员变量:位于堆内存
-
生命周期不一样(了解)层部变量:随着方法进栈而诞生,随着方法出栈而消失成员变量:随着对象创建而诞生,随着对象被垃圾回收而消失
-
this关键字当方法的局部变量和类的成员变量重名的时候,根据就近原则”,优先使用局部变量。
public void sayHello(String name){ System.out.println(name+",你好。我是“+this.name)这里面的name都是局部变量的name,不是类中的name
封装
- 方法就是一种封装
- 关键字private也是一种封装
一旦使用了private进行修饰,那么本类当中仍然可以随意访问。 但是!超出了本类范围之外就不能再直接访问了。
封装:就是隐藏对象的属性和实现细节,仅对外提供公共访问方式。
封装的好处:隐藏类的实现细节;让使用者只能通过程序员规定的方法来访问数据;可以方便的加入存取控制语句,限制不合理操作.
构造方法
注意事项:
- 构适方法的名称必须和所在的类名称完全一样,就连大小写也要一样
- 构造方法不要写返回值类型,连void都不写
- 构造方法不能return一个具体的返回值
- 如果没有编写任何构造方法,那么编译器将会默认赠送一个构造方法,没有参数、方法体什么事情都不做。
引用类型
Scanner类的功能:可以实现键盘输入数据,到程序当中。 引用类型的一般使用步骤:
- 导包 import 包:如巢需要使用的目标类,和当前类位于同一个包下,则可以省略导包语句不写。 只有java.Lang包下的内容不需要导包,其他的包都需要import语句。
- 创建
- 使用
键盘的输入
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
匿名对象:
只能用一次的对象,比如作为方法的参数
继承
访问变量
在父子类的继承关系当中,如果成员变量重名,则创建子类对象时,访问有两种方式: 直接通过子类对象访问成员变量: 等号左边是谁,就优先用谁,没有则向上找。 间接通过成员方法访问成员变量: 该方法属于谁,就优先用谁,没有则向上找。
this,super关键字
注意事项:
无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类的。|
继承的三个特点:
重写
重写(@Override)注解 重写概念:在继承关系当中,方法的名称一样,参数列表也一样。又叫覆盖,
重载概念:方法的名称一样,参数列表不一样。
注意事项:
-
子类方法的返回值必须【小于等于】父类方法的返回值范围。
-
子类方法的权限必须【大于等于】父类方法的权限修饰符。
小扩展提示:public>protected>(default)>private备注:(default)不是关键字default,而是什么都不写,留空。
super()
继承关系中,父子类构造方法的访间特点:
1. 子类构造方法当中有一个默认隐含的“super()周用,所以一定是先调用的父类构造,后执行的子类构造
2. 子类构造可以通过super关键字来调用父类重载构造。
3. super的父类构适调用,必须是子类构造方法的第一个语句。不能一个子类构造调用多次super构造。
构造方法访问构造方法(构造方法的重载):
在本类的构造方法中,访问本类的另一个构造方法。
A. this(.…)调用也必须是构造方法的第一个语句,唯一一个。 B. super和this两种构造调用,不能同时使用。
public Zi(){
super();
this(n:123);//本类的无参构造,调用本类的有参构造this(1,2);//错误写法!又有super又有this错误
super this内存图:
其中,
- 方法区会存在 super_class,继承父类的方法区内容
- 会存在super和this指针
- 堆中会创建父类内容。
抽象
接口是对行为的抽象,它是抽象方法的集合,利用接口可以达到API 和实现分离的目的。它不包含任何非常量的变量,同时没有方法实现。JDK1.8 后引入的default 后可以。用关键字implements 实现。
抽象类是不能实例化的类,用关键字abstract 修饰,其主要目的是代码重用。除了不能实例化,形式上和一般的 Java 类并没有太大区别,可以有一个或者多个抽象方法,也可以没有抽象方法。抽象类大多用于抽取相关 Java 类的共用方法实现或者是共同成员变量,然后通过继承的方式达到代码复用的目的。
创建
public abstract class Animal {
public abstract void eat(); #这里是没有具体实现的,直接是分号;结尾
}
使用
-
不能直接new一个抽象类的对象
-
必须继承使用
-
必须覆盖重写所有的抽象方法
public class Dog extends Animal { @Override public void eat() { }
注意事项
关于抽象类的使用,以下为语法上要注意的细节,虽然条目较多,但若理解了抽象的本质,无需死记硬背。
- 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
- 抽象类中,可以有构造方法,子类创建对象时,初始化父类成员使用的。
理解:子类的构造方法中,有默认的super,需要访问父类构造方法。
pub1icZi(){
//super(); # 父类方法默认执行
System.out.println(“子类构造方法执行“);
-
抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。
-
抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。
理解:假设不重写所有抽象方法,则类中可能包含抽象方法,那么创建对象后,调用抽象的方法,没有意义。
public abstract class Dog extends Animal { # 子类也是抽象类 @Override public void eat() { }
多态
多态的定义
多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,
因为在程序运行时才确定具体的类,这样,不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。多态性增强了软件的灵活性和扩展性。
多态的条件
继承、重写、向上转型。
继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将子类的对象赋给父类引用,只有这样该引用才能够具备技能调用父类的方法和子类的方法。
实现多态
重写、接口、抽象类和抽象方法:
通过重写、接口、抽象类和抽象方法实现
基于继承的实现机制主要表现在父类和继承该父类的一个或多个子类对某些方法的重写,多个子类对同一方法的重写可以表现出不同的行为。
基于接口的多态中,指向接口的引用必须是指定这实现了该接口的一个类的实例程序,在运行时,根据对象引用的实际类型来执行对应的方法。
定义:
对象具有多种形态
实际含义:父类引用指向子类对象
父类名称 对象名 = new 子类名称
接口名称 对象名 = new 实现类名称
使用
-
直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找。
用父类
-
间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找。
子类没有覆盖重写,就是父
子类如果覆盖重写,就是子
编译看左,运行看右。
个人口诀:一旦子重写了,就得用子;主要用父,父没有就是没有,不管子有没有
向上转型
对象的向上转型,其实就是多态写法:
父类引用指向子类对象
格式:父类名称对象名=new子类名称0:|Animal animal = new Cat0; 含义:右侧创建一个子类对象,把它当做父类来看待使用。创建了一只猫,当做动物石待,没问题。 注意事项:向上转型一定是安全的。从小范围转向了大范围,从小范围的猫,向上转换成为更大范围的动物。 类似于: double num=100;/∥正确,int-->double.自动类型转换。
向下转型
Zi zi = (Zi)fu;
zi.method();
对象的向下转型,其实是一个【还原】的动作。 格式:子类名称对象名=子类名称父类对:I
含义:将父类对象,【还原】成为本来的子类对象。;Animal animal =new Cat0;/
∥本来是猫,向上转型成为动物:Cat cat =(Cat)animal;
//本来是猫,已经械当做动物了,还原回来成为本来的猫注意事项:
a. 必须保证对象本来创建的时候,就是猫,才能向下转型成为猫。 b. 如果对象创建的时候本来不是猫,现在非要向下转型成为猫,就会报错。|
(原来是啥,你才能还原成啥!!)
多态的底层
多态的底层实现是动态绑定,即在运行时才把方法调用与方法实现关联起来。动态绑定涉及很多 JVM 的细节,全部写清楚需要很大篇幅,因此本文仅简单描述,后续会有其他文章就其中的细节一一分享。
静态绑定与动态绑定
JVM 的方法调用指令有五个,分别是:
invokestatic:调用静态方法;
invokespecial:调用实例构造器方法、私有方法和父类方法;
invokevirtual:调用虚方法;
invokeinterface:调用接口方法,运行时确定具体实现;
invokedynamic:运行时动态解析所引用的方法,然后再执行,用于支持动态类型语言。
权限修饰符
Java中有四种权限修饰符: public >protected >(default)>private
| - | public | protected | (default) | private- |
|---|---|---|---|---|
| 同一个类(我自己) | YES | YES | YES | YES |
| 同一个包(我邻居) | YES | YES | YES | NO |
| 不同包子类(我儿子) | YES | YES | NO | NO |
| 不同包非子类(陌生人) | YES | NO | NO | NO |
抽象类抽象方法
不需要,抽象类不一定非要有抽象方法。抽象方法不能有方法主体。格式如下
普通类和抽象类
- 普通类不能包含抽象方法,抽象类可以包含抽象方法。
- 抽象类不能直接实例化,普通类可以直接实例化。
- 定义抽象类就是让其他类继承的
接口和抽象类
-
实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。
-
构造函数:抽象类可以有构造函数;接口不能有。
-
main 方法:抽象类可以有 main 方法,并且我们能运行它;接口不能有 main 方法。
-
实现数量:只能继承一个抽象类,类可以实现很多个接口。
-
访问修饰符:抽象类中的方法可以是任意访问修饰符 public private protected 。 接口中的方法默认使用 public 修饰;
-
相同点: 1)都不能被实例化。 2)接口的实现类或抽象类的 子类都只有实现了 接口或抽象类中方法后才能实例化。 不同点: 1)在成员变量上,
抽象类可以有变量、常量、构造方法、有抽象方法也可以有非抽象方法;
接口只能有常量、抽象方法。 2)在使用上,
接口侧重于实现封装(接口隐藏内部实现),
抽象类侧重于提取共性。
3)在继承上,接口可以继承多个父类,抽象类只能继承一个父类。 4)抽象类可以有构造器,抽象方法可以有public、protected和default这些修饰符;
接口不能有构造器,接口方法默认修饰符是public,不可以使用其它修饰符。
接口
定义
public interface XXX{}
接口定义方法:
备注:换成了关键字interface之后,编译生成的字节码文件仍然是:.java->.class。 如果是Java7,那么接口中可以包含的内容有:
-
常量
-
抽象方法
public abstract 返回值类型方法名称(参数列表);注意事项: 1.接口当中的抽象方法,修饰符必须是两个固定的关键字:public abstract 2.这两个关键字修饰符,可以选择性地省略。(今天刚学,所以不推荐。) public abstract void method(){ }
如果是Java8,还可以额外包含有:
-
默认方法
//带有默认的方法体 //无需使用接口的类实现该方法 //接受默认重写 public default void method5(){ } // 默认方法中有重复的代码部分 public default void method1(){ System.out.println("这是默认的方法1"); System.out.println("AAAAA"); System.out.println("BBBBB"); System.out.println("CCCCC"); } public default void method2(){ System.out.println("这是默认的方法1"); System.out.println("AAAAA"); System.out.println("BBBBB"); System.out.println("CCCCC"); } // 把共同的部分抽取出来 public default void method(){ System.out.println("AAAAA"); System.out.println("BBBBB"); System.out.println("CCCCC"); }//只能本接口中的抽象方法用,不能被其他类继承实现
4.静态方法
//直接通过接口的名称调用方法
MyInterfaceAbstract.methodStatic();
如果是Java9,还可以额外包含有:
- 私有方法
接口定义常量:
接口当中也可以定义“成员变量”,但是必须使用public static final三个关键字进行修饰。 从效果上看,这其实就是接口的【常量】。 格式: public static final 数据类型常量名称。数据值;备注: 一旦使用final关键字进行修饰,说明不可改变。 注意事项:
- 接口当中的常量,可以省略public static final,注意:不写也照样是这样。
- 接口当中的常量,必须进行赋值;不能不赋值。
接口名称.常量
总结:
注意事项:
使用接口的时候,需要注意:
-
接口是没有静态代码块或者构造方法的。
-
一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。
-
如果实现类所实现的多个接囗当中,存在重复的抽象方法,那么只需要覆盖重写一次即可
-
对多个接口当中冲突的默认方法进行了覆盖重写,比如两个静态方法名字一样了。就得重写了。
-
一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法
类>接口
接口的继承
1.类与类之间是单继承的。直接父类只有一个。 2.类与接口之间是多实现的。一个类可以实现多个接口。 3.接口与接口之间是多继承的。 注意事项: 1g多个父接口当中的抽象方法如果重复,梁关系。 2.多个父接口当中的默认方法如果重复,么子接口必须进行默认方法的覆盖重写,【而且带着defoult关键字】
String
字符串是常量,值在创建之后不能修改。
StringBuilder
字符出缓冲区,可以提高字符出的操作效率(石成一个长度可以变化的字符出)底层也是一个数组,但是没有械final修饰,可以改变长度bytel]value=new byte[16]:
相比String内存占用少,效率高
构造方法:
有参数的构造方法和无参数的构造方法
public class Demoe1StringBuilder{
public static void main(String[]args){
//空参数构造方法
StringBuilder bul-new StringBuilder(); System.out.println("bul:"+bu1);//bu1:""
//常字符串的构造方法
StringBuilder bu2=new StringBuilder("abc"); System.out.println("bu2:"+bu2);//bu2:abc
常用方法:
append():可以添加任意的对象
//链式编程
s.append(1).append("hdi").append(true);
System.out.println(s);
StringBuilder和String可以相互转换:
string->5tringButlder:可以使用StringButlder的构造方法stringButlder(string str)构造一个字符串生成器,并初始化为指定的字符串内容。 StringButlder->5tring:可以使用StringBuilder中的tostring方法public string tostring():将当前stringButLder对象转换为string对象。
包装类
定义:
基本数据类型,使用起来非常方便,但是没有对应的方法来操作这些基本类型的数据可以使用一个类,把基本类型的数据装起来,在类中定义一些方法,这个类叫做包装类我们可以使用类中的方法来操作这些基本类型的数据
装箱与拆箱:
装箱:
把基本类型的数据,包装到包装类中(基本类型的数据->包装类)
构造方法: Integer(int value) 构造一个新分配的 Integer对象,它表示指定的int值。 Integer(String s)构造一个新分配的 Integer 对象,它表示 string 参数所指示的int值。传递的字符串,必须是基本类型的字符串,否则会抛出异常“100”正确“a”她异常
静态方法: static Integer valueof(int i) 返回一个表示指定的int 值的Integer实例。 static Integer valueof(String s) 返回保存指定的 String的值的 Integer对象。
拆箱:
在包装类中职出基本类型的数据(包装类-)基本类型的数据)成员方法: int intvglue() 以int 类型返回该Integer的值。