面向对象
- 面向对象编程(Object-Oriented Programming,OOP)
- 面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据。
- 抽象
- 三大特性:
- 封装
- 继承
- 多态
方法的调用
-
静态方法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XrKs6WQL-1645524917063)(C:\Users\Lr\AppData\Roaming\Typora\typora-user-images\image-20220118203634441.png)]
-
非静态方法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EMyoNMfz-1645524917064)(C:\Users\Lr\AppData\Roaming\Typora\typora-user-images\image-20220118205913874.png)]
-
值传递
package oop.demo01; //值传递 public class Demo04 { public static void main(String[] args){ int a = 1; System.out.println(a);//1 Demo04.change(a); System.out.println(a);//1 } //返回值为空 public static void change(int a){ a = 10; } }
构造器
-
使用new关键字创建对象
-
使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象,进行默认的初始化以及对类中构造器的调用
-
类中的构造器也称为构造方法,是在进行创建对象的时候必须调用的。并且构造器有以下两个特点:
-
必须和类名字相同
-
必须没有返回类型,也不能写void
作用:
-
new本质是在调用构造方法
-
初始化对象的值
注意点:
定义有参构造后,如果想要使用无参构造,显示的定义一个无参的构造
-
-
创建对象内存分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SJSyvUr5-1645524917065)(C:\Users\Lr\AppData\Roaming\Typora\typora-user-images\image-20220119111659902.png)]
类与对象
-
类与对象
类是一个模板:抽象,对象是一个具体的实例
-
方法: 定义、调用
-
对应的引用
引用类型: 基本类型(8)
对象是通过引用操作的:栈----->堆
-
属性:字段Field 成员变量
默认初始化:
数字:0 0.0
char u0000
boolean:false
引用:null
修饰符 属性类型 属性名 = 属性值
-
对象的创建与使用
必须使用new 关键字创造对象,构造器 Person xiaolizi = new Person();
对象的属性 xiaolizi.name
对象的方法 xiaolizi.high()
-
类:
静态的属性 属性
动态的行为 方法
封装
-
高内聚 低耦合 高内聚就是类的内部数据操作细节自己完成,不允许外部干涉,低耦合仅暴露少量的方法给外部使用
-
封装(数据的隐藏) 通常应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏
-
属性私有,get/set
封装的作用
-
提高程序的安全性,保护数据
-
隐藏代码的实现细节
-
统一接口
-
系统可维护性增加了
-
继承
-
继承的本质是对某一批类的抽象
-
extends 的意思是“扩展”。子类是父类的扩展
-
JAVA中只有单继承,没有多继承(一个儿子只能有一个爸爸 但是一个爸爸可以有多个儿子)
-
继承是类和类之间的一种关系,除此之外,类和类之间的关系还有依赖,组合,聚合等
-
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示
-
在JAVA中,所有的类,都默认直接或者间接继承object
-
super
super注意点:
-
super调用父类的构造方法,必须在构造方法的第一个
-
super必须只能出现在子类的方法或者构造方法中
-
super 和this 不能同时调用构造方法
-
Student student = new Student();//测试类 public class Student extends Person { //子类 public Student() { //隐藏代码:调用了父类的无参构造 System.out.println("Student 无参执行"); } public class Person { //父类 public Person() { System.out.println("Person无参执行"); } 执行结果:Person无参执行 Student 无参执行
VS this:
代表的对象不同:
this: 本身调用者这个对象
super: 代表父类对象的应用
前提:
this : 没有继承也可以使用
super :只能在继承条件才能使用
构造方法:
this() ; 本类的构造
super(); 父类的构造
重写
重写:需要有继承关系,子类重写父类的方法
-
方法名必须相同
-
参数列表必须相同
-
修饰符:范围可以扩大但不能缩小: public>Protected>Default>private
-
抛出的异常:范围,可以被缩小,但不能扩大,ClassNotFoundException—>Exception(大)
重写(override),子类的方法和父类必须一致,方法体不同
静态方法:
public class A extends B{ public static void test(){ System.out.println("A=>test()"); } } //重写都是方法的重写,和属性无关 public class B { public static void test(){ System.out.println("B=>test()"); } } public class Application { public static void main(String[] args){ //方法的调用只和左边,定义的数据类型有关 A a = new A(); a.test();//A类的方法 //父类的引用指向了子类 B类为父类 B b = new A(); b.test();//B类的方法 测试结果: A=>test() B=>test()
非静态方法:
非静态:重写
/重写都是方法的重写,和属性无关
public class B {
public void test(){
System.out.println("B=>test()");
}
}
public class A extends B{
//Override :重写
@Override //注解:有功能的注释
public void test() {
System.out.println("A=>test()");
}
}
测试结果:A=>test()
A=>test()
多态
-
多态:即同一方法可以根据发送对象的不同而采用多种不同的行为方式
-
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多。
-
多态存在的条件
-
有继承关系
-
子类重写父类方法
-
子类引用指向子类对象
//父类 public class Person { public void run(){ System.out.println("run"); } } //子类 public class Student extends Person { @Override public void run() { System.out.println("son"); } public void eat() { System.out.println("eat"); } } //测试类 import oop.demo06.Person; import oop.demo06.Student; public class Application { public static void main(String[] args) { //一个对象的实际类型是确定的 //new Student(); //new Person(); //可以指向的引用类型不确定:父类的引用指向子类 //Student 能调用的方法都是自己的或者继承父类的 Student s1 = new Student(); //Person父类型,可以指向子类,但是不能调用子类独有的方法 Person s2 = new Student(); Object s3 = new Student(); //对象能执行哪些方法,主要看对象左边的类型,和右边关系不大 s2.run();//子类重写了父类的方法,执行子类的方法 ((Student) s2).eat();//可以使用强制类型转换。将大类型转换为小类型 s1.eat(); } } 测试结果: son eat eat
-
-
多态注意:
-
多态是方法的多态,属性没有多态
-
父类和子类,有联系 类型转换异常 ClassCastException
-
存在条件:继承关系,方法需要重写,父类引用指向子类对象 Father f1 = new Son();
-
static 方法,属于类,不属于实例
- final 常量;
3. private
4. 方法;
- final 常量;
-
-
instanceof (类型转换) 引用类型
public class Application {
public static void main(String[] args) {
//Object > String
//Object > Person > Teacher
//Object > Person > Student
Object object = new Student();
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Teacher);//False 跟Student 无关是另外的一个分支
System.out.println(object instanceof String);//False String 类型是Object下的
System.out.println("==============================");
Person person = new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Object);//true
System.out.println(person instanceof Teacher);//False
// System.out.println(person instanceof String);//编译报错
System.out.println("==============================");
Student student = new Student();
System.out.println(student instanceof Student);//true
System.out.println(student instanceof Person);//true
System.out.println(student instanceof Object);//true
//System.out.println(student instanceof Teacher);//False编译报错
// System.out.println(student instanceof String);//False编译报错
public class Application {
public static void main(String[] args) {
//类型之间的转换
//子类转换为父类,可能丢失自己本来的一些方法
Student student = new Student();
student.go();
Person person = student;//student(低) ->person(高) 可以自动转换
Person obj = new Student();
//student将这个对象转换为Student类型,就可以使用Student类型的方法
((Student)obj).go();
}
注意:
- 父类引用指向子类的对象
- 把子类转换为父类,向上转型
- 把父类转换为子类,向下转型:强制转换
- 方便方法的调用,减少重复的代码,简洁
static
- 非静态的方法可以调用静态方法里的所有东西 而静态方法只能调用静态方法里面的东西 不能调用非静态方法
因为static跟类一起加载
private static int age;//静态变量
private double score;//非静态的变量
public void run(){
}
public static void go(){
}
public static void main(String[] args){
go();
// run();//报错
-
静态代码块
public class Person { //赋初始值 { System.out.println("匿名代码块"); } //静态代码块只执行一次 static { System.out.println("静态代码块"); } public Person(){ System.out.println("构造方法"); } public static void main (String[] args){ Person person = new Person(); } } 测试结果: 静态代码块 匿名代码块 构造方法 public static void main (String[] args){ Person person1= new Person(); System.out.println("============"); Person person2 = new Person(); } 测试结果: ============ 匿名代码块 构造方法
注意:用final定义不能实现继承
-
//静态导入包 import static java.lang.Math.random; import static java.lang.Math.PI; public class Test { public static void main(String[] args) { System.out.println(random()); System.out.println(PI); } }
抽象类
//abstract 抽象类:类 extends: 单继承(接口可以多继承)
public abstract class Action{
//约束 可以自行实现
//abstract,抽象方法,只有方法名字,没有方法的实现!
public abstract void doSomething();
//1. 不能new 这个抽象类,只能靠子类去实现它;约束
//2.抽象类中可以写普通的方法1
//3.抽象方法必须在抽象类中
接口
- 普通类:只有具体实现
- 抽象类:具体实现和规范(抽象方法)都有
- 接口:只有规范 自己无法写方法 约束和实现分离:面向接口编程
- 声明类的关键字是class,声明接口的关键字是interface
- 接口不能被实例化,接口中没有构造方法
- implements 可以实现多个接口
- 接口中的方法需要重写
/interface 定义的关键字,接口都需要有实现类
public interface UserService {
//接口中的所有定义都是抽象的 public abstract
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
//抽象类:extends
//类 可以实现接口 implements 接口
//实现了接口的类,就需要重写接口中的方法
public class UserServiceImpl implements UserService{
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
}
//多继承 利用接口实现多继承
public class UserServiceImpl implements UserService,TimeService {
@Override
public void timer()
public interface TimeService {
void timer();
}
//常量:public static final
//int AGE = 99;
内部类
-
内部类就是在一个类的内部再定义一个类,比如在A类中定义一个B类,那么B类相对于A类来说就称为内部类,而A类相对B类就是外部类。
public class Outer { private int id = 10; public void out(){ System.out.println("这是外部类的方法"); } class Inner{ public void in(){ System.out.println("这是内部类的方法"); }
-
-
成员内部类
public class Outer { private int id = 10; public void out(){ System.out.println("这是外部类的方法"); } class Inner{ public void in(){ System.out.println("这是内部类的方法"); } //获得外部类的私有属性 私有方法 public void getID(){ System.out.println(id); } } } public class Application { public static void main(String[] args) { //new Outer outer = new Outer(); //通过这个外部类来实例化内部类 Outer.Inner inner = outer.new Inner(); inner.in(); inner.getID(); } }
-
静态内部类
public static class Inner{ public void in(){ System.out.println("这是内部类的方法"); }
-
局部内部类
public class Outer { //局部内部类 public void method(){ class Inner{ public void in(){ } } } }
-
匿名内部类
public class Test { public static void main(String[] args){ //没有名字初始化类,不用将实例保存到变量中 new Apple().eat(); //UserService userService = new UserService() new UserService(){ @Override public void hello() { } }; } } class Apple{ public void eat(){ System.out.println("1"); } } interface UserService{ void hello(); }
-
异常机制
-
异常(Exception) 指程序运行中出现的不期而至的各种状况,如:文件找不到,网络连接失败,非法参数等
-
异常发生在程序运行期间,它影响了正常的程序执行流程。
-
异常类型
- 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常
- 运行时异常:运行时异常是可能被程序员避免的异常,与检查性异常相反,运行时异常可以在编译时被忽略
- 错误(ERROR):错误不是异常,而是脱离程序员控制的问题。比如,当栈溢出时,一个错误就发生了,在编译时时检查不到的。
-
Java 把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类
-
在Java API中已经定义了许多异常,这些异常分为两大类,错误Error和异常Exception
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-enfGjx4c-1645525492610)(h]
ttps://img-blog.csdnimg.cn/6067c1ae497747e2a5d253f5b2e69990.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Y-q5oOz5q-P5aSp5YGl5bq355qE5p2O5p-Q5Lq6,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LnIqkgeO-1645524917065)(C:\Users\Lr\AppData\Roaming\Typora\typora-user-images\image-20220124114642244.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zAD9cnWW-1645524917066)(C:\Users\Lr\AppData\Roaming\Typora\typora-user-images\image-20220124120325869.png)]
- Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关
- Java虚拟机运行错误(Virtual MachineError),当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryErrror.这些异常发生时,Java虚拟机(JVM)一般会选择线程终止
- 发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、链接错误(LinkageError).这些错误不可查,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。
public class Test {
public static void main(String[] args){
int a = 1;
int b = 0;
//假设要捕获多个异常:从小到大
try{ //try监控区域
System.out.println(a/b);
}catch (ArithmeticException e){//catch(其中Throwable最高) 捕获异常
System.out.println("程序出现异常,变量b不能为0");
}finally {//处理善后工作
System.out.println("finally");
}
//finally 可以不要finally
}
}
测试结果:
程序出现异常,变量b不能为0
finally
自动捕获 // 选中要捕获的然后Ctrl + Alt +T
throw throws
public class Test {
public static void main(String[] args){
new Test().test(1,0);
}
public void test(int a, int b){
if (b==0){
throw new ArithmeticException();//主动抛出异常,一般在方法中使用
}
}
}
public class Test {
public static void main(String[] args){
//使用try catch可以捕获异常 不会使程序终止,会使程序运行下去
try {
new Test().test(1,0);
} catch (ArithmeticException e) {
e.printStackTrace();
}
}
//假设这个方法中,处理不了这个异常。方法上抛出异常
public void test(int a, int b) throws ArithmeticException{
if (b==0){
throw new ArithmeticException();//主动抛出异常,一般在方法中使用
}
}
}
自定义异常
- 使用Java内置的异常类可以描述在编程时出现的大部分异常情况,用户还可以自定义异常。用户自定义异常类,只需继承Exception类
- 在程序中使用自定义异常类
- 创建自定义异常类
- 在方法中通过throw关键字抛出异常对象
- 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作
- 在出现异常方法的调用者中捕获并处理异常。
//自定义的异常类
public class MyException extends Exception{
//传递数字>10
private int detail;
public MyException(int a){
this. detail = a;
}
//toString:异常的打印信息
@Override
public String toString() {
return "MyException{" + "detail=" + detail + '}';
}
}
public class Test {
//可能会存在异常的方法
static void test(int a) throws MyException {
System.out.println("传递的参数为:"+a);
if (a>10) {
throw new MyException(a);//抛出 这里抛出 则外面的throws要捕获
}
System.out.println("OK");
}
public static void main(String[] args) {
try {
test(11);
} catch (MyException e) {
System.out.println("MyException=>" +e);
}
}
}
//自定义的异常类
public class MyException extends Exception{
//传递数字>10
private int detail;
public MyException(int a){
this. detail = a;
}
//toString:异常的打印信息
@Override
public String toString() {
return "MyException{" + "detail=" + detail + '}';
}
}
public class Test {
//可能会存在异常的方法
static void test(int a) throws MyException {
System.out.println("传递的参数为:"+a);
if (a>10) {
throw new MyException(a);//抛出 这里抛出 则外面的throws要捕获
}
System.out.println("OK");
}
public static void main(String[] args) {
try {
test(11);
} catch (MyException e) {
System.out.println("MyException=>" +e);
}
}
}