类
类构造方法
构造方法构造方法与类名 必须 相同 并且没有返回值;
可以指定参数;
只能在对象实例化的时候调用;
当没有指定构造方法时, 系统会 自动添加无参 的构造方法;
当有指定构造方法,无论是否有参、无参的构造方法,都 不会自动添加 无参的构造方法;
一个类中可以有多个构造方法;
在一个构造方法中只能调用一个构造方法, 比如 有参构造函数内, 只能调用一个构造函数 ,比如 默认构造方法。
对象实例化
对象实例化的过程分为两部分
1. 声明对象
类名 对象名,在栈中开辟一个空间
2. 实例化对象
new 构造方法(),在堆开辟一个空间
通过 = 赋值运算, 类名 对象名 = new 构造方法(),将栈中的内存空间指向堆中的地址。
this
this 在类中就是代表 当前对象,可以通过 this 关键字完成当前对象的成员属性、成员方法和构造方法的调用。
使用: 当在定义类中的方法时,如果需要调用该类对象,就可以使用 this 来表示这个对象。简单来说,在类内部使用了本类对象,都用 this 表示。
this面向对象的三大特征
面向对象的三大特征:继承、封装、多态
封装
将类的某些信息隐藏在类内部,不允许外部程序直接访问;
通过该类提供的方法来实现对隐藏信息的操作访问;
简单来说就是:隐藏对象的信息,留出访问的接口。
优点
封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问;
要访问该类的代码和数据,必须通过严格的接口控制;
封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段;
适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。
Java 实现封装的步骤
封装1. 修改属性的可见性, 设置为 private,只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏;
2. 创建 getter/setter 方法, 设置为 public 用于属性的读,用于对私有属性的访问;
3. 在 getter/setter 方法中加入属性控制语句,对属性值的合法性判断;
static
静态成员、类成员
类共享对象,所有类公用一个;类加载时产生,类销毁时释放,声明周期长;
使用 类名.静态成员(推荐) 或者 对象.静态成员
注意
在成员方法中,可以直接访问类中静态成员;
静态方法中 不能 直接访问同一个类中的 非静态成员(方法和属性),只能直接调用同一个类中的静态成员,只能通过对象实例化(重新 new 一个)后,对象.成员方法的方式访问;
静态方法中不能使用 this;
继承
继承一种类与类之间的关系;
使用已存在的类的定义作为基础建立新类;
新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类地某些功能,只能全部继承;
继承地实现 extends 关键字
注意
继承后的初始化顺序
父类静态成员 ----》 子类静态成员 ----》父类对象构造 ----》 子类对象构造
父类的构造不允许被继承,不允许被重写,但是会影响子类对象的实例化过程;
其中,子类构造的过程中如果没有显示的调用,一定 会默认调用父类 无参 构造方法,但是可以时候 super() 选择调用父类的构造方法, super 必须放在子类构造方法有效代码的 第一行。
super 代表 父类的引用,访问父类的成员方法 可以使用 super.方法名();访问父类的属性,可以使用 super.属性名称;访问父类的构造方法,可以使用 super()。
this 和 super
this 当前类对象的引用
访问 当前类 的 成员方法、成员属性、构造方法(使用方式this()),不能在静态方法中使用;
super 父类对象的引用
访问 父类 的 成员方法、成员属性、构造方法(使用方式super()),不能在静态方法 中使用;
构造方法调用时,super 和 this 不能同时出现。
方法重写 和 方法重载
方法重写:在满足继承关系的子类中,方法名、参数格式、顺序、返回值可以是子类 类型(与父类兼容 );访问修饰符的限定范围大于等于父类方法;
方法重载:在同一个类中,方法名相同,参数个数、顺序、类型不同;返回值类型、范文修饰符不做限定。
Object 类
Object 类是所有类的父类;一个类没有使用 extends 关键字明确标识继承关系,则默认继承 Object 类(包括数组);Java 中的每个类都可以使用 Object 中定义的方法。
final
当一个类 不希望有子类继承 的时候,或者类中的方法 不允许被子类重写(可以正常被子类继承使用),可以使用 final 关键字;
final 修饰 方法内的局部变量 只要在具体使用之前进行赋值即可,一旦赋值 不允许被修改;
如果修饰类中 成员属性 赋值过程:1 定义的时候直接初始化; 2 构造方法中赋值;3 构造代码块中赋值。
总结
对于基本数据类型 的变量,初始赋值之后不能修改;
对于 引用类型 的变量,初始化之后不能再指向另一个对象,但是对象的内容是可以改变的;
修饰类表示不允许被继承;
修饰方法表示不允许被子类重写(可以被继承);
修饰变量表示不允许修改;
可配合 static 使用, 表示静态的不允许修改的信息,比如 配置信息;
public final class 类名{
public final void 方法名(){}
}
多态
允许不同类的对象对同一消息做出不同的响应;
编译时多态:设计时多态,方法重载
运行时多态:程序运行时动态决定调用哪个方法(Java中的多态)
多态必要条件:满足继承关系;父类引用指向之类对象
向上类型转换(Upcast): 将子类型转换为父类型;
- 隐式/自动类型转换,是小类型到大类型的转换;
比如 Animal dog = new Dog(); // Dog 类是 Animal 类的子类
子类的对象可以赋值给父类的对象;
注意:1 当一个子类对象向上转型父类类型以后,就被当成父类的对象,所能调用的方法会减少,只能调用子类重写父类的方法以及父类派生的方法(如set, get 方法),而不能调用子类独有的方法;
2 父类中的静态方法是不允许被子类重写的。
向下类型转换(Downcast): 将父类型转换为子类型;
- 强制类型转换,是大类型到小类型;
比如 Animal a = new Dog();
Dog d = (Dog)a;
向下转型之后,可以调用子类自己独特的方法;
注意: 兄弟类之间不能进行强制类型转换;
通过 instanceof 运算符,来解决引用对象的类型,避免类型转换的安全性问题,提高代码的强壮性。
抽象类 和 抽象方法
应用场景
某个父类只是限定其子类应该包含怎样的方法,但不需要准确知道这些子类如何实现这些方法;
关键字 abstract
public abstract class XX {
抽象方法: 不允许包含方法体;子类中需要重写父类的抽象方法,否则子类也是抽象类
public abstract void XX ();
}
注意:这个类不允许实例化,可以通过向上转型,指向子类实例;
子类如果没有重写父类所有的抽象方法,则也要定义为抽象类;
抽象方法所在的类一定是抽象类;
抽象类中可以没有抽象方法。
接口 interface
Java 只支持单继承,如果一个类型中需要兼容多种类型特征该如何解决,多个不同类型具有相同特征该如何解决?
这就是 接口存在的意义:
接口定义了某一批类所需要遵守的规范;
接口不关心这些类的内部数据,也不关心这些类里方法的实现细节,它只规定这些类里必须提供某些方法;
接口访问修饰符 public
public interface 接口名{
接口中抽象方法可以不写 abstract 关键字,访问修饰符默认public;当类实现接口,需要去实现接口中的所有抽象方法,否则需要将该类设置为抽象类;
接口中可以包含常量,默认修饰符 public static final
类型 变量名称= 值;
public void 方法名()
默认方法 default 可以带方法体, 类可以不用是实现这个方法 JDK 1.8后新增
可以在实现类中重写,并可以通过接口引用的调用
default void 方法名(){ // code ....}
静态方法 static 可以带方法体, 类可以不用是实现这个方法 JDK 1.8后新增
不可以在实现类中重写,可以通过接口名.调用
static void 方法名(){ }
}
public class 类名 extends 父类 implements 接口1,接口2......{}
接口也可以实现继承,并且可以继承多个父接口;实现接口的类如果不能实现所有接口中待重写的方法,则必须设置为抽象类;
public interface 子接口 extends 父接口1,父接口2{ }
内部类
成员内部类
成员内部类静态内部类
静态内部类 静态内部类方法内部类
方法内部类匿名内部类
匿名内部类也就是没有名字的内部类, 它将 类的定义与类的创建 放在了一起完成,正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写;
使用匿名内部类还有一个前提条件:必须继承一个父类或实现一个接口;
适用场景
只用到类的一个实例;
类在定义后马上用到;
给类命名并不会导致代码更容易被理解;
抽象类的 匿名内部类只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现,最常用的情况就是在多线程的实现上,因为要实现多线程必须继承 Thread 类或是 实现 Runnable 接口。
接口式的匿名内部类上面的代码看似 实例化一个接口,事实上是 实现了一个接口的匿名类,而且 只能实现一个接口。
网友评论