第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:
    image

6.1 判断对象是否已经加载、链接、初始化

  • 首先根据new对象的类名是否在常量池中定位到一个符号引用,并检查这个符号引用代表的类是否已经加载、解析和初始化。其实就是验证是否是第一个使用该类。如果是第一次使用该类,就会执行类的加载过程。

  • JVM加载一个类的时候会创建一个instanceKlass,用来表示这个类的元数据,包括常量池、字段、方法等。存放在方法区。

6.2 在 java堆 中创建对象

  • 在new一个对象时,jvm创建instanceOopDesc,来表示这个对象,存放在堆区,其引用存放在栈区;平时说的Java Object Layout就是instanceOopDesc,它用来表示对象的实例信息;
  • instanceOopDesc对应java中的对象实例,包括对象头(其中包含类定义的引用Klass,Klass 中定义了类方法),实例数据(对象真正存储的有效信息,包括程序代码中定义父类子类的各种类型的字段)。
posted @   问稻  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示