Java面向对象详解(一)
一. 面向对象基础
1. 面向对象思想
1.1 概述
面向对象是相对于面向过程来讲的,指的是把相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统建模,更贴近事物的自然运行模式。
面向过程到面向对象,是程序员思想上 从执行者到指挥者的转变。
1.2 三大思想
面向对象思想从概念上讲分为以下三种:OOA、OOD、OOP
OOA:面向对象分析(Object Oriented Analysis)
OOD:面向对象设计(Object Oriented Design)
OOP:面向对象程序(Object Oriented Programming)
1.3 三大特征
封装性:所有的内容对外部不可见
继承性:将其他的功能继承下来继续发展
多态性:方法的重载本身就是一个多态性的体现
2. 类和对象
类表示一个共性的产物,是一个综合的特征,而对象,是一个个性的产物,是一个个体的特征。
类必须通过对象才可以使用,对象的所有操作都在类中定义。
类由属性和方法组成:
属性:就相当于人的一个个的特征
方法:就相当于人的一个个的行为,例如:说话、吃饭、唱歌、睡觉
3. 创建对象内存分析
3.1 栈
Java栈的区域很小,大概2m左右,特点是存取的速度特别快
栈存储的特点是,先进后出
存储速度快的原因:
(1)栈内存, 通过 '栈指针' 来创建空间与释放空间
(2)指针向下移动, 会创建新的内存,向上移动,会释放这些内存
(3)这种方式速度特别快,仅次于PC寄存器
但是这种移动的方式, 必须要明确移动的大小与范围,明确大小与范围是为了方便指针的移动 , 这是一个对于数据存储的限制,存储的数据大小是固定的,影响了程序的灵活性。所以我们把更大部分的数据 存储到了堆内存中。
存储的是基本数据类型的数据 以及 引用数据类型的引用。
3.2 堆
堆存放的是类的对象。Java是一个纯面向对象语言, 限制了对象的创建方式。new关键字,是指告诉JVM ,需要明确的去创建一个新的对象,去开辟一块新的堆内存空间。
堆内存与栈内存不同, 优点在于我们创建对象时,不必关注堆内存中需要开辟多少存储空间,也不需要关注内存占用时长,堆内存中内存的释放是由GC(垃圾回收器)完成的。当栈内存中不存在此对象的引用时,则视其为垃圾,等待垃圾回收器回收。
3.3 方法区
方法区存放的是:
(1)类信息
(2)静态的变量
(3)常量
(4)成员方法
3.4 PC寄存器
PC寄存器保存的是当前正在执行的JVM指令的地址,在Java程序中,每个线程启动时,都会创建一个PC寄存器。
3.5 本地方法栈
保存本地(native)方法的地址
4. 构造方法
4.1 概述
用于对象初始化,在创建对象时自动调用。所有的Java类中都会至少存在一个构造方法,如果一个类中没有明确的编写构造方法,则编译器会自动生成一个无参的构造方法,构造方法中没有任何的代码。如果自行编写了任意一个构造器, 则编译器不会再自动生成无参的构造方法。
4.2 格式
例子:
class Person{
String name;
int age;
// 无参构造方法
public Person(){
System.out.println("对象创建时,此方法调用");
}
// 全参构造方法
public Person(String name,int age){
this.name = name;
this.age = age;
}
}
4.3 建议
(1)建议自定义无参构造方法,不要对编译器形成依赖,避免错误发生。
(2)当类中有非常量成员变量时,建议提供两个版本的构造方法,一个是无参构造方法,一个是全属性做参数的构造方法。
(3)当类中所有成员变量都是常量或者没有成员变量时,建议不提供任何版本的构造。
5.方法重载
方法名称相同, 参数类型或参数长度不同(参数顺序), 可以完成方法的重载。
方法的重载与返回值无关。
方法的重载 ,可以让我们在不同的需求下, 通过传递不同的参数调用方法来完成具体的功能。
例子:
class Math{
int sum (int x,int y){
int z = x+y;
return z;
}
// 参数类型不同
double sum (double x,double y){
double z = x+y;
return z;
}
// 方法3和方法4的参数顺序不同,也可构成重载
double sum (double x,int y){
double z = x+y;
return z;
}
double sum (int y,double x){
double z = x+y;
return z;
}
// 参数长度不同
double sum (double x){
double z = x+10;
return z;
}
}
6. 构造方法重载
与方法重载类似
空的构造方法和全参的构造方法其实就属于构造方法的重载
7. 匿名对象
没有对象名称的对象 就是匿名对象。
匿名对象只能使用一次,因为没有任何的对象引用,所以将称为垃圾,等待被GC回收。
例子:
public class Demo{
public static void main (String[] args){
int n = new Math().sum(100,200);
System.out.println(n);
}
}
class Math{
int sum(int x,int y){
return x+y;
}
}
如果一个对象要使用两次或两次以上时必须要给对象创建对象名
例子:
public class Demo{
public static void main (String[] args){
new Student().name = "张三";
new Student().name = 18;
new Student().say();
}
}
class Student{
String name;
int age;
void say(){
System.out.println("姓名:"+name+"\n年龄:"+age);
}
}
此时输出的结果为
姓名:null
年龄:0
new三次对象相当于在堆中开辟三块空间
第一块给只name赋值;第二块只给age赋值;第三块只调用say方法,此时没有赋值,因此name为null、age为0
二. 面向对象进阶
1. 封装private
封装的意义在于保护或防止代码(数据)被我们无意中破坏。保护成员属性,不让类以外的程序直接访问和修改。
原则:隐藏对象的属性和实现细节,仅对外公开访问方法,并且控制访问级别。
在开发中,为了避免出现逻辑错误,我们建议对所有属性进行封装,并为其提供setter及getter方法进行设置和取得操作。
例子:
class Student{
private String name;
private int age;
public void getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
public void getAge(){
return this.age;
}
public void setAge(int age){
this.age = age;
}
}
2. this
在Java基础中,this关键字是一个最重要的概念。使用this关键字可以完成以下的操作:
(1)调用类中的属性
(2)调用类中的方法或构造方法;在一个构造方法中,调用另一个构造方法时,调用的代码必须编写在构造方法的第一行。
例子:
Student(){
this("默认姓名",1);
System.out.println("123");
}
此时 this("默认姓名",1);必须写在第一行,因为在执行这句代码时对象还没初始化完毕,这时候如果执行其他代码时可能会
造成某些错误,因此规则上必须写在第一行
Student(String name,int age){
this.name = name;
this.age = age;
}
(3)表示当前对象
3. static
3.1 概述
static表示“静态”的意思,可以用来修饰成员变量和成员方法
static的主要作用在于创建独立于具体对象的域变量或者方法,可以简单理解为,被static关键字修饰的方法或者变量不需要依赖于
对象来进行访问,只要类被加载了,就可以通过类名去进行访问。并且不会因为对象的多次创建 而在内存中建立多份数据。
3.2 重点
(1)静态成员在类加载时加载并初始化。
(2)无论一个类存在多少个对象,静态的属性,永远在内存中只有一份( 可以理解为所有对象公用 )
(3)在访问时: 静态不能访问非静态 , 非静态可以访问静态。静态修饰的方法被调用时,对象可能还没创建
例子:
(1)class Student{
void static say(){
System.out.println("你好");
}
void say2(){
say();
}
}
(2)class Student{
void static say(){
say2();
}
void say2(){
System.out.println("你好");
}
}
(1)不会报错,因为此时如果say2能执行,说名对象已经创建,则say一定存在。
(2)会报错,因为say被调用时对象不一定创建,因此无法调用say2方法。
4. 包
4.1 包介绍
(1)把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
(2)包如同文件夹一样,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
(3)包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。
4.2 包的使用规则
包的定义:
通常由多个单词组成, 所有单词的字母小写, 单词与单词之间使用.隔开 ,一般命名为“com.公司名.项目名.模块名....”。
4.3 import关键字
import 包名.类名
5. 代码块
(1)普通代码块
在执行的流程中出现的代码块,我们称其为普通代码块。
(2)构造代码块
在类中的成员代码块,我们称其为构造代码块,在每次对象创建时执行,执行在构造方法之前。
例子:
{
执行语句;
}
(3)静态代码块
在类中使用static修饰的成员代码块,我们称其为静态代码块,在类加载时执行。每次程序启动到关闭只会执行一次的代码块。
static{
执行语句;
}
(4)同步代码块
在后续多线程技术中学习。
面试题:
构造方法 与 构造代码块 以及 静态代码块的执行顺序:
静态代码块 --> 构造代码块 --> 构造方法
原因:静态代码块在对象还没创建时就已经执行,而构造代码块在构造方法执行前先执行,因此执行的顺序为 静态代码块 --> 构造代码块 --> 构造方法。
6. 权限修饰符
修饰符 类 包 子类 其他包
public √ √ √ √
protected √ √ √ x
default √ √ x x
private √ x x x
7. main方法详解
main()方法一直写到了今天:
public static void main(String args[])
以上的各个参数的含义如下:
(1)public:表示公共的内容,可以被所有操作所调用
(2)static:表示方法是静态的,可以由类名称直接调用。
(3)void:表示没有任何的返回值操作
(4)main:系统规定好的方法名称。如果main写错了或没有,会报错:NoSuchMethodError: main
(5)String[] args:字符串数组,接收参数的
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?