构造方法
每个类都有构造方法(构造器)。如果没有显式的为类定义构造方法,Java编译器将会为该类提供一个默认的无参构造方法(public 类名(){})。 构造方法是在实例化类的时候调用执行的。 构造方法与方法类似,就是构造方法名字必须和类名一致而且没有返回值类型。
修饰符 类名(){
//构造方法代码
}
无参构造:就是不带参数的构造方法。 有参构造:带有参数的构造方法。
提示:以下是本篇文章正文内容,下面案例可供参考
对象的创建
使用new关键字来创建对象,用变量类型和变量名接收其返回值(该类的实例化对象)。 类名 变量名 = new 构造方法;
使用new关键字创建对象的时候,除了分配内存空间外,它还会给创建好的对象进行默认的初始化以及对类中对应构造器的调用。
内存分配:new出来的对象都会被放到堆内存中,其接收的变量实际为对应堆内存的地址。 默认初始化:对类中的成员变量进行初始化。
封装
一句话:属性私有,get set 在面向对象的程序设计方法中,封装是一种“隐藏”的方式。
我们在设计程序的时候,一定要追求“高内聚,低耦合”。
高内聚:就是类的内部数据操作细节自己完成,不允许外部干涉。 低耦合:只是暴露方法供外部使用。 在Java中,我们一般都是设置类属性的访问权限对其进行封装,一般设置为private,再提供其属性public的getter和setter方法供外部类对其属性的操作。
比如下面的学生类:
public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age < 0 || age > 150) {
this.age = 20;
} else {
this.age = age;
}
}
}
这个学生类中,博主将所有的成员变量都设置为private私有的,外部不能直接对其进行操作,但是提供了它们的getter方法来获取成员变量的数据,提供了它们的setter方法来设置成员变量的值。博主在设置年龄的方法中添加了检查年龄是否合法的代码,这样就能很好的避免设置的数据不合法的情况。
继承
继承的本质是对某一批类的抽象,从而实现对现实直接更好的建模,继承是Java面向对象编程的一个基础,可通过继承来创建分等级层次的类。
继承就是子类继承父类的行为和特征,使得子类实例化对象具有父类的能被继承的属性和方法,使得子类具有与父类相同的行为和特征。
extends是Java的一个关键字,表示继承。使用如下:
calss 子类 extends 父类{
}
super和this
super:
super使用前提,该类是某个类的子类,它只能在继承的条件下使用。 super代表父类对象的引用。 super调用父类的构造方法时,其语句必须是子类构造器中的第一句。 super关键字只能出现在子类的方法或者构造器中。
this:
this代表调用者本身的对象,它使用在类的方法或者构造器中。 super和this区别:
super和this区别:
super | this |
---|
只能在继承条件下才能使用 | 没有继承时也能使用 | 代表父类对象的引用 | 代表本类对象的引用 | super():父类的构造 | this():本类的构造 |
注意
- 在子类构造器中使用super调用父类的构造方法时,
super(); 必须放在子类构造器语句的第一条。 - 当我们在子类构造器中未使用super显式调用父类构造方法时,Java解释器会隐式的调用父类的无参构造器,如果父类没有无参构造,这时就需要我们显式的添加父类构造器。
- 子类加载的时候,会先将父类实例化(即先调用父类的构造器),然后再实例化自身(调用自己的构造器)。
方法重写 重写是子类对父类中允许访问的方法重新实现的过程,其方法名和参数列表都不能改变(即外壳不变,内核重写),方法重写的前提是继承。
方法重写的规则:
- 参数列表和方法名必须与被重写的方法一致。
- 返回值类型与被重写方法的返回值可以不同,但必须是父类返回值的派生类。
- 访问权限不能比父类中被重写方法的访问权限更低(权限问题可查看博主关于修饰符的文章)。
- 子类只能重写父类的成员方法。
- 子类不能重写声明为
final 的父类方法。 - 父类中声明为
static 的方法不能被子类重写,但是子类可以再次声明该方法。 - 子类重写的方法可以抛出的异常范围不能大于父类被重写方法抛出的异常。
重写就是为了满足子类对父类方法的扩充或者改变。 **重写与重载**
重写 | 重载 |
---|
需要有继承关系的子类中实现 | 任意类 | 参数列表与被重写方法一致 | 参数列表与被重载方法不一致 | 返回值可与被重写方法返回值不一致,但是其返回值类型必须是父类方法返回值的派生类 | 返回值可以与被重载方法不同,但不能只是与被重载方法的返回值不一致 | //该类隐式的继承了Object类
public class Person {
public Person() {
}
public void print() {
System.out.println("Person方法");
}
}
public class Student extends Person {
public Student() {
}
@Override
public void print() {
System.out.println("Student方法");
}
public void print(String name){
System.out.println(name);
}
public void test(){
super.print();
this.print();
}
}
多态
一句话:父类的引用指向子类的对象 多态就是同一个方法可以根据发送对象的不同采取多种不同的行为方式。一个对象的实际类型是确定的,但是它能指向的引用类型有很多,它能够被它的父类(直接父类和间接父类)所接收。
多态存在的条件:
- 有继承关系。
- 子类重写父类方法。
- 父类引用指向子类对象。
public class Application {
public static void main(String[] args) {
Person s1 = new Student();
s1.print();
}
}
我们在测试类中可以看到,创建了一个学生对象,但是我们采用了其父类类型接收其引用,这就是子类对象指向父类引用。我们在子类中重写了父类的print方法,所以s1.print()执行的是子类的方法。如果父类中没有此方法,s1.print();会报错,编译不通过。如果子类中没有重写该方法,运行时就会执行父类的方法,则不能体现出多态。
这里就能用“编译看左边,运行看右边”来解释:
- 编译看左边:
编译时,Java编译器会检查接收对象(左边的Person s1)是否有该方法(print()),如果没有,则编译不通过。 - 运行看右边:
运行时,JVM会运行实际创建对象(右边的new Student())的方法,如果子类无该方法,则调用父类的方法。
多态是方法的多态,属性没有多态。 instanceof instanceof:运算符; instanceof是Java保留的关键字。它的作用是检测它左边的对象是否是它右边的类的实例,如果是,则返回true,如果不是,则返回false。
Person的另一个Teacher子类:
public class Teacher extends Person {
@Override
public void print() {
System.out.println("Teacher的方法");
}
}
Person s1 = new Student();
System.out.println(s1 instanceof Student);
System.out.println(s1 instanceof MathStudent);
System.out.println(s1 instanceof Teacher);
System.out.println(s1 instanceof Person);
System.out.println(s1 instanceof Object);
instanceof关键字,用于判断一个左边的实例对象是否是右边的类。
- 如果实例对象不能转化为右边的类对象,则编译不通过(两者无关)。
- 如果实例对象能够转化为右边的类对象,并且其真实对象(new时候的类型)不是右边的类或者子类,则返回false(非直系亲戚)。
- 如果实例对象能够转化为右边的类对象,并且其真实对象是右边的类或者是右边类的子类,则返回true(直系亲戚)。
引用类型转换 在Java中,我们也能对引用类型进行转换,当然这种转换是需要条件的,引用类型转换之间的类必须存在父子关系,才能编译通过。
引用类型和基本数据类型类似,高到低需要强制转换,低到高则能自动转换。这里的高类型就是“辈分”高的类型。
- 如果将一个类对象转换为其父类类型,则可以自动转换。
- 如果将一个类对象装换为其子类类型,运行时出现转化异常(java.lang.ClassCastException)。
- 如果一个类对象转换为与其不相关的类类型,编译不通过。
比如上图: Student类对象能在它所属的那条直线上(Object<–Person<–Student<–MathStudent)随意转换,但是它转换为MathStudent时运行会出错。它就不能转换为与其不在同一条直线上的类型,比如它转换为Teacher类型时编译就会出错。
抽象类
abstract:抽取; 在Java中,abstract表示抽象。 如果一个类被abstract所修饰,这个类就是一个抽象类。 如果一个方法被abstract所修饰,这个方法就是一个抽象方法,而且抽象方法是没有方法体的。
public abstract class Action {
public abstract void doSomething();
}
- 抽象类中可以没有抽象方法,但是包含抽象方法的类必须是抽象类。
- 抽象类不能使用new关键字类创建对象,抽象类的创建就是为了让子类继承(抽象类可以采用匿名实现,在创建对象的时候,实现它的方法即可)。
Action action = new Action() {
@Override
public void doSomething() {
}
};
- 抽象方法没有方法体,它就是用来让子类实现。
- 子类继承抽象类,那么必须要实现父类中所有未实现的抽象方法,否则该子类也必须是抽象类。
抽象类,可以将类的共同行为做一个再次的抽象,再由具体的实现类去实现其具体的行为,相当于约束,使用这类约束,就可以在一定程度上提高开发效率。
接口
interface:接口; 在Java中,使用interface关键字来定义接口。 接口就是规范,其中定义的就是一组规范,可以理解为其中的方法全部都是抽象的方法,接口中的方法都没有方法体,接口存在的意义就是供类去实现,实现类必须实现接口中的所有方法,除非实现类是一个抽象类,或者实现类是该接口的子接口。 注意
- 接口中的方法都是抽象方法,都没有方法体。
- 接口中的方法不添加修饰符时,默认修饰符为
public abstract 。 - 接口中的方法修饰符要么不写,要么写为
public abstract ,不然会出现错误(我们编写接口时,一般都不会为其方法添加修饰符)。
总结
大概就是上面这一些了,这个是属于java基础内容的的前面一部分,之后有了时间再继续往后面整理。如有错误之处,还望指出!
|