1 抽象类
概述:
Java中可以定义没有方法体的方法,该方法由其子类来具体的实现。该没有方法体的方法我们称之为抽象方法,含有抽象方法的类我们称之为抽象类。
抽象类可以理解为是一个只有方法声明没有方法体的特殊类。
抽象方法结构:
修饰符 abstract 返回值 方法名(参数列表);
public abstract void eat();
特点:
1,通过JAVA关键字abstruct实现
2,可以修饰方法或者类
3,抽象类里可以没有抽象方法(由子类去实现)
4,如果类中有抽象方法,那该类必须定义为抽象类
5,子类继承了抽象类后,要么还是一个抽象类,要么把继承的抽象方法全部重写变成普通方法
6,多用于多态中
7,抽象类不可以被实例化,(不能被new)
package test.oop;
//测试抽象的特点
public class Test3_Abstract {
public static void main(String[] args) {
// Animal2 a = new Animal2(); //7,抽象类不能实例化
// Dog2 d = new Dog2();
// Animal2 a = new Dog2();
Animal2 a2 = new Cat2();
a2.eat();//父类的方法声明--父类的
a2.sleep();//父类的方法声明--子类的
}
}
//创建父类
//1,为什么产生父类?--为了提取子类的共性,提高父类代码的复用性
//2,怎么优化父类?--程序设计--父类有没有可以省略的功能--方法体可以省略
//3.2,如果类中存在抽象方法,那么加abstract关键字修饰抽象类
abstract class Animal2{
public void eat() {
System.out.println("父类吃");
}
// 3,如果方法体,写了也要被修改,那就可以省略不提供--没有方法体的方法--抽象方法
//3.1,加abstract关键字修饰成抽象方法
abstract public void sleep();//抽象方法只能被public protected修饰,包含子类
}
//创建子类
//4,子类继承父类后,父类如果被修饰成了抽象类,就继承了抽象方法,必须把子类修饰成抽象类
//4.1,子类abstract修饰
abstract class Dog2 extends Animal2{
}
//4.2,重写抽象方法
class Cat2 extends Animal2{
@Override//注解,作用是用来标志这个方法是一个重写方法
public void sleep() {
System.out.println("子类睡");
}
}
抽象类的构造方法:
package test.oop;
//测试抽象类的使用--构造方法
//总结:
//1,抽象类 里 有构造方法
//2,抽象类自己不能被实例化,仍然会提供构造方法,因为方便子类new
//3,抽象类的子类new时,会调用自己的构造方法,自己的第一行里有个super()可调用父类的构造方法
public class Test4_Abstract2 {
public static void main(String[] args) {
//2,先执行父类的构造方法,再执行自己的构造方法
Animal3 a = new Dog3();
Animal3 a2 = new Dog3(5);
}
}
//创建抽象类
abstract class Animal3{
//构造方法
//3,抽象类不能被实例化,为什么还要提供构造方法?--为了方便子类new
public Animal3() {
System.out.println("Animal3..无参构造");
}
}
class Dog3 extends Animal3{
public Dog3(){
super();//1,默认就存在,会主动找父类的无参构造
System.out.println("Dog3...无参构造");
}
public Dog3(int a){
super();//1,默认就存在,会主动找父类的无参构造
System.out.println("Dog3...含参构造"+a);
}
}
抽象类的成员变量:
1,抽象类里可以有变量,可以有常量,也可以被继承。
2,final里的值可以被继承,但是不能被修改。
抽象类的成员方法:
1,抽象类里可以全是抽象方法,也可以全是普通方法(目的不让外界实例化),也可以同时存在抽象方法和普通方法。
2,抽象类里如果包含抽象方法,要求子类,重写所有的抽象方法,否则就是一个抽象类。
2 接口
概述:
Java里面由于不允许多重继承,所以如果要实现多个类的功能,则可以通过实现多个接口来实现。
Java接口和Java抽象类代表的就是抽象类型,就是我们需要提出的抽象层的具体表现。OOP面向对象的编程,如果要提高程序的复用率,增加程序的可维护性,可扩展性,就必须是面向接口的编程,面向抽象的编程,正确地使用接口、抽象类这些太有用的抽象类型做为java结构层次上的顶层。
interface 接口名{ 代码… }
特点:
1、 接口中都是抽象方法(jdk1.8以后可以是default/static修饰的普通方法)
2、 通过interface关键字创建接口
3、 通过implements让子类来实现
4、 可以理解成,接口是一个特殊的抽象类
5、 接口突破了java的单继承的局限性
6、 接口和类之间可以多实现,接口和接口之间可以多继承
7、 接口是对外暴露的规则,是一套开发规范
8、 接口提高了程序的功能扩展,降低了耦合性(低耦合)
接口中的构造方法:
1,接口里不允许有构造方法
2,实现类里有构造方法,并且调用Object的super();
接口中的成员变量:
接口中没有变量,有静态的常量,底层为变量自动拼接public static final
int a = 10;//简写形式
//public static final int a = 10 ;//接口会为你的变量,自动拼接public static final
接口中的成员方法:
1,接口里都是抽象方法,可简写 void save( );系统自动拼接abstract public
2,jdk1.8以后允许普通方法存在,但是必须是被defaule或static修饰,--static修饰的方法必须被接口名.方法调用
interface Inter{
//2,接口里jdk1.8的新特性的普通方法
public default void show() {
System.out.println("这是jdk1.8的新特性+default");
}
static public void test() {//Illegal modifier for the interface method test; only public, abstract, default, static and strictfp are permitted
System.out.println("这是jdk1.8的新特性+static");
}
void save ();//简写形式
//1,abstract public void save ();系统自动拼接abstract public
}
多继承:
继承是子类和父类---单继承
接口和接口---多继承之间的关系 interface Doo extends Boo,Coo{ }
多实现:
实现是实现类和接口之间的关系
abstract class Aoo implements Boo,Coo{ }
继承并实现:
单继承多实现:实现类继承了父类并实现了接口的功能
abstract class Eoo extends Aoo implements Boo,Coo{ }
Eoo为实现类
3 关键字
3.1 this关键字
this代表本类对象的一个引用对象。
作用:
1、当成员变量和局部变量名称相同是,想要在方法里使用成员变量,可用this.调用。
package text.oop;
//测试this关键字的使用
public class Text4_This {
public static void main(String[] args) {
new Demo().test();;//调用资源.只包括类里的成员(成员变量/成员方法),无法调用局部变量
System.out.println(new Demo().name);
}
}
class Demo{
String name;
int count = 20;
public void test() {
int count = 10;//局部变量
System.out.println(count);//10,就近原则
// this表示的是本类对象的引用--底层帮你new了一个本类对象
// Demo this =new Demo();
System.out.println(this.count);//20,成员变量
System.out.println(name);//null,成员变量
}
}
2、用来完成构造方法间互相的调用。
注意:只能是构造方法的第一条语句,也就是一个构造方法只能有一个;this调用只能是单向的,避免死循环。
package text.oop;
//测试this作用2 构造方法间互相调用
//总结:
//1,只能是构造方法的第一条语句,也就是之一个构造方法只能有一个
//2,this调用只能是单向的
public class Test5_This2 {
public static void main(String[] args) {
new Demo2();
// new Demo2(2);
}
}
class Demo2{
public Demo2() {
// this(10);//1,无参构造中调用含参构造
System.out.println("无参构造");
}
public Demo2(int a) {
//2,含参构造中调用无参构造
this();//3,只能在构造方法内的第一条语句,也就是只能调用一个
System.out.println("含参构造"+a);
}
}
3.2 super关键字
通过super关键字可以使用父类的内容,super代表父类的一个引用对象,如果用,必须出现在调用位置的第一行。
父类中成员变量和方法的引用:
//测试继承中super的使用
public class Test2_extends2 {
public static void main(String[] args) {
new Zi2().eat();
new Zi2().study();
new Zi2().sleep();
}
}
//创建父类
class Fu2{
int age=10;
public void eat() {
System.out.println("父类吃");
}
}
//创建子类,继承Fu2
class Zi2 extends Fu2{
int age=20;
public void eat() {
//调用父类原来的eat()--重写并不影响父类的原有功能
super.eat();
System.out.println("子类吃");
}
public void call() {
//调用父类原来的eat()
sout(age);//20,就近原则
sout(super.age);//10,当子类和父类属性名相同时,可以super调用,若不相同,则可以省略。
super.eat();
System.out.println("子类打电话");
}
}
父类中构造方法的引用:
//总结:
//1,在子类的构造方法中,会隐藏这一行代码super()--调用父类的无参构造
//2,当创建子类对象时,会调用父类的构造方法,先执行父类的,再执行子类的
public class Test3_Extends3 {
public static void main(String[] args) {
new Zi3();//会先去执行父类的无参构造,再执行自己的
}
}
//创建父类
class Fu3{
public Fu3() {
System.out.println("父类的无参构造");
}
public Fu3(int a) {
System.out.println("父类的含参构造"+a);
}
}
//创建子类,继承Fu3
class Zi3 extends Fu3{
public Zi3() {
//1,在子类的构造方法中,会隐藏这一行代码super()--
// super();//会自动执行父类的无参构造--如果父类不提供无参构造,提供了含参构造,调用会报错
// super(5);//调用父类的含参构造--出现在构造方法里时,位置必须是第一行代码
System.out.println("子类的无参构造");
}
}
3.3 static关键字
用于修饰成员(成员变量和成员方法)。
特点:
1、 可以修饰成员变量,成员方法
2、 随着类的加载而加载,优先于对象加载
3、 只加载一次,就会一直存在,不再开辟新空间
4、 全局唯一,全局共享
5、 可以直接被类名调用+对象调用
6、 静态只能调用静态,非静态可以随意调用
7、 static不能和this或者super共用,因为有static时可能还没有对象
8 、静态资源不能被重写
package test.oop;
//测试关键字static的使用
//总结:
//1,静态的调用关系--静态只能调用静态--非静态调用啥资源都可以
//2,静态资源是加载非常早的,随着类的加载就已经加载进内存了,比对象早
//3,静态资源的访问方式:通过对象调用+通过类名调用
//4,静态资源是全局变量,全局共享(多个对象数据公用)---普通资源只在对象内有效
public class Test4_Static {
public static void main(String[] args) {
Student s = new Student();//创建对象s
//调用普通资源--只能创建对象访问
s.study();
System.out.println(s.age);
//调用静态资源
// s.coding();
// System.out.println(s.name);
//1,静态资源,多了一种访问方式,除了可以用对象访问,更提倡用类名直接调用
//2,静态资源优先于对象加载,因为随着类的加载就已经加载了
Student.coding();
System.out.println(Student.name);
//3,静态资源,全局唯一,全局共享(各个对象里数据公用)////普通资源只在对象内有效
Student s1 = new Student();//创建对象s1
s1.age=20;
System.out.println(s1.age);//20
Student s2 = new Student();//创建对象s2
// Student.name="张三";
System.out.println(s2.age);//10
}
}
class Student{
//普通资源
int age = 10;
public void study() {
//6,非静态调用关系?--非静态可以调用非静态+静态资源
System.out.println(name);//可直接调用静态资源
coding();//可以
System.out.println("正在学JAVA");
}
//静态资源---变量/方法前面加static修饰,修饰为静态资源
static String name;
static public void coding() {
//4,静态资源内,不能使用this或者super关键字
// this.study();
// super.
//5,静态资源如何调用?--只能调用静态资源
System.out.println(name);//5.1可以直接调用静态成员变量
// study();//5.1不能直接调用,要讲study()修饰为静态,才可以调用
System.out.println("正在敲代码");
}
}
3.4 final关键字
概述:
1,表示最终的意思
2,可以修饰类,方法,成员变量
作用:
java出现了继承后,子类可以更改父类的功能,当父类功能不许子类改变时可以利用final关键字修饰父类。
package test.oop;
//测试final关键字
//1,final 修饰的类是最终的类,不能被继承
//2,final 修饰的变量,是一个最终的变量,值不能被修改,称之为常量
//3,final 修饰的方法,不能被重写,可以使用
public class Test6_Final {
public static void main(String[] args) {
new Boy().eat();
}
}
//final class Person{//1,final 修饰的类是最终的类,不能被继承
class Person{//1,final 修饰,不能被继承
//2,final 修饰的变量,是一个最终的变量,值不能被修改,称之为常量
// final int a = 10;
static final int SUM =10;//常量的标准写法
// a=20;
// final public void eat() {//3,final 修饰的方法,不能被重写,可以使用
public void eat() {
System.out.println("吃啥都行");
}
}
class Boy extends Person{
public void eat() {
final int a = 10;
System.out.println("男孩吃");
}
}
4 静态代码块、构造代码块、局部代码块
静态代码块:在类加载时就加载,并且只被加载一次,一般用于项目的初始化。
构造代码块:在调用构造方法前会自动调用,每次创建对象都会被调用。
局部代码块:方法里的代码块,方法被调用时才会执行。
package test.oop;
//测试静态代码块
//总结:
//1,静态代码块:用于初始化项目--位置在成员位置
//2,执行顺序
// 类加载时:静态代码块
// 实例化时:构造代码块>构造方法
// 方法调用:局部代码块
public class Test5_StaticBlock {
public static void main(String[] args) {
StaticDemo s = new StaticDemo();//先执行构造代码块然后执行构造方法
s.eat();//执行局部代码块
}
}
class StaticDemo{
//静态代码块--位置也是成员变量--用来完成项目的初始化--只加载一次
static{//最优先加载,在类被加载是就一起加载
System.out.println("静态代码块");
}
//构造代码块--成员位置--提取构造方法的共性
{
System.out.println("这是构造代码块");
}
//构造方法
public StaticDemo() {
System.out.println("这是无参构造");
}
//局部代码块--方法里--用来控制变量的作用范围
public void eat() {
{
System.out.println("这是局部代码块");
}
}
}
代码块发生继承时的顺序为:
父类静态代码块>子类静态代码块>父类非静态代码块>父类构造方法>子类非静态代码块>子类构造方法
5 访问控制符
用来控制一个类,或者类中的成员的访问范围。
注意:
1,没有访问控制符,默认default,不能写出来
2,重写时,子类的权限大于或等于父类的权限可以重写
6 异常
异常的继承结构:
Throwable - 顶级父类
-- Error:系统错误,无法修复
-- Exception:可修复的错误
--RunTimeException //运行期报错
--ClassCastException
--NullPointerException
--CheckedException //编译器报错
--SQLException
--IOException
--ClassNotFoundException
RuntimeException 是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类。
检查异常 CheckedException:一般是外部错误,这种异常都发生在编译阶段,Java 编译器会强制程序去捕获此类异常,即会出现要求你把这段可能出现异常的程序进行 try catch,该类异常一般包括几个方面:
试图在文件尾部读取数据
试图打开一个错误格式的 URL
试图根据给定的字符串查找 class 对象,而这个字符串表示的类并不存在
Throw 和 throws 的区别:
位置不同:
1,throws 用在函数上,后面跟的是异常类,可以跟多个;而 throw 用在函数内,后面跟的是异常对象。
功能不同:
1,throws 用来声明异常,让调用者只知道该功能可能出现的问题,可给出预先的处理方式;throw 抛出具体的问题对象,执行到 throw,功能就已经结束了,跳转到调用者,并将具体的问题对象抛给调用者。也就是说 throw 语句独立存在时,下面不要定义其他语句,因为执行不到。
2,throws 表示出现异常的一种可能性,并不一定会发生这些异常;throw 则是抛出了异常,执行 throw 则一定抛出了某种异常对象。
3,两者都是消极处理异常的方式,只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。