面向对象编程
本质:以类的方式组织代码,以对象来组织(封装)数据
面向对象:分类的思维模式, 首先思考解决问题需要哪些分类,然后对这些分类进行单独思考。
面向过程:步骤清晰简单,每一步都清清楚楚。
类和对象
-
从认识论角度思考是先有对象后有类,对象是具体事物,类是对具体事物的抽象
-
从代码运行角度思考是先有类后有对象,类是对象的模版
类
类是一种抽象的数据类型,它是对某一类事物的整体描述/定义,但不能代表某一具体事物。
类用来组织代码
对象
对象是类(抽象概念)的具体实例。
对象用来封装数据
对象的创建
使用new关键词创建对象:
除了分配内存空间以外还会对创建好的对象进行默认的初始化以及对类中构造器进行调用
构造器也就是构造方法,是在进行创建对象时必须调用的,构造方法有两个特点:
-
必须和类的名字相同
-
必须没有返回值
public class Man {
String name;
//这里用到了private,其他类想修改Man类的私有属性age,必须使用get、set方法
private int age;
//这就是构造方法
public Man() { }
//带参数的构造方法
public Man(String name, int age) {
this.name = name;
this.age = age;
}
}
new对象时栈堆流程要理解
对象的初始化
对象(堆中)是通过引用(栈中)来操作的,不属于八个基础类型的都是引用类型
默认初始化:
数字:0 0.0
char:u0000
boolean:false
引用类型:null
对象的使用
对象的属性(静态的):man.name
对象的方法(动态的):man.sleep()
封装
该漏的漏,该藏的藏
程序设计要追求“高聚合,低耦合“,高内聚就是类的内部数据操作细节自己完成,不允许外界干涉,
低耦合是仅暴露少量方法给外界使用1
封装(数据的隐藏)
通常应禁止直接访问一个对象中数据的表示,而应通过操作接口来访问,这称为信息隐藏
记住这句话就够了:
属性私有,get/set
继承
继承的本质是对某一批类的进一步抽象,从而对现实世界更好的建模
-
extends的意思是“扩展”。子类是父类的扩展
-
java只有单继承没有多继承
-
继承是类(子类)与类(父类)之间的一种关系,除此之外类与类之间还有依赖、聚合、组合等关系
Object类
java中所有的类都直接或间接继承Object类
Super
super只能出现在子类方法和构造器方法中
super和this不能同时调用构造方法
类的构造器中super的应用
public class Person{
public Person(){
System.out.println("我是父类无参构造中的方法");
};//这是一个无参构造
}
public class Man extends Person{
public Man(){
super(); //这是无参构造中隐藏的一行代码,并且这行代码只能在无参构造的第一行。
//super();会调用父类的无参构造,从而会执行父类构造器中的方法。
System.out.println("我是子类无参构造中的方法");
};//当Man类被创建时会输出"我是父类无参构造中的方法"和"我是子类无参构造中的方法"
}
方法的重写
常用@Override注释表示重写方法
-
方法名必须一致
-
方法列表也必须一致
-
方法体必须不同
-
修饰符的范围可以扩大但不能缩小
-
抛出的异常可以被缩小但不能扩大
为什么要重写
-
父类的方法不一定满足子类的需求
-
子类不一定需要父类的一些方法
多态
把子类转换成父类,向上转型;把父类转换成子类,向下转型,强制转换,可能损失角度
存在条件:有继承关系,方法需要重写,父类的引用指向子类。
父类Person的引用man1指向子类对象Man,这里man1就是子类的对象
Person man1=new Man();
public class Person{
void run(){"通过多态的方式,子类对象可以调用父类的方法"};
}
public class Man extends Person {
}
//text方法
//下面就是多态的使用
Person man1=new man(); //对象能执行哪些方法主要看左边的类
System.out,println(man1.run());//这里就能使用Man没有的方法了
哪些不能重写:
-
static:它属于类,不属于实例,所以不能new对象
-
final:常量
-
private:私有方法
instanceof
instanceof 是java的保留关键字。
他的作用就是测试左边的对象是不是右边类的实例,是的话就返回true,不是的话返回false。
抽象
由abstract关键词修饰,有抽象类和抽象方法
抽象类里面可以没有抽象方法,但抽象方法所在的类一定得声明是抽象类
抽象类
不能用new关键词创建对象,它是用来让子类继承的一种建模的模版
抽象方法
只有方法的声明,没有方法的实现,它是用来让子类实现的
子类继承抽象类,必须得实现抽象类没有实现的方法,否则子类要申明是抽象类(像接口,接口不能有具体的实现)。
接口(interface)
接口的本质是契约
抽象类和普通类以及接口的区别
普通类:只能有方法的具体实现
抽象类:可以有方法的具体实现和方法声明的规范
接口:只能有方法声明的规范
为什么要使用接口?
因为抽象类只能进行单继承,而接口能实现多继承,这样就可以更好的规范java对现实世界的建模。
打个比方:
我要定义一个机器猫的类,如果单单继承普通猫这个类显然有些不合理,机械猫的功能有很多很多,如果每个功能都写好在机械猫这个类里面也不是不行,但后续如果要开发机械狗呢,重新写一遍太麻烦了,不如干脆定义一个机械的接口,让继承猫的和继承狗的类全部实现这个接口,这样做就大大简化了开发,后续出现甲方要一个变形金刚机械猫,也只需要额外实现一个变形金刚接口即可,这就是接口能多继承的好处
Impl(接口的实现类)
接口的实现类必须要重写接口类的方法,因为该类可以创建对象,所以也得实现该类的方法。
多继承
需要在implements后面实现的接口后面加 “,” 号再写接口名
public class userServiceImpl implements UserService,TimeService{}
内部类
内部类就是在一个类中再定义一个类。
第一类:定义在外部类局部位置上,分为局部内部类(有类名)、匿名内部类(没有类名)。
第二类:定义在外部类的成员位置上,分为成员内部类(没有static修饰)、静态内部类(使用static修饰)。
1.成员内部类
public class OuterClass {
private int x;
public class InnerClass {
public void printX() {
System.out.println("x = " + x); // 成员内部类可以直接访问外部类的实例变量
}
}
}
在上述示例中,InnerClass是一个成员内部类,它可以访问外部类的实例变量x。
2.静态内部类
public class OuterClass {
private static int x;
public static class InnerClass {
public void printX() {
System.out.println("x = " + x); // 静态内部类可以访问外部类的静态变量
}
}
}
在上述示例中,InnerClass是一个静态内部类,它可以访问外部类的静态变量x。
3.方法内部类
public class OuterClass {
private int x;
public void outerMethod() {
int y = 10;
class InnerClass {
public void printXY() {
System.out.println("x = " + x); // 方法内部类可以访问外部类的实例变量
System.out.println("y = " + y); // 方法内部类可以访问方法的局部变量(必须是final或effectively final)
}
}
InnerClass inner = new InnerClass();
inner.printXY();
}
}
在上述示例中,InnerClass是一个方法内部类,它可以访问外部类的实例变量x和方法的局部变量y(必须是final或effectively final)。
4.匿名内部类
public class OuterClass {
public void methodWithInterface() {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Running in anonymous inner class");
}
};
Thread thread = new Thread(runnable);
thread.start();
}
在上述示例中,使用匿名内部类实现了Runnable接口,并创建了一个新的线程来执行匿名内部类的逻辑。
这些代码示例展示了不同类型的Java内部类的用法。每种内部类都有其特点和用途,可以根据需求选择合适的内部类类型来实现特定的功能。
各自适用场景
成员内部类(Member Inner Class):
当内部类需要直接访问外部类的实例变量和方法时,可以使用成员内部类。 适用于需要内部类与外部类之间有紧密关联和相互访问的情况。
静态内部类(Static Inner Class):
当内部类不需要访问外部类的实例变量,只需访问外部类的静态成员时,可以使用静态内部类。 适用于与外部类关系较松散的情况,可以独立存在。
方法内部类(Method Local Inner Class):
当需要在一个方法中定义一个类,并且这个类只在该方法内部使用时,可以使用方法内部类。 适用于需要在方法内部封装一些辅助逻辑或实现某个特定功能的情况。
匿名内部类(Anonymous Inner Class):
当只需要使用某个接口或抽象类的实例,而不需要创建具体的类文件时,可以使用匿名内部类。 适用于需要临时定义一个类并实现接口或继承抽象类的情况。 需要根据具体的需求和场景来选择合适的内部类类型。内部类的使用可以提供更好的封装性、可读性和代码组织性,同时可以实现特定的设计模式和功能实现。
异常
检查性异常:
最具代表性的检查性异常是用户错误或问题引起异常,这是程序员无法预见的。
例如要打开一个不存在的文件,异常就发生了,这些异常在编译时不能被简单的忽略。
运行时异常:
运行时异常是可能被程序员避免的异常,与检查性异常相反,它可以在编译时被忽略
错误:
错误不是异常,它是脱离程序员控制的问题,错误在代码中通常被忽略。
例如,栈溢出时,一个错误就发生了,它们在编译时也是检查不到的
异常的处理机制
五个关键字:try,catch,finally,throw,throws
抛出异常(throw)和捕获异常(catch)
try{
int a=1;
int b=0;
if(b==0){
throw new ArithmeticException();//可预见的错误应该主动抛出异常
}
System.out.println(a/b);
}catch{
...
}
自定义异常
用户自定义异常类,只需要继承Exception类即可
使用步骤:
-
创建自定义异常类继承Exception类或其子类
-
在方法中通过throw关键字抛出异常对象
-
如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
-
在出现异常方法的调用者中捕获并处理异常
代码示例:
public class MyException extends RuntimeException{标签:java,内部,子类,基础,笔记,class,接口,方法,public From: https://www.cnblogs.com/haohao2036/p/17604305.html
public MyException(){
}
public MyException(String s){
super(s);
.....
}
}
public class Test {
static int quotient(int x,int y) throws Exception{
if(y<0){
throw new MyException("除数不能是负数");
}
return x/y;
}
public static void main(String[] args) {
int a= 3;
int b=0;
try {
int result = quotient(a,b);//调用quotient自定义异常方法,当b=0,会抛出ArithmeticException类的异常对象
System.out.println(result);
}catch (MyException e){
System.out.println(e.getMessage());
}catch (ArithmeticException e) {//异常对象会被此ArithmeticException类捕获
System.out.println("除数不能为0");
}catch (Exception e){
System.out.println("程序发生了其它的异常");
}
}
}
class MyException extends Exception{
String message;
public MyException(String ErrorMessage){
this.message = ErrorMessage;
}
@Override
public String getMessage() {
return message;
}
}