java-面向对象高级阶
继承
继承格式
class 父类{
}
class 子类 extends 父类{
}
- 继承是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法, 或子类从弗雷继承方法,使得子类具有父类相同的行为
- 继承限制:
- java中只有单继承,多重继承 (继承爷爷的性质),没有多继承
super:
-
通过super,可以访问父类的构造方法
-
在继承时,子类默认使用父类无参的构造方法
-
如果父类没有无参的构造方法则需要使用super()调用
class 父类{
}
class 子类 extends 父类{}
-
-
通过super,可以访问父类的属性
-
通过super,可以访问父类的方法
方法重写
- 参数列表必须完全和被重写的方法相同
- 返回值类型必须完全与被重写的方法的返回值类型一直
- 访问权限不能比父类中被重写的方法的访问权限低,
- 父类的成员方法只能被他的子类重写
- 声明为static和private的方法不能被重写,但是能够再次声明
class Work{
public void say() {
System.out.println("I gnna work");
}
}
class myWork extends Work{
public void say() {
System.out.println("I gnna study");
}
}
方法重写 和重载的区别
- 发生位置
- 重载:一个类中
- 重写:父子类中
- 参数列表限制
- 重载:必须不同、
- 重写:类型、数目 必须相同
- 访问权限:
- 重载:与访问权限无关(各种重载的方法随意设置权限)
- 重写:子类的访问权限必须 不小于 父类的访问权限
- 返回值:
- 重载:与返回值类型无关
- 重写:返回值类型必须一致
- 异常处理:
- 重载:与异常处理无关
- 重写:异常范围可以更小,但是不能抛出新的异常
final关键字
- final用于修饰属性 变量
- 变量成为常量,无法再对其赋值
- 常量的命名规范 由一个或多个单词形成,单词与单词之间必须使用下划线隔开,单词中所有的字母大写
- final修饰的局部变量,只能赋值一次(可先声明后赋值)
- final修饰成员属性,必须在声明的时候赋值
- 用于修饰类
- final修饰的类,不能被继承
- 用于修饰方法
- final修饰的方法不能被子类重写
抽象类
抽象类必须使用 abstract class 声明
一个抽象类中可以没有抽象方法。抽象方法必须写在抽象类或接口中
抽象类中可以有一些具体实现的方法
格式:
abstract class 类名{ //抽象类
}
抽象方法:
-
只声明未实现的方法称为抽象方法( 未实现指的是:没有{}方法体)
-
抽象方法必须使用abstrct关键字声明
abstract class 类名{
public abstract void 方法名(); // abstract 返回值类型 必须有
}
在抽象类使用的规则:
- 抽象类本身不能进行实例化的操作,即不能使用 new关键字来完成
- 一个抽象类必须被子类所继承,被继承的子类如果不是抽象类,则必须重写抽象类中的全部抽象方法
- 抽象类不能使用final声明
- 抽象类可以有构造方法,而且子类对象实例化时候的流程与普通类继承是一样的,都是先调用父类中的构造方法(默认无参),之后再调用子类知己的构造方法。
抽象类和普通类的区别
- 抽象类只能使用 public 或 procted 修饰(如果父类是 private修饰,那么子类无法继承,也无法实现其抽象方法),缺省 默认为 public
接口
-
如果一个类中全部的方法都是抽象方法,全部的属性 都是全局常量,那么此时就可以将这个类定义成接口
interface 接口名称{
全局常量;
抽象方法;
} -
接口中可以省略 public abstract
多态
- 就是对象的多种表现形式
多态的体现:
- 子类就是父类的一种形态
- 方法的重载 和 重写 就是多态的一种, 只不过是方法的多态 (相同方法名的多种形体)
- 重载:一个类中方法的多态性体现
- 重写: 子父类中方法的多态性体现
Object 类
- 如果在创建类的时候没有声明要继承的类,那么java就默认他继承Object类
- Object 的toString类
- 类Object 的toString方法返回一个字符串,该字符串由对象为实例的类的名称,符号字符“@”以及对象的哈希码的无符号十六进制表示形式组成。
- 换句话说,此方法返回一个 值等于 getClass().getName() + “@”+ Integer.toHexString(hashCode())
- 当我们使用Syso打印对象的时候,就是在调用toString()方法,可以查看println底层源码
- 我们可以重写 toString方法
== 与equals
-
==
- 用于基本数据类型的比较
- 判断引用的是否指向同一块内存地址
-
object 底层源码 的 equals 方法,是用的 == ,所以如果想实现比较其内容的话,要根据需求重写 equals方法
public boolean equals(Object obj) {
return (this == obj);
} -
equals,重写时需要满足一下条件(理解即可)
- 自反性 :对于任何非空的参考值x , x.equals(x)应该返回true 。
- 它是对称的 :对于任何非空引用值x和y , x.equals(y)应该返回true当且仅当y.equals(x)回报true 。
- 传递性 :对于任何非空引用值x , y和z ,如果x.equals(y)回报true个y.equals(z)回报true ,然后x.equals(z)应该返回true 。
- 它是一致的 :对于任何非空引用值x和y ,多次调用x.equals(y)始终返回true或始终返回false ,前提是未修改对象上的equals比较中使用的信息。
- 对于任何非空的参考值x , x.equals(null)应该返回false 。
-
快捷键生成equals 方法 shift+ alt+s 选择:Generate hashCode() and equals
//重写equals代码 public boolean equals(Object o) { if(this == o) { //判断两者内存地址是否一致 return true; } if(o==null) { //判断 o 对象 是否为 空 return false; } if( (o instanceof Persons) ){ Persons p2 = (Persons)o; if(this.name.equals(p2.name) && this.age == p2.age) { return true; } } return false; }
-
String 作为一个基本数据类型来使用
String s1 = “java”;
String s2 = “java”;System.out.println(s1==s2); //true System.out.println(s1.equals(s2)); //true why? 在此处程序员把String 作为一个基本的数据类型来使用 如果String缓冲池内不存在与其指定值相同的String对象,那么此时虚拟机将为此创建新的String对象,并存放在String缓冲池内。 如果String缓冲池内存在与其指定值相同的String对象,那么此时虚拟机将不为此创建新的String对象,而直接返回已存在的String对象的引用。
JVM把内存划分成两种:一种是栈内存,一种是堆内存。
①在函数中定义的一些基本类型的变量和对象的引用变量(变量名)都在函数的栈内存中分配。
②当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用
内部类:(不重要)
- 在java中,可以将一个类定义在另一个类里面或者一个方法里边
- 内部类一般包括:
-
成员内部类:
- 成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)
- 注意:当成员内部类拥有和外部类同名的成员变量或者方法是,会发生隐藏现象,默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以 外部类.this.成员变量 外部类.this.成员方法
- 外部类使用成员内部类
Outter outter = new Outter();
Outter.Inner inner = outter.new Inner();
-
局部内部类
- 是定义在一个方法或者一个作用域里面的类,他和成员内部类的区别在于
- 局部内部类就像是 方法里面的一个局部变量,不能有public protected、private 以及static修饰
-
匿名内部类:没有名字,在创建时只能用一次
- 匿名内部类的使用规范
- 使用匿名内部类时,我们必须继承一个类或者一个借口,但是两者不可兼得,同时也只能继承一个类或者接口
- 匿名内部类中不能有构造方法
- 匿名内部类为局部内部类的一种, so局部内部类的限制同样对匿名内部类生效
- 匿名内部类不能是抽象的,他必须要实现接口的所有抽象方法
- 只能访问final修饰的局部变量 内部类会被单独编译成一个字节码文件,为了保证内部类 和 外边的值一致,限制了变量的值不可更改
- 匿名内部类的使用规范
-
public class Demo1 {
public static void main(String[] args) {
// 创建了一个Human 接口的实现类,并new了一个对象
// 匿名内部类
Human p = new Human() {
public void say() {
System.out.println("匿名内部类");
}
};
haha(p);
}
public static void haha(Human p) {
}
}
- 静态内部类
包装类:
在Java中有一个设计的原则“一切皆对象”,那么这样一来Java中的一些基本的数据类型,就完全不符合于这种设计思 想,因为Java中的八种基本数据类型并不是引用数据类型,所以Java中为了解决这样的问题,引入了八种基本数据类型 的包装类
|序号| 基本数据类型| 包装类
1 int Integer
2 char Character
3 float Float
4 double Double
5 boolean Boolean
6 byte Byte
7 short Short
8 long Long
- 8种包装类,可以将基本数据类型按照类的形式进行操作
- 可分为两大种类型:(Ctrl+T 可以查看类的结构)
- Number: Interage \ Short \ Long \ Double \ Float \ Byte 都是Number的子类
- Object:Character、Boolean 都是Object的直接子类
// 包装类的学习:
// 手动装箱
Integer num = new Integer(200); // 删除线,指此操作已经过时
// 手动拆箱
int a = num.intValue();
System.out.println("包装类拆箱结果为:"+a);
// 自动装箱
Integer num1 = 200;
// 自动拆箱
int b = num1;
字符串转换:
-
使用包装类可以讲一个字符串变为指定的基本数据类型,一般在接收输入数据时使用较多
System.out.println(“请输入内容”);
String text = scanner.next();
System.out.println(“字符拼接”+text+1); //string + int 实现的效果是字符串的拼接int num = Integer.parseInt(text); //此处 num 为int型 System.out.println("?:"+num+1); //因为前边有 字符串类型,所以会自动将num、1转换成string类型 System.out.println(num+1);
可变参数:
-
一个方法中定完了参数,则在带哦用时必须传入与其一一对应的参数,但是在jdk1.5之后提供了新的功能,可以根据需要自动传入任意个数的参数
-
注意:可变参数只能出现在参数列表的最后
public static int sum(int...nums) { int n =0; for(int i=0;i<nums.length;i++) { n+=nums[i]; } return n; } System.out.println(sum(1)); System.out.println(sum(1,2));
递归
- 递归在数学与科学计算机科学中,是种方法的定义中使用方法自身。也就是说,递归算法是一种直接或者间接