百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

三石说:java基础 类与对象

bigegpt 2025-03-02 16:15 7 浏览

类:

类是封装对象的行为和属性的载体,具有相同属行和行为的一类实体。类中包含方法和属性。

类中的构造方法:

1.构造方法没有返回值2.名称与类名相同,在构造方法中可以为成员变量赋值,也就是初始化成员变量,若在类中的构造方法都不是无惨的构造方法,编译器不会为类设置一个无参的构造方法,在类中没有设置构造方法时编译器才会在类中自定义一个无参的构造方法;

类中的成员方法:

成员方法对应于类对象的行为,成员方法可以是有参也可以是无参,可以有返回值也可以没有返回值,成员方法中可以调用其他成员方法也可以调用类成员变量,成员方法中也可以定义成员变量这是的成原变量为局部变量, 静态成员变量,静态成员方法:都用 类名.成员方法名。类名.成员变量掉用。静态方法中不可以用this关键字,静态方法不能直接调用非静态方法静态类中不能用this传值,可以用 return进行返回值,和直接输出;用来测试静态方法

1.静态方法不可以访问非静态变量

2.非静态方法可以访问静态方法;

静态方法或属性在类加载时产生的。非静态方法是在new中产生的调用静态方法的格式:类名.静态方法名(参数);

This关键字:

this也可以调用成员方法和成员变量只是不太规范。主要用于当前对象的调用;This也可以做为方法的返回值

this可以在当前方法中获取当前对象的引用。

Static关键字:

new创建对象,数据存储空间才会分配,其方法才会对外界调用。而static修饰的:(1)如果没有创建对象,也可以进行调用这个方法。(2)只想为某特定的区域分配单一存储空间,而不考虑究竟创建出多少对象。

当一个事物声明static那就意味着这个域或方法不会与包含他那个类所关联在一起,所以即使从未创建某个类的任何对象,也可以调用其static方法,或访问static域。

比如:

class StaticTest{

static int i= 47;

String a =1;

}

StaticTest st1=new StaticTest();

StaticTest st22=new StaticTest();

st1.i和st22.i指向的是同一个存储空间,他们具有相同的值。

尽管当static作用于某个字段时,肯定会改变数据创建的方式(因为一个static字段对每个类来说都只有一份存储空间,而非static字段则是对每个对象有一存储空间)

static方法的内部能调用非静态方法。

static加载顺序:

父类静态代码块->子类静态代码块-->父类非静态代码块-->父类构造方法-->子类非静态代码块-->子类构造方法。

Super关键字:

子类可易继承父类的非私有变量,和方法作为自己的成员变量和成员方法,子类中的方法名与父类的方法名相同时称为子类隐藏了父类的成员变量,子类不能继承父类的成员方法,此时称为重写父类的成员变量;

若子类想访问父类中被子类隐藏的成员方法或变量时可以用super关键字 此时必须由子类来使用super关键字;用途:

1.super(参数列表);调用父类有参的构造器

2.操作被隐藏在父类中的成员变量或被重写的方法格式:super.成员变量名 必须放在方法的第一个语句中;

Super.成员方法名([参数列表])Extends 子类继承父类,子接口继承父接口,implements子类对接口的实现

final关键字:

final作用于数据,方法,类。

1.一个永不改变的编译时常量。

2.一个在运行时被初始化的值,而你不希望它被改变。

一个既是static又是final的域只占据一段不能改变的存储空间。

空白的final:java允许生成一个空白的final;所谓的空白的final是指的被声明为final但又未给定初始值的域。比如: private final int j;

final参数:java允许声明一个参数为final的对象。

void(final Gizmo g){

g=new Gizmo() // Illegal ---g is final

}

final方法:定义为final方法的原因有两个;1.把方法锁定,以防止任何继承类修改它的含义(保持不变,防止覆盖)。2.是效率

private和final关键字:类中所有的private方法都隐式的指定为final,由于无法取用private方法,所以也就无法进行覆盖他,对于private方法添加final关键字并不能给方法增加任何意义。

final类:将类设置为final即使永远不需要做任何变动,或者出于安全不希望有子类。由于final类禁止继承,所以final类的方法都隐式的指定为final的,因为无法覆盖他们,同样也可以给final类的方法添加final修饰词,但是这没有任何意义。

final修饰引用类型的时候,引用的指向不能修改,但是引用的值可以改

final Student stu = new Student(1,"assd");

stu.setAge(12); // 这里是可以的,因为改变的是堆内存中的数据,引用还是指的这一个堆内存地址。

stu=new Student(); // 这里是不允许的因为,final类型是不可以变的。

final好处:

1.final关键字提高了性能。JVM和Java应用都会缓存final变量。

2.final变量可以安全的在多线程的环境下共享,而不需要额外的同步开销。

3.使用final关键字,JVM会对方法,变量进行优化。

final修饰的String类

String 类代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。字符串是常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String 对象是不可变的,所以可以共享。

public final class String
 ? ?implements java.io.Serializable, Comparable, CharSequence {
 ? ?/**该值用于字符存储。  */
 ? ?private final char value[];

 ? ?/**  缓存字符串的哈希代码*/
 ? ?private int hash; // Default to 0

 ? ?/** 使用jdk1.0.2中的serialVersionUID实现互操作性*/
 ? ?private static final long serialVersionUID = -6849794470754667710L;

 ? ?/**
 ? ? * 类字符串在序列化流协议中是特殊大小写的。
 ? ? */
 ? ?private static final ObjectStreamField[] serialPersistentFields =
 ? ? ? ?new ObjectStreamField[0];
 ? ?/**
 ? ? *初始化新创建的{@code String}对象,使其表示空字符序列。请注意,此构造函数的用法是没有必要,因为字符串是不可变的。
 ? ? */
 ? ?public String() {
 ? ? ? ?this.value = "".value;
 ?  }
直接赋值方式创建对象是在方法区的常量池
String str="hello";//直接赋值的方式

通过构造方法创建字符串对象是在堆内存
String str=new String("hello");//实例化的方式

1)直接赋值(String str = "hello"):只开辟一块堆内存空间,并且会自动入池,不会产生垃圾。

2)构造方法(String str=  new String("hello");):会开辟两块堆内存空间,其中一块堆内存会变成垃圾被系统回收,而且不能够自动入池,需要通过public  String intern();方法进行手工入池。

在开发的过程中不会采用构造方法进行字符串的实例化。

Q&A String的不可变性

Strings are constant; their values cannot be changed after theyare created. String buffers support mutable strings.Because String objects are immutable they can be shared. 
 ? ?For example:
 String str = "abc";
 与下面的相等;
 * ? ? char data[] = {'a', 'b', 'c'};
 * ? ? String str = new String(data);
 * Here are some more examples of how strings can be used:
 * 
 * ? ? System.out.println("abc");
 * ? ? String cde = "cde";
 * ? ? System.out.println("abc" + cde);
 * ? ? String c = "abc".substring(2,3);
 * ? ? String d = cde.substring(1, 2);
 * 
*

Q&A 为何String设计为不可变?

1、运行时常量池的需要,节省内存空间。

  比如执行 String s = "abc";执行上述代码时,JVM首先在运行时常量池中查看是否存在String对象“abc”,如果已存在该对象,则不用创建新的String对象“abc”,而是将引用s直接指向运行时常量池中已存在的String对象“abc”;如果不存在该对象,则先在运行时常量池中创建一个新的String对象“abc”,然后将引用s指向运行时常量池中创建的新String对象。这样在运行时常量池中只会创建一个String对象"abc",这样就节省了内存空间。

2、同步

  因为String对象是不可变的,所以是多线程安全的,同一个String实例可以被多个线程共享。这样就不用因为线程安全问题而使用同步。

3、允许String对象缓存hashcode

  查看上文JDK1.8中String类源码,可以发现其中有一个字段hash,String类的不可变性保证了hashcode的唯一性,所以可以用hash字段对String对象的hashcode进行缓存,就不需要每次重新计算hashcode。所以Java中String对象经常被用来作为HashMap等容器的键。

4、安全性

  如果String对象是可变的,那么会引起很严重的安全问题。比如,数据库的用户名、密码都是以字符串的形式传入来获得数据库的连接,或者在socket编程中,主机名和端口都是以字符串的形式传入。因为String对象是不可变的,所以它的值是不可改变的,否则黑客们可以钻到空子,改变String引用指向的对象的值,造成安全漏洞。

Q&A String s = new String("xyz");创建了几个String Object?二者之间有什么区别?

两个或一个,”xyz”对应一个对象,这个对象放在字符串常量缓冲区,常量”xyz”不管出现多少遍,都是缓冲区中的那一个。New String每写一遍,就创建一个新的对象,它一句那个常量”xyz”对象的内容来创建出一个新String对象。如果以前就用过’xyz’,这句代表就不会创建”xyz”自己了,直接从缓冲区拿。

对象:

对象是通过new关键字来创建的,通过引用来接收对象,当对象创建出来后引用就会为对象分配内存,new字是创建对象的操作符,对象的比较有两种形式:

1.“==”运算符是用来比较两个对象引用的地址是否相等,

2.“equal()”方法是来比较两对象引用的内容是否相等。对象的销毁是引用结束后就会被垃圾处理器进行回收;

Q&A 创建对象的方法:

1.使用new关键字。

2.使用Class类中的newInstance方法,newInstance方法调用无参构造方器创建对象。Class.forName.newInstance;

3.使用clone方法、

4.反序列化。

Q&A 对象的产生过程以及存储:

对象的产生:

new将对象存储在堆中,所以用new创建一个对象---特别小的,简单的变量,往往不是很有效。因此对于(基本类型)java不用new来创建这样的变量,而是创建一个并非是引用的“自动”变量。这个变量的值直接存储"值"到堆栈中。

程序创建,运行时对象是如何分配呢?内存是怎样分配呢?

对象产生的时机 类加载,然后进行对象的实例化:

#####Q&A 什么时候会进行类加载?

1.创建类的实例,也就是new一个对象

2.访问某个类或接口的静态变量,或者对该静态变量赋值

3.调用类的静态方法

4.反射(Class.forName("A"))

5.初始化一个类的子类(会首先初始化子类的父类)

6.JVM启动时标明的启动类,即文件名和类名相同的那个类

new ObjectInitTest() 对象的产生过程 1.JVM会在ObjectInitTest.class文件 2.先加载类级别的成员(静态成员变量 静态块初始化) 3.再加载对象级别的成员(实例成员变量 实例块初始化)

Q&A什么时候进行对象的实例化?

类加载成功(或已加载过)后,就开始进行对象的实例化了。对象的实例化依次进行了如下几个步骤:

1.对象在堆中的内存空间分配

2.初始化零值,这时会将实例变量都赋予零值

3.设置对象头,对象头保存了一些对象在运行期的状态信息,包括类信息地址(知道对象是属于哪个类的)、hashcode(用于hashmap和hashset等hash结构中)、GC分代年龄(可以依此确定对象何时该放入老年代)等

4.init方法执行,这时对变量的实例变量进行初始化

对象初始化的过程也是线程安全的动作。

StringBuffer StringBulider String 的区别:

StringBuffer线程安全,StringBulider线程不安全,底层实现StringBuffer比StringBulider多一个Synchronized.从源码中可以看得到:

StringBuffer源码分析:
@Override
 ? ?public synchronized int length() {
 ? ? ? ?return count;
 ?  }

 ? ?@Override
 ? ?public synchronized int capacity() {
 ? ? ? ?return value.length;
 ?  }


 ? ?@Override
 ? ?public synchronized void ensureCapacity(int minimumCapacity) {
 ? ? ? ?if (minimumCapacity > value.length) {
 ? ? ? ? ? ?expandCapacity(minimumCapacity);
 ? ? ?  }
 ?  }

 ? ?/**
 ? ? * @since ? ?  1.5
 ? ? */
 ? ?@Override
 ? ?public synchronized void trimToSize() {
 ? ? ? ?super.trimToSize();
 ?  }

 ? ?/**
 ? ? * @throws IndexOutOfBoundsException {@inheritDoc}
 ? ? * @see ? ? ?  #length()
 ? ? */
 ? ?@Override
 ? ?public synchronized void setLength(int newLength) {
 ? ? ? ?toStringCache = null;
 ? ? ? ?super.setLength(newLength);
 ?  }

 ? ?/**
 ? ? * @throws IndexOutOfBoundsException {@inheritDoc}
 ? ? * @see ? ? ?  #length()
 ? ? */
 ? ?@Override
 ? ?public synchronized char charAt(int index) {
 ? ? ? ?if ((index < 0) || (index >= count))
 ? ? ? ? ? ?throw new StringIndexOutOfBoundsException(index);
 ? ? ? ?return value[index];
 ?  }

String 是否可以继承,“+”如何实现的,与StringBuffer区别?

java中通过使用“+”符号串联时实际是使用的StringBuilder实例的appdenf()方法来实现的。

构造器

考虑到在初始化期间要自动代用构造器,构造器采用与类名相同的名称,在java中“初始化”和“创建”捆绑在一起,两者不能分离。

  • 是一个类创建对象的根本途径,如果一个类没有构造器,这个类通常无法创建实例。因此, Java语言提供了一个功能:如果程序员没有为一个类编写构造器,则系统会为该类提供一个默认的构造器静态变量调用:
  • Java编程时不要使用对象去调用static修饰的Field、方法,而是应该使用类去调用static修饰的Field、方法!如果在其他Java代码中看到对象调用static修饰的Field、方法的情形,完全可以把这种用法当成假象,将其替换成用类来调用static修饰的Field、方法的代码

相关推荐

程序员请收好:10个非常有用的 Visual Studio Code 插件

一个插件列表,可以让你的程序员生活变得轻松许多。作者|Daan译者|Elle出品|CSDN(ID:CSDNnews)以下为译文:无论你是经验丰富的开发人员还是刚刚开始第一份工作的初级开发人...

PADS在WIN10系统中菜单显示不全的解决方法

决定由AD转PADS,打开发现菜单显示不正常,如下图所示:这个是由于系统的默认字体不合适导致,修改一下系统默认字体即可,修改方法如下:打开开始菜单-->所有程序-->Windows系统--...

一文讲解Web前端开发基础环境配置

先从基本的HTML语言开始学习。一个网页的所有内容都是基于HTML,为了学好HTML,不使用任何集成工具,而用一个文本编辑器,直接从最简单的HTML开始编写HTML。先在网上下载notepad++文...

TCP/IP协议栈在Linux内核中的运行时序分析

本文主要是讲解TCP/IP协议栈在Linux内核中的运行时序,文章较长,里面有配套的视频讲解,建议收藏观看。1Linux概述  1.1Linux操作系统架构简介Linux操作系统总体上由Linux...

从 Angular Route 中提前获取数据

#头条创作挑战赛#介绍提前获取意味着在数据呈现在屏幕之前获取到数据。本文中,你将学到,在路由更改前怎么获取到数据。通过本文,你将学会使用resolver,在AngularApp中应用re...

边做游戏边划水: 基于浅水方程的水面交互、河道交互模拟方法

以下文章来源于腾讯游戏学堂,作者Byreave篇一:基于浅水方程的水面交互本文主要介绍一种基于浅水方程的水体交互算法,在基本保持水体交互效果的前提下,实现了一种极简的水面模拟和物体交互方法。真实感的...

Nacos介绍及使用

一、Nacos介绍Nacos是SpringCloudAlibaba架构中最重要的组件。Nacos是一个更易于帮助构建云原生应用的动态服务发现、配置和服务管理平台,提供注册中心、配置中心和动态DNS...

Spring 中@Autowired,@Resource,@Inject 注解实现原理

使用案例前置条件:现在有一个Vehicle接口,它有两个实现类Bus和Car,现在还有一个类VehicleService需要注入一个Vehicle类型的Bean:publicinte...

一文带你搞懂Vue3 底层源码

作者:妹红大大转发链接:https://mp.weixin.qq.com/s/D_PRIMAD6i225Pn-a_lzPA前言vue3出来有一段时间了。今天正式开始记录一下梗vue3.0.0-be...

一线开发大牛带你深度解析探讨模板解释器,解释器的生成

解释器生成解释器的机器代码片段都是在TemplateInterpreterGenerator::generate_all()中生成的,下面将分小节详细展示该函数的具体细节,以及解释器某个组件的机器代码...

Nacos源码—9.Nacos升级gRPC分析五

大纲10.gRPC客户端初始化分析11.gRPC客户端的心跳机制(健康检查)12.gRPC服务端如何处理客户端的建立连接请求13.gRPC服务端如何映射各种请求与对应的Handler处理类14.gRP...

聊聊Spring AI的Tool Calling

序本文主要研究一下SpringAI的ToolCallingToolCallbackorg/springframework/ai/tool/ToolCallback.javapublicinter...

「云原生」Containerd ctr,crictl 和 nerdctl 命令介绍与实战操作

一、概述作为接替Docker运行时的Containerd在早在Kubernetes1.7时就能直接与Kubelet集成使用,只是大部分时候我们因熟悉Docker,在部署集群时采用了默认的dockers...

在MySQL登录时出现Access denied for user ~~ (using password: YES)

Windows~~~在MySQL登录时出现Accessdeniedforuser‘root‘@‘localhost‘(usingpassword:YES),并修改MySQL密码目录适用...

mysql 8.0多实例批量部署script

背景最近一个项目上,客户需要把阿里云的rdsformysql数据库同步至线下,用作数据的灾备,需要在线下的服务器上部署mysql8.0多实例,为了加快部署的速度,写了一个脚本。解决方案#!/bi...