Java面向对象
面向对象(OOP)
- 本质:以类的方式组织代码,以对象的形式封装数据
- 面向对象是抽象的思想
- 特性:封装,继承,多态
- 类中只存在属性和方法,一个一般的类不存在main方法,一个项目中只应有一个main方法
- this代表当前类
- 类是抽象的,需要实例化为对象
- 对象是通过引用来操作的,栈中存放引用变量名(对象在堆中的地址),对象真实操作在堆中。
封装
- 高内聚,低耦合:高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用
- 封装:数据的隐藏,通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口访问,这称为信息隐藏
- 属性私有(private),getter/setter
- 提高程序的安全性,保护数据;隐藏代码的实现细节;统一接口;增加系统可维护性;
- 判断两个方法是否相同看方法名和参数列表
继承
- 继承的本质是对一批类的抽象(类本身就是抽象的)。
- 子类是父类的extends(扩展)
- 子类 is a 父类,例如 老师是人,学生是人
- 子类可以获得父类的所有非私有方法和非私有属性;将子类实例化之后可以使用父类的方法和属性;在子类中使用super.属性名/方法名调用;
- Java中所有的类都直接或间接继承object类
- Java中只有单继承,没有双继承;子类只能有一个父类;
- final修饰的类不能被继承
super
- 子类用super()调用父类的构造方法或者this()调用本身的构造方法,必须在构造方法的第一句
- super必须只能出现在子类的方法或者构造方法中
- super()和this()不能同时调用构造方法,因为都必须在构造方法中的第一行
- 本质:如果要new一个有父类的子类,在子类的构造方法中首先要构造出该子类的父类;
super VS this
- this代表本身调用者这个对象;super代表父类对象
- this没有继承也可以使用;super必须在继承条件才可以使用
- this():本类的无参构造方法;super():父类的无参构造方法;
- this()和super()只能在构造方法中使用;
方法重写(又名方法覆盖)
B.java
public class B {
public static void test() {
System.out.println("我是B,我是父类!");
}
}
A.java
public class A extends B{
public static void test() {
System.out.println("我是A,我是子类!");
}
}
Main.java
public class Main {
public static void main(String[] args) {
A a=new A();
a.test();
B b=new A();//上转型对象
b.test();
//如果子类重写了父类的静态方法,那么子类对象的上转型对象不能调用子类的静态方法,只能调用父类的静态方法
//父类的static方法是不会被重写的,不具有多态特性,即使子类中有相同的static方法,编译能通过,但不会覆盖父类的static方法。
//静态方法的调用只和左边定义的数据类型有关
}
}
---静态执行结果------ -----非静态执行结果-(分别去掉A、B两类方法中的static)----
我是A,我是子类! 我是A,我是子类!
我是B,我是父类! 我是A,我是子类!
-
非静态的方法才能重写(覆盖)
-
Java引用变量有两个类型,一个是编译时类型,还有一个是运行时类型。编译时类型是由声明该变量时使用的类型所决定,运行时类型是由该变量指向的对象类型决定
-
上转型对象可以访问子类继承或隐藏的成员变量,可以操作子类继承或重写的方法,其作用等价于子类对象去调用这些方法,因此,如果子类重写了父类的某个方法,则当对象的上转型对象调用这个方法时一定是调用了这个重写的方法
-
如果子类与父类都定义了相同的变量名称,子类变量名会将父类变量名隐藏,上转型对象调用该变量是调用父类的,只有子类对象调用才是调用子类的
-
上转型对象可以被强制转换到它的子类对象,这时,该子类对象又具备了子类的所有属性和功能
-
上转型对象不能操作子类新增的成员变量和方法
-
对象的上转型对象:继承或隐藏的变量;继承或重写的方法;
对象:子类新增的变量和方法;继承或隐藏的变量;继承或重写的方法;
以上也可以概括为:对象能执行那些方法,主要看左边的类中有没有,和右边new的类型关系不大
-
子类只能重写父类非私有的方法
-
重写需要有继承关系,子类重写父类的方法,方法名和参数列表必须相同。重写的方法范围可以扩大,但不能缩小。重写抛出的异常只能缩小,不能扩大
-
为什么需要重写:父类的功能子类不一定需要或者不一定满足
-
static方法不能重写,因为它是属于类(当类加载时,static方法就已经存在,而此时对象还未创建),而不属于实例对象;final修饰的方法在常量池中,无法重写;private方法无法重写
多态
- 同一方法可以根据发送对象的不同而采用多种不同的行为方式
- 多态是方法的多态,没有属性的多态
- 一个对象的实际类型是确定的,但可以指向对象的引用类型有很多(父类/有关系的类)
String name=new String();
Object nam=new String();//Java中的类全部默认继承Object类;父类的引用指向子类对象
Father father=new Son(); //上转型对象实例是子类对象
-
多态存在的条件:有继承关系;子类重写父类方法;父类引用指向子类对象;
-
instanceof 运算符是二目运算符,X(对象) instanceof Y(类):当X是Y本类或者子类创建的对象时,true;先有继承关系,再有instanceof的使用
X(对象) instanceof Y(类)//编译时看左边类型,运行时看右边对象;X和Y比较之前会先判断X的左边类型能不能转换成Y类型,能则通过,
//不能则编译报错
- 需要用到对象的强制类型转换时,需要使用instanceof进行判断。
static代码块
public class staticBlock {
// 2 赋初值
{
System.out.println("我是匿名代码块");
}
// 1 只执行一次
static {
System.out.println("我是静态代码块");
}
// 3
public staticBlock() {
System.out.println("我是构造方法");
}
public static void main(String[] args) {
staticBlock s1=new staticBlock();
System.out.println("===================");
staticBlock s2=new staticBlock();
}
}
------执行结果-------
我是静态代码块
我是匿名代码块
我是构造方法
===================
我是匿名代码块
我是构造方法
构造器
- 在new一个对象的时候,会调用类的构造方法,一个类即使是空的,也会有一个无参构造方法。
例如public 类名(){}
- 构造方法有两个特点:1、必须和类的名字相同 2、必须没有返回类型,也不能写void
- 构造器作用:1、new一个对象的时候本质是在调用构造器 2、用来初始化值
- 一旦定义有参构造,无参构造直接消失,还想用无参构造,无参构造就必须是显式;
- int具体数字不属于堆中方法区常量池
抽象类(本质是类)
- abstract修饰符可以用来修饰方法或类,修饰方法就是抽象方法,修饰类就是抽象类
- 抽象类中可以没有抽象方法,抽象类中也可以写普通的方法,但是有抽象方法的类一定要声明为抽象类
- 抽象类不能用new来创建对象,它是用来让子类继承的
- 抽象方法只能声明方法,不能实现方法,它是让子类来实现的
- 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类
- 抽象类是抽象的抽象,是一种约束
- 抽象类存在构造器吗? 可以有
- 抽象类存在的意义是什么?提高开发效率
接口
- Java中类是单继承但是接口可以多继承
- 一个类可以实现多个接口
- 接口本质是契约,必须遵守,接口就是规范,定义了一组规则,不能实现方法,只能声明方法
- 接口是对对象的抽象
- 接口中所有定义的方法都是抽象的,接口中所有方法默认且只能是public abstract;
- 常量默认是public static final 例如:
int i=10; String s=“ChenShuBo”;
- 类实现接口,必须要重写接口中的方法
- 接口不能被实例化,因为没有构造方法
- 接口中只能定义常量和抽象方法
内部类
1、成员内部类:成员内部类利用已经实例化的外部类进行内部类的实例化,内部类可以调用外部类的私有属性和私有方法
Application.java
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();//实例化外部类
Outer.Inner inner = outer.new Inner();//实例化内部类
inner.getID();
inner.inner();
}
}
Outer.java
public class Outer {
private int id=10;
public void outer(){
System.out.println("这是外部类!");
}
public class Inner{
public void inner(){
System.out.println("这是内部类!");
}
public void getID(){
System.out.println(id);
outer();
}
}
}
------执行结果------
10
这是外部类!
这是内部类!
2、使用static修饰成员内部类就成了静态内部类;static只能修饰内部类不能修饰普通类
3、 定义在普通类(没有main方法)中的方法中的类称为局部内部类
4、
Application.java
public class Application {
public static void main(String[] args) {
new Apple().run //匿名内部类
new user(){ //匿名内部类
@Override
public void run() {}
};
}
}
user.java
interface user{
void run ();
}
Apple.java
class Apple{
void run(){ }
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)