面向对象
java是面向对象语言,这里的对象是现实世界的抽象,java程序是人写出来的,需要遵从人的思维方式,让人易于理解,只有这样,才能让这个语言推广开来。
面向对象的三大原则是:封装、继承、多态
封装:
封装在文件中,封装在类中,封装在方法中。使用合理隐藏,合理暴露的原则。目的就是提高代码的复用性。
// 封装的哲学思维:合理隐藏,合理暴露。
// 封装最初的目的:提高代码的安全性和复用性,组件化。
// 封装的步骤:
// 1.成员变量应该私有。用private修饰,只能在本类中直接访问。
// 2.提供成套的getter和setter方法暴露成员变量的取值和赋值。
//封装实际上已经成为了Java的代码规范,即使代码毫无意义我们还是要这样写。
class Person{
String name;
int age;
static String address;
public void eat(){
//封装在方法中
}
public static String getName(){
}
}
封装在文件中:就是我们写的java文件。如:Person.java
封装在类中:Person.java文件中,类后面的大括号,就是我们封装在类中的东西,这些东西概括就是方法和属性。
方法和属性根据修饰符和名称,有再次细分,用静态static修饰的方法和属性属于类,不用static修饰的属于实例对象。
封装在类中的五大成分:
修饰符 class 类名{
// 1.成员变量(Field): 描述类或者对象的属性信息的。
// 2.成员方法(Method): 描述类或者对象的行为信息的。
// 3.构造器(Constructor): 初始化一个对象返回。
// 4.代码块
// 5.内部类
}
类中有且仅有这五种成分,否则代码报错!
注:构造器:和类名一样的函数叫构造器函数,类加载会默认一个无参构造器。但是如果写了一个构造器函数,就不会再赠送这个无参构造器。
构造器:
格式:修饰符 类名(形参列表){
}
作用:初始化类的一个对象返回。
构造器的分类:无参数构造器,有参数构造器。
构造器的注意点:一个类默认自带一个无参数构造器,但是如果写了有参数构造器那么
默认的无参数构造器就消失了,此时如果还需要用无参数构造器就需要自己重新写一个。
构造器初始化对象的格式:
类名 对象名称 = new 构造器;
Student s = new Student();
无参数构造器的作用:初始化一个类的对象(使用对象的默认值初始化)返回。
有参数构造器的作用:初始化一个类的对象(可以在初始化对象的时候为对象赋值)返回。
3. 封装在方法中:我们平时写的逻辑代码就写在这里。
继承extends
为什么是extends,而不是extend。因为继承父类,会继承他所有的方法和属性,继承这么多,当然得用复数形式extends。
extends是单根继承,意思是一个类只能extends一个class类,不能多个,也不同extends A extends B …这样写。
继承的好用是方便代码的复用。
多态:
多态针对的是实例对象。实例对象中的属性和方法在编译器不能确定,只能在运行期才能确定。
有争议的观点(拓展):
子类是否可以继承父类的私有成员(私有成员变量,私有成员方法)?
– 我认为子类是可以继承父类的私有成员的,只是不能直接访问而已。
– 以后可以暴力去访问继承自父类的私有成员~~~
子类是否可以继承父类的静态成员?
– 我认为子类是不能继承父类的静态成员的,
– 子类只是可以访问父类的静态成员,父类的静态成员只有一份可以被子类共享访问。
共享并非继承。
this关键字
this关键字作用:指向当前实例对象,用在构造器和非静态方法中。
super
代表了父类的引用,用于子类访问父类的变量和方法。
static
对于成员变量和成员方法,通过有无static修饰符,判断变量和方法属于类还是属于实例。属于类,必定属于实例。
注意,有static修饰的成员方法和成员变量,属于类,用[类名].[方法名]调用。不建议用实例对象调用。这样方便区分这个方法属于类还是属于实例。
被static修饰的成员变量和成员方法属于类,放在静态区,所有实例对象都可以访问。没有static修饰的成员变量和成员方法属于实例对象。
1.当 static
修饰成员变量或者成员方法时,该变量称为静态变量,该方法称为静态方法。该类的每个对象都共享同一个类的静态变量和静态方法。任何对象都可以更改该静态变量的值或者访问静态方法。但是不推荐这种方式去访问。因为静态变量或者静态方法直接通过类名访问即可,完全没有必要用对象去访问。
2.无static修饰的成员变量或者成员方法,称为实例变量,实例方法,实例变量和实例方法必须创建类的对象,然后通过对象来访问。
3.static修饰的成员属于类,会存储在静态区,是随着类的加载而加载的,且只加载一次,所以只有一份,节省内存。存储于一块固定的内存区域(静态区),所以,可以直接被类名调用。它优先于对象存在,所以,可以被所有对象共享。
4.无static修饰的成员,是属于对象,对象有多少个,他们就会出现多少份。所以必须由对象调用。
方法重写@override
子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现。
* @Override:注解,重写注解校验!
* 这个注解标记的方法,就说明这个方法必须是重写父类的方法,否则编译阶段报错。
* 建议重写都加上这个注解,一方面可以提高代码的可读性,一方面可以防止重写出错!
加上后的子类代码形式如下:
public class Cat extends Animal {
// 声明不变,重新实现
// 方法名称与父类全部一样,只是方法体中的功能重写写了!
@Override
public void cry(){
System.out.println(“我们一起学猫叫,喵喵喵!喵的非常好听!”);
}
}
子类继承父类,子类感觉父类方法不好用,自己重新实现父类的方法。父类的静态方法和静态变量都不可以被重写
具体要求:
1.子类重写方法的名称和形参列表必须与父类被重写方法一样。
2.子类重写方法的返回值类型申明要么与父类一样,要么比父类方法返回值类型范围更小。
3.子类重写方法的修饰符权限应该与父类被重写方法的修饰符权限相同或者更大。
4.子类重写方法申明抛出的异常应该与父类被重写方法申明抛出的异常一样或者范围更小!
方法重载
方法名相同,参数不同,返回类型不同
构造器
修饰符 类名(形参列表) {
// 构造体代码,执行代码
}
通过构造器可以返回一个类对象,构造器可以帮助我们把对象的数据(属性和行为)初始化好。
属性可以通过构造器设置值,也可以通过setter设置值。
构造器会默认执行super()方法,根据参数去匹配调用父类构造器
子类构造器默认一定会先调用父类的无参数构造器再执行自己。
this代表了当前对象的引用(继承中指代子类对象):
this.子类成员变量。
this.子类成员方法。
this(…):可以根据参数匹配访问本类其他构造器。(还没有学习)
super代表了父类对象的引用(继承中指代了父类对象空间)
super.父类成员变量。
super.父类的成员方法。
super(…):可以根据参数匹配访问父类的构造器。
拓展:this(…)根据参数匹配访问本类其他构造器。
注意:
this(…)借用本类其他构造器。
super(…)调用父类的构造器。
this(…)和super(…)必须放在构造器的第一行,否则报错!
所以this(…)和super(…)不能同时出现在构造器中!!!
class Student{
private String name ;
private int age ;
private String schoolName ;
public Student() {
}
public Student(String name , int age){
// 借用兄弟构造器的功能!
this(name , age , “黑马”);
}
public Student(String name, int age, String schoolName) {
this.name = name;
this.age = age;
this.schoolName = schoolName;
}
}