java进阶第二讲-数组、String类

1 回顾一下Object

Object中的方法:public native int hashCode();带有native关键字的方法调用的是底层C++的dll文件这种方法我们在工具中看不到具体的实现,当然也可以去其他地方找相关的实现代码。hashCode()它是一个对象在堆中的内存地址经过hash算法计算之后又进行了进制的转换得出的结果.返回值是int问题:如果两个对象的hashCode()值一样,说明什么问题?是同一个对象hashCode()方法有什么用?因为hashCode()方法计算的对象是内存地址,内存地址对于一个对象来讲是惟一的,所以hashCode()算法算出来的也是唯一值。因此这个方法可以判断:1. 一个对象是否存在。2. 一个对象与另一个对象是否是同一个对象。3. 两个对象的hashCode值比较的话,就相当于引用之间使用"==",只能比较地址,不能比较值。protected void finalize() throws Throwable { }
Called by the garbage collector on an object
when garbage collection determines that there are no more references to the object.// 当GC发现没有任何的引用指向当前对象的时候,这个方法就会被GC自动调用// 这个方法被调用的时候,对象被回收了吗?还没有,也就是说,对象在被GC回收之前,// GC会自动调用这个finalize()方法这个方法其实就是SUN公司java工程师为程序员准备的一个对象销毁之前的时刻。可以直观的观测对象销毁之前的状态。
public class AarrayTest01 {@Overrideprotected void finalize() throws Throwable {System.out.println("对象即将被GC回收!");}public static void main(String[] args) throws Throwable {Object o = new Object();// 翻看源码,回到上一次停留的地方ctr + alt + ←System.out.println(o.hashCode());Object o1 = new Object();// 翻看源码,回到上一次停留的地方ctr + alt + ←System.out.println(o1.hashCode());AarrayTest01 a = new AarrayTest01();for (int i = 0; i < 100000; i++) {System.out.println(new AarrayTest01());}}
}

2 数组

  • 声明:declare 在java中只能声明一个变量,也就是说没有给这个变量赋初始值。
  • 定义:define 在java中,定义一个变量,就是给变量赋值的过程
int[] a = {1,2}; // 推荐这种方式,这种格式更有利于理解数组
int a1[];// 这种方式也行,API中大部分是这种格式
public class AarrayTest01 {public static void main(String[] args) throws Throwable {// 数组int[] a = {1,2}; // 推荐这种方式,这种格式更有利于理解数组int a1[];// 这种方式也行,API中大部分是这种格式System.out.println(a);// 什么结果?内存中的首地址,什么形式呢?// [I@16d3586----类型名 + @ + 内存地址hash后的十六进制表示// [I@16d3586 格式其实是Object对象的toString()执行之后才会得到的结果// System.out.println(a);它自动调用了Objcet的toString()方法// 为什么数组会自动调用Object类的toString方法?说明数组也是引用类型的。// 它的父类是Object。只有这种解释。// 什么是引用类型? 类型 变量名,这个变量名指向的是一块内存空间,我们说它就是引用类型。// A a = 内存地址; 这种形式就是引用类型。java当中,只有两种类型,基础数据类型和引用类型// 引用类型所指向的内存地址实际是对象(常量、static修饰的变量)的内存地址。// 这也说明了,数组是引用类型。我们也可以推断,数组的本身是保存在堆中的。}
}
  • Object类的简介
/*** Class {@code Object} is the root of the class hierarchy.* Every class has {@code Object} as a superclass. All objects,* including arrays, implement the methods of this class.*/
  • 数组是一种数据类型,但是它不是基础数据类型,是引用数据类型。
  • 基础数据类型:byte short int long float double boolean char
  • 除去这8中之外,全是引用类型。
public class AarrayTest01 {public static void main(String[] args) throws Throwable {// 数组int[] a = {1,2}; // 推荐这种方式,这种格式更有利于理解数组int a1[];// 这种方式也行,API中大部分是这种格式System.out.println(a.getClass().getName());// a.getClass()后为什么可以直接"."getName():因为getClass()返回了引用(一个对象的引用)// 为什么返回的是引用,而不是对象?// 因为对象在堆中,很大,引用只是一个地址,很小,从效率上来讲,你说是传引用还是传对象?// 我们一般讲传输,都是要通过网络、通过电脑中的bus,// 传一个几个Byte数据好,还是传几百M上G的数据好呢?---传引用更好// 好比,你在银行有1个亿的存款,你去取钱,是拿一张有一个亿的卡好呢,还是拿1亿的现金?// 你要拿1亿现金,家里先得修一个装得下1亿现金的金库。如果你拿一张卡,就是拿了一个引用// 这个引用指向的是银行的金库,自己没有必要再修一个金库。// 在java中,基础数据类型都是传值// 引用数据都是传引用(这里的传:实参和形参之间的传递方式,方法的返回值返回的方式)// java做好了封装,引用类型都是传递的都是引用。返回值类型也都是引用,没有返回过值。// 在C中C++中,可以传值,也就是说可以传指针所指向的内存地址的值。但这样不好。// 你想,你传一个值出来,其实是做了一份拷贝,那么你就一定要有一块同等大小的空间去接。// 浪费空间。由于值可能很大,传输上耗时,效率低下。// 谁能"."?"类名."和"引用.","类名."静态的属性或者是方法;"引用."成员属性或者是方法// 一个方法的返回值类型有哪些?void 基础数据类型 引用数据类型// 基础数据类型可以"."方法吗?不能的。void返回的是null,null也是一个引用类型// 它不能"."任何东西,一旦"."就会报NullPointerException// 能"."成员方法的只有引用类型。}
}
  • 通过实验,我们看到了数组拥有Object类中所有的方法。所以我们也能断定它是Object的子类,数组也是引用类型。数组的引用如果被置空,也会报空指针异常。
  • 数组有一个属性:length
    • length属性,指的是数组的长度。
    • 任何一个数组都有这个属性。

2.1 数组的类型

  • 基础数据类型的数组:int[] a;这意味着,a所指向的数组中保存的是int类型的数据
  • 引用类型的数组:Person[] p;这意味着,p所指向的数组中保存的是Person类型的对象的引用。

2.2 数组的定义

  • 静态初始化

    • int[] a = {1,2,3,4};
  • 动态初始化
    • int[] a = new int[大小];
    • 然后再给数组中的元素赋值。

2.3 访问数组中元素的方式

  • 取下标的方式进行访问,下标从0开始到length-1
  • 注意:在java中,“=” 后面的大括号中的内容就是一个对象,在javascript中也是这样。
  • 这种用法,目前来说只对数组成立。数组赋值的时候,int[] a = {……};这是静态的初始化方式

2.4 数组的内存图

2.5 两种初始化方式的差别

  • 静态初始化是在已知数组元素值的时候,可以直接静态初始化。
  • 静态初始的时候,实际上是根据{}中的值的个数来分配了数组的内存空间
  • 动态初始化的时候,实际上是根据new int[初始化大小]中的初始化大小的值来分配内存空间
  • 动态初始化是指,后续可以给数组中的元素进行赋值。
  • 如果是静态初始化,一开始初始化的时候在{}中没有给值,如果在后续赋值,会抛出Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 0。数组索引越界异常。为什么?因为静态初始化的时候,JVM会根据{}中的值的个数在堆中给数组分配大小。
  • 这也说明一个问题,一旦数组的大小被确定之后,是不能改变的。
int[] arr = {};
arr[0] = 1;
//Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
int[] arr1 = new int[3];
arr1[3] = 100;//ArrayIndexOutOfBoundsException: 3
  • 数组一旦被创建,其大小就固定了,无论静态的还是动态的。大小是固定的。数组的大小是不可以被改变的。也就是说length值已经被确立了。我们可以想象,这个length属性一定被final修饰。

2.6 数组的优缺点

  • 优点

    • 数组在堆中是一块连续的内存空间
    • 数组中存放的是同一类型的值
    • 我们要访问某个元素,是通过数组的下标进行访问,因为连续,元素的类型相同,因为每个元素的大小都是固定的,我们又能拿到首元素的地址,所以访问的速度会很快,效率很高
  • 缺点:

    • 数组中的元素存放在一段连续的内存空间上,而且数组一旦被创建,大小就固定了,不能改变。对于超出当前数组大小范围的数据元素的存放,就需要另外开辟一个更大的数组空间,进行数组的拷贝。这样增加系统的开销。
    • 数组的删除和增加,都会造成大量的数据移动,效率不高。

2.7 数组的扩容

  • 数组的扩容,本质上没有在原有的数组所在的堆内存空间上进行扩展,而是另外重新开辟了一块内存空间。也就是说,原来的int[] a = 0x1234;扩容以后的int[] a 不再指向0x1234,而是指向了新开辟的数组的内存地址(0x2345)
  • 数组的扩容的步骤:
    第一步:开辟一个更大的数组
    第二步:将原数组中的内容拷贝过来
    第三步:将要存入的元素追加到更大数组中相应的位置
    第四步:将原数组的引用指向新数组的对象

2.8 为什么推荐使用 “类型[] a”

  • 因为:类型[] 表示是一个数组类型,后边的变量指的是这个数组的引用。
  • 如果是 “类型 标识符[]”这种形式,会让人误解。也很难体现出引用数据类型的特征。
  • 所以,我们推荐使用 类型[] 数组名 的方式

2.9 二维数组

  • 二维数组的形式:
int[][] arr
  • 二维数组的定义
int[][] arr = {{1,2,3}, {4,5,6}, {7}
}; ----静态的方式int[][] arr = new int[3][5]; ----动态的方式

3 String类

public final class String //意味着:这是一个最终的类,没有子类,不能被继承
// All string literals in Java programs,
// such as "abc", are implemented as instances of this class.
// Strings are constant; their values cannot be changed after they are created
这句话什么意思?字符串是常量,它们的值在它们被创建之后不能改变。String str = "abc";is equivalent to:等价于char data[] = {'a', 'b', 'c'};String str = new String(data);分析:常量,什么是常量?存放在哪里?final static修饰的是常量存放在方法区内存中String的本质是什么?也就是说String是怎么实现的?char[] 数组。我们可以想到,char[]数组中的元素要不能被改变,则一定要被final修饰。String类型的数据全部存放于方法区的"字符串常量池"中。字符串一旦被创建,不能改变。String name = "abc";// 这意味着String是引用类型,name是引用类型的变量名
// 引用类型的变量只能保存地址,不能保存实际的值。
// "abc"不是内存地址,它是一个实实在在的值。
// 所以"abc"赋值给name,实际上是将"abc"存放的内存地址的值给到了name。
// 并不是将"abc"的本身给到了name。那么,"abc"这个字符串一定是一个对象
// 这个对象存放在方法区内存中的字符串常量池中。
// 为什么要怎么做?要将字符串存放到方法区内存中的字符串常量池中?
// 为什么要规划这么一块内存空间?
// 对事物的描述,人类最能接受的方式是字符串。字符串是不是最利于识别的,也是用得最多的
// 使用率太高了,如果把它放在堆中,是不是很占空间。也很消耗JVM的性能。
// 把字符串做成常量的话,利用率是不是高一些。重复在堆中创建销毁的次数是不是得到了缓解。


// 测试代码
public class AarrayTest01 {public static void main(String[] args) throws Throwable {String str = "abc";str = "def";// 这是什么意思?是两个字符串对象被创建了,def的地址给到了str这个引用类型变量// 常量池中仍然存在"abc"// 字符串常量一旦建立就不能被改变System.out.println("abc".hashCode());System.out.println(str.hashCode());str += "d";// 这里是合并了吗?覆盖了原来的abc吗?没有,创建了一个新的System.out.println(str);String str1 = "abc";String string = "abc";System.out.println(str1 == string);System.out.println(string.hashCode());System.out.println("------------------");// 请问这里创建了几个字符串对象?3 存在于字符串常量池中的有几个?3// "abc" "d" "abcd"// str = str + "d" ----> "abcd"}
}

ng = “abc”;
System.out.println(str1 == string);
System.out.println(string.hashCode());
System.out.println("------------------");

    // 请问这里创建了几个字符串对象?3 存在于字符串常量池中的有几个?3// "abc" "d" "abcd"// str = str + "d" ----> "abcd"
}

}


java进阶第二讲-数组、String类相关推荐

  1. JAVA进阶教学之(String类的构造方法)

    试题: 问:以下程序一共创建了几个对象 public class StringTest03 {public static void main(String[] args) {String s1=new ...

  2. JAVA进阶教学之(String类的常用方法)

    接下来我们进入的学习章程,就是可以通过查阅帮助文档进行实际的应有 1. char charAt(int index) 返回指定索引的 char价值. 代码示例: public class String ...

  3. Java黑皮书课后题第10章:**10.23(实现String类)在Java库中提供了String类,给出你自己对下面方法的实现(将新类命名为MyString2)

    **10.23(实现String类)在Java库中提供了String类,给出你自己对下面方法的实现(将新类命名为MyString2) 题目 简短的吐槽 代码:这里将类名改用Test23_MyStrin ...

  4. java源码详解——String类

    java源码详解--String类目录: Java String 类 下面开始介绍主要方法: Java charAt() 方法 Java compareTo() 方法 int compareTo(St ...

  5. 【java进阶06:数组】使用一维数组模拟栈数据结构 使用二维数组模拟酒店,酒店管理系统 Arrays工具类 冒泡排序算法、选择排序算法、二分法

    目录 数组 二维数组 总结 作业 Arrays工具类 数组 数组总结 及 静态初始化一维数组 /* Array:1.java语言中的数组是一种引用数据类型,不属于基本数据类型,数组的父类是Object ...

  6. Java技术——你真的了解String类的intern()方法吗

    0.引言 什么都先不说,先看下面这个引入的例子: [java] view plain copy String str1 = new String("SEU")+ new Strin ...

  7. Java学习笔记20(String类应用、StringBuffer类、StringBuilder类)

    1.获取指定字符串中大小写和数字的个数: package demo;public class StringTest {public static void main(String[] args) {g ...

  8. Java学习笔记七——数组工具类Arrays

    数组工具类Arrays Java提供的Arrays类里包含的一些static修饰的方法可以直接操作数组.若将里面的方法用熟的话,那开发效率会大大提高.下面介绍其中的方法. List<T> ...

  9. Java中是否可以继承String类,为什么

    详细解析: 1. 关于final修饰符 参考文章:  浅析Java中的final关键字 根据程序上下文环境,Java关键字final有"这是无法改变的"或者"终态的&qu ...

最新文章

  1. Java项目:前后端分离网上手机商城平台系统设计和实现(java+vue+redis+springboot+mysql+ssm)
  2. ccf--20140903--字符串匹配
  3. 无限轮播图片的实现原理
  4. 调研了10家公司的技术架构,我总结出了一套大数据平台的套路
  5. 【python】 邮件发送-----zmail
  6. 遥感高光谱分类文献阅读:Exploring Hierarchical Convolutional Features for Hyperspectral Image Classification
  7. 如何将网络监控摄像头中的网络流 RTSP 转换成 M3U8 流并嵌入微信公众号
  8. 虾皮「光速大裁员」:7分钟大会后,软件瞬间查无此人
  9. Struck Structured Output Tracking with Kernels阅读笔记
  10. 2022-2028年全球与中国辐射屏蔽纺织品行业深度分析
  11. 关于computer vision的会议及vision guys-机器学习与视觉大牛族谱深度挖掘
  12. Play 1.x 学习资料汇总
  13. 中国大学慕课第六周编程题
  14. Mysql分组取每组排序后第一个
  15. kubeadm创建k8s集群(1.14.2版本)
  16. natapp邀请码,新用户购买域名可以享受9折优惠
  17. 学生教育云平台登录入口_国家中小学网络云平台登录入口_国家中小学网络云平台...
  18. 1.1.1和1.1.2支持漫游运营商LOGO更换
  19. Python入门(八):文件处理
  20. 门禁系统中的综合布线应用

热门文章

  1. 使用python-opencv告警QObject::moveToThread
  2. one-hot和Embedding
  3. 家国梦自动收取金币、货物、升级建筑、拆相册等脚本
  4. PNPOLY - Point Inclusion in Polygon W. Randolph Franklin
  5. 计算机科学与技术导论的课后题答案,《计算机科学导论》课后习题答案
  6. NI控件之 CWGraph使用(COM)
  7. 大专生三面蚂蚁金服,成为java架构师应该学的知识
  8. IDL学习:语法基础-字符串
  9. [前端] 键盘事件常用操作
  10. 停摆的卡拉VS疯狂的摩拜,共享单车大洗牌时代来临