第11篇 类对象
1. 静态方法与非静态方法的区别
- 静态方法在定义类的时候就随着类装载到了内存中,不会自动销毁,直到关闭 jvm
- 非静态方法只有实例化对象的时候才会分配内存,与实例化对象共存。
public class Demo01 { //静态方法 修饰符 static public static void user(){ //sayHello1();//报错,静态方法不能直接调用非静态方法,因为其还没有分配内存,只能通过实例区调用。 sayHello2(); } //非静态方法 public void sayHello1(){ } public static void sayHello2(){ } public void sayHello3(){ user();//非静态方法可以直接调用静态方法 } }
2. 构造器(c++构造函数)
- 如果不显式地定义构造函数,编译时编译器会自动生成一个无代码块的无参构造函数
- 编写时如果添加了有参构造方法而未添加无参构造方法,那么编译器不会再默认添加无参构造方法。
- 如果只定义有参不定义无参,且后续还需要调用无参构造方法,编译器会报错!
/*例如,如果不显式调用父类有参构造函数,且没写父类的无参构造函数的情况下: 子类会默认调用父类的无参构造函数,但是编译器无法找到一个无参构造函数,会报错! */ public class A{ int a; public A(int a){this.a =a;} } public class B extends A{ //以下演示编译器默认的子类B的无参构造函数 public B(){ super();//编译器默认在方法体第一行调用父类的无参构造函数。找不到则报错! } } //想要不报错,有以下两个方法: //1.自己写B的构造函数,且在方法体第一行写A类的有参构造函数 public class B extends A{ //以下演示编译器默认的子类B的无参构造函数 public B(int a){ super(a);//父类有参 } } //2.在A类中追加一个无参构造函数 public class A{ int a; public A(int a){this.a =a;} public A(){};//追加无参 }
3.修饰符
public, protected, private (与C++一致)
public class Person { String name; public Person(String name) { this.name = name; } //alt+insert可以快速选择生成getName()和setName函数 //通过规定对外接口,限制外部对内部变量的随便访问 public String getName() { return name; } public void setName(String name) { this.name = name; } }
4.代码块
class Person{ //匿名代码块 { System.out.println("匿名代码块"); } //加了Static为静态代码块 static{ System.out.println("静态代码块"); } //无参构造函数 public Person(){ System.out.println("构造方法"); } } //调用以下函数生成一个Person实例会产生什么结果呢?即上述三者的运行先后次序是什么呢? new Person(); /* 静态代码块 匿名代码块 构造方法 */ //再执行一次呢? new Person(); /* 匿名代码块 构造方法 */
- 直接由{ }括起来的代码为代码块
- 普通代码块(叫匿名代码块),再每次生成对象实例的时候都会执行一次,而且是先于构造函数执行
- 静态代码块,即 static { },只有第一次定义实例的时候会执行,且其执行次序先于普通的代码块和构造方法
- 匿名代码块常用于赋初始值
5. final修饰符用于类
-
final 可以用于修饰类,放在class之后,类名之前
-
被 final 修饰的类没有子类
class final Person{} class Man extends Person{}//报错!Person已经是fianl,它不能生成子类
6.类实例化的过程
[原帖链接] (https://blog.csdn.net/qq_41860497/article/details/130335081)
6.0 双亲委派机制
JVM提供以下三种classLoader 用于把class文件加载到JVM中:
-
Bootstrap classLoader:主要负责加载核心的类库(java.lang.*等),构造ExtClassLoader和APPClassLoader。
-
ExtClassLoader:主要负责加载jre/lib/ext目录下的一些扩展的jar。
-
AppClassLoader:主要负责加载应用程序的主函数类
一个自编的class文件经过以下流程进入JVM:
6.1 判断对象是否已经加载、链接、初始化
-
首先根据new对象的类名是否在常量池中定位到一个符号引用,并检查这个符号引用代表的类是否已经加载、解析和初始化。其实就是验证是否是第一个使用该类。如果是第一次使用该类,就会执行类的加载过程。
-
JVM加载一个类的时候会创建一个instanceKlass,用来表示这个类的元数据,包括常量池、字段、方法等。存放在方法区。
6.2 在 java堆 中创建对象
- 在new一个对象时,jvm创建instanceOopDesc,来表示这个对象,存放在堆区,其引用存放在栈区;平时说的Java Object Layout就是instanceOopDesc,它用来表示对象的实例信息;
- instanceOopDesc对应java中的对象实例,包括对象头(其中包含类定义的引用Klass,Klass 中定义了类方法),实例数据(对象真正存储的有效信息,包括程序代码中定义父类子类的各种类型的字段)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!