对面向对象的三大特征:继承、封装、多态
继承(extends)
继承可以实现代码的重用。
如果新定义一个Student类,发现已经有Person类包含了我们需要的属性和方法,那么Student类只需要继承Person类即可拥有Person类的属性和方法。
class Person {
String name;
int height;
public void rest(){
System.out.println("休息一会!");
}
}
class Student extends Person {//Student 继承了Person类的所有方法和特征
String major; //专业
public Student(String name,int height,String major) {
//天然拥有父类的属性
this.name = name;
this.height = height;
this.major = major;
}
1.父类也称作超类、基类、派生类等。
2.Java中只有单继承,没有像C++那样的多继承。多继承会引起混乱,使得继承链过于复杂,系统难于维护。
3.Java中类没有多继承,接口有多继承。
4.子类继承父类,可以得到父类的全部属性和方法 (除了父类的构造方法),但不见得可以直接访问(比如,父类私有的属性和方法)。
5.如果定义一个类时,没有调用extends,则它的父类是:java.lang.Object。
三种方法防止某个类被继承:
- 存取控制:将某个类不标记为公有,则只有同一个包中的类可以继承它;
- 使用final修饰符,表示它是继承树的末端;
- 让类只拥有private构造程序。
-
Object类是所有Java类的根基类,所有的Java对象都拥有Object类的属性和方法。未使用extends关键字指明父类则默认继承Object类。
-
instanceof是二元运算符,左边是对象,右边是类;当对象是右面类或子类所创建对象时,返回true;否则,返回false。
-
点击一个类,按contral+t 可以查看关系树。
方法的重写
在子类中重新定义父类的方法,在子类调用时优先调用重写的方法。
- 方法名,形参列表相同;
- 返回值类型和声明异常类型,子类小于等于父类;
- 访问权限,子类大于等于父类。
Object 中的toString方法会返回“类名+@+16进制的hashcode”
==和equals()方法
“==”比较双方是否相同,基本类型比较值是否相同,引用类型比较地址是否相同。
equals()是对象内容相等,在很多地方都会被重写。
super关键字
super是对直接父类对象的引用,可以用来访问被子类重写覆盖的方法和属性。
- 构造方法的第一句总是
super();
不论写不写。 - 属性/方法查找顺序:先当前类,再父类,直到Object类,没有则报错。
- 构造方法调用顺序:先上溯到Object类,再依次向下执行类的初始化块和构造方法,直到当前子类为止
抽象类
抽象类不能被实例化,必须被继承才能实例化。
抽象方法
封装
1.提高代码的安全性。
2. 提高代码的复用性。
3. “高内聚”:封装细节,便于修改内部代码,提高可维护性。
4. “低耦合”:简化外部调用,便于调用者使用,便于扩展和协作。
访问控制符:
- 子类无法使用父类私有的属性和方法
多态
多态指的是同一个方法调用,由于对象不同可能会有不同的行为。
- 多态是指方法的多态,属性没有多态;
- 多态存在的三个必要条件:继承,方法重写,父类引用指向子类对象;
- 用该父类引用调用子类重写的方法,就会出现多态。
- 没有多态的话很多地方会需要大量的重载
final关键字
- 类前加final,则该类不能被继承;
- 方法前加final,则该方法不能被重写,但是仍然可以重载;
- 变量前加final,则变量不能被改变;
抽象类和接口
包含抽象方法的类就是抽象类。通过abstract方法定义规范,要求子类必须定义具体实现。
- 抽象类父类没有实现,子类必须实现;
- 有抽象方法的类只能定义成抽象类;
- 抽象类不能实例化,不能用new来实例化抽象类;
- 抽象类可以包含属性、方法、构造方法。但是构造方法不能用来new实例,只能用来被子类调用;
- 抽象类只能用来被继承;
- 抽象方法必须被子类实现;
接口就是比“抽象类”还“抽象”的“抽象类”。
[访问修饰符] interface 接口名 [extends 父接口1,父接口2…] {
常量定义;
方法定义;
}
- 1.访问修饰符:只能是public或默认。
- 2.接口名:和类名采用相同命名机制。
- 3.extends:接口可以多继承。
- 4.接口中的属性只能是常量,总是:public static final 修饰。不写也是。
- 5.接口中的方法只能是:public abstract。 省略的话,也是public abstract。
- 接口中一般有大量注释。
子类实现时使用implements
,可以实现多个接口。
接口中定义静态方法和默认方法(JDK8以后)
- jdk8之前只能定义抽象方法;
- 默认方法
interface A {
default void moren(){
System.out.println("默认方法!");
}
可以对默认方法重写。
- 静态方法
可以在接口中直接定义静态方法的实现。这个静态方法直接从属于接口,可以通过接口名调用
内部类
内部类主要分为成员内部类(非静态内部类、静态内部类)、匿名内部类、局部内部类。
- 有非静态内部类对象则一定存在对应的外部类对象。
- 非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态内部类成员。
- 非静态内部类不能有静态方法、静态属性和静态初始化块。
内部类好处
- 内部类提供了更好的封装。只能让外部类直接访问,不允许同一个包中的其他类直接访问。
- 内部类可以直接访问外部类的私有属性,内部类被当成其外部类的成员。 但外部类不能访问内部类的内部属性。
- 接口只是解决了多重继承的部分问题,而内部类使得多重继承的解决方案变得更加完整。
内部类成员变量访问方法:
- 内部类里方法的局部变量:变量名。
- 内部类属性:this.变量名。
- 外部类属性:外部类名.this.变量名。
String类
- String类不可被继承;
- 初始化字符串时可用连接符,加号两边只要有一个是字符串,结果就是字符串;
直接写的字符串会被放在常量池里:
String str1 = "abc";
String str2 = new String("def");
String str3 = "abc";
String str4 = str2.intern();
String str5 = "def";
System.out.println(str1 == str3);// true
System.out.println(str2 == str4);// false,用equals()就是true
System.out.println(str4 == str5);// true
String类API文档阅读
常用方法:
public class StringTest1 {
public static void main(String[] args) {
String s1 = "core Java";
String s2 = "Core Java";
System.out.println(s1.charAt(3));//提取下标为3的字符
System.out.println(s2.length());//字符串的长度
System.out.println(s1.equals(s2));//比较两个字符串是否相等
System.out.println(s1.equalsIgnoreCase(s2));//比较两个字符串(忽略大小写)
System.out.println(s1.indexOf("Java"));//字符串s1中是否包含Java
System.out.println(s1.indexOf("apple"));//字符串s1中是否包含apple
String s = s1.replace(' ', '&');//将s1中的空格替换成&
System.out.println("result is :" + s);//s1不会变
}
}
public class StringTest2 {
public static void main(String[] args) {
String s = "";
String s1 = "How are you?";
System.out.println(s1.startsWith("How"));//是否以How开头
System.out.println(s1.endsWith("you"));//是否以you结尾
s = s1.substring(4);//提取子字符串:从下标为4的开始到字符串结尾为止
System.out.println(s);
s = s1.substring(4, 7);//提取子字符串:下标[4, 7) 不包括7
System.out.println(s);
s = s1.toLowerCase();//转小写
System.out.println(s);
s = s1.toUpperCase();//转大写
System.out.println(s);
String s2 = " How old are you!! ";
s = s2.trim();//去除字符串首尾的空格。注意:中间的空格不能去除
System.out.println(s);
System.out.println(s2);//因为String是不可变字符串,所以s2不变
}
}