首页 > 技术文章 > hashCode、匿名内部类、部分数组

wzd19901129 2021-02-14 21:24 原文

2021.02.14
第九次记录
情人节和大年初三重叠的一天
今天主要学习hashCode、匿名内部类、部分数组(数组没学完)
**课堂笔记1:**
/*
object类中的hashcode方法:
1.源代码:
public int hashCode()
2.这个方法不是抽象方法,带有native关键字,底层调用的是C++程序。
3.hashCode返回对象的哈希码值:
实际上就是一个java对象的内存地址,经过哈希算法,得出的一个值。
所以hashCode()方法的执行结果可以等同看做一个java对象的内存地址。
*/
**代码演示1:**

```java
public class AbouthashCode {
public static void main(String[] args) {
Object o = new Object();
System.out.println(o.hashCode());
MyClass mc = new MyClass();
System.out.println( mc.hashCode());
}
}
class MyClass {

}
```
输出结果:
1956725890
356573597
**课堂笔记2:**
/*
匿名内部类:
1.内部类:在类的内部又定义了一个新的类。
2.内部类的分类:
静态内部类:类似于静态变量;
实例内部类:类似于实例变量;
局部内部类:类似于局部变量;
3.注意:使用内部类编写的代码可读性差,能不用尽量不用。
4.匿名内部类是局部内部类的一种。
因为这个类没有名字,得名匿名内部类
5.学习匿名内部类主要是以后看到别人这样写代码的时候能够理解。
并不代表以后都要这样写。因为匿名内部类有两个缺点:
第一:太复杂,太乱,可读性差
第二:类没有名字,以后向重复使用,不能用
*/
**代码演示2:**

```java
class 匿名内部类 {
//由于前面有static,被称为“静态内部类”
static class Inner1 {

}
//没有static,被称为“实例内部类”
class Inner2 {

}
public void dosome(){
//局部内部类
class Inner3 {

}
}
public void doOther(){

}

public static void main(String[] args) {
Mymath mm = new Mymath();
// ComputeUmpl cu = new ComputeUmpl();
//mm.mysum(new ComputeUmpl(), 100, 200);
mm.mysum(new Compute(){
//这就叫匿名内部类
public int sum(int a, int b) {
return a + b;
}
}, 100, 200);
}
}
//负责计算的接口
interface Compute {
//抽象方法
int sum(int a, int b);
}
/*
class ComputeUmpl implements Compute {
public int sum(int a, int b){
return a + b;
}
}
*/
//数学类
class Mymath {
//数学求和方法
public void mysum(Compute c, int x, int y){
int retValue = c.sum(x, y);
System.out.println(x + "+" + y + "=" + retValue);
}
}
```
输出结果:
100+200=300
**课堂笔记3:**
/*
Array
1.java中的数组是一种引用数据类型。不属于基本数据类型。数组的父类是Object类。
2.数组实际上是一个容器,可以同时容纳多个元素。(数组是一个数据的结合)
数组:字面意思是“一组数据”
3.数组当中可以存储基本数据类型的数据,也可以存储引用数据类型数据。
4.数组因为是引用数据类型,所以数组对象是在堆内存当中。(数组是存储在堆当中的)
5.数组当中如果存储的是“java对象”的话,实际上存储的是对象的“引用(内存地址)”。
6.数组一旦创建,在java中规定,长度不可变。(数组长度不可变)
7.数据的分类包括:一维数据、二维数组、三维数组、多维数组...(一维数组较多,二维数组偶尔使用)
8.所有的数组对象都有Length属性(java自带的),用来获取数组元素中的个数。
9.java中的数组要求数组中的元素统一。比如int类型数组只能存储int类型。
10.数组在内存方面存储的时候,数组中的元素内存地址(存储的每一个元素都是有规则的挨着排列的)
是连续的。内存地址连续。这是数组存储元素的特点(特色)。数组实际上是一种简单的数据结构。
11.所有的数组都是拿“第一个小方框的内存地址”作为整个数组对象的内存地址。
(数组中首元素的内存地址作为整个数组的内存地址)
12.数组中每一个元素都是有下标的,下标从0开始,以1递增,最后一个下标是:length - 1
下标非常重要,因为我们对数组中元素进行“存取”的时候,都需要通过下标来进行。
13.数组这种数据结构的优点和缺点是什么?
优点:查询/查找/检索某个下标上的元素时效率极高。可以说是查询效率最高的一个数据结构。
为什么检索效率高?
第一:每一个元素的内存地址在空间存储上是连续的。
第二:每一个元素类型相同,所以占用空间大小一样。
第三:知道第一个元素内存地址,知道每一个元素占用空间的大小,又知道下标,所以
通过一个数学表达式就可以计算出某个下标上元素的内存地址。直接通过内存地址定位
元素,所以数组的检索效率是最高的。
数组中存储100个元素,或者存储100万个元素,在元素查询/检索方面,效率是相同的,
因为数组中元素查找的时候不会一个一个找,是通过数学表达式计算出来的。
缺点:
第一:由于为了保证数组中每个元素的内存地址连续,所以在数组上随机删除或者增加元素的时候,
效率较低,因为随机增删元素会涉及到后面元素统一向前或者向后位移的操作。
第二:数组不能存储大数据量,因为很难在内存空间上找到一块特别大的连续的内存空间。
注意:对于数组中最后一个元素的增删,是没有效率影响的。
14.怎么声明/定义一个一维数组:
语法格式:
int[] array1;
double[] array2;
boolean[] array3;
String[] array4;
Object[] array5;
15.怎么初始化一个一维数组呢?
包括两种方式:静态初始化一维数组、动态初始化一维数组
静态初始化一维数组语法格式:
int[] array = {100,1,565,486,22};
动态初始化一维数组语法格式:
int[] array = new int[5]; 这里的5表示数组的元素个数
初始化一个5个长度的int类型数组,每个元素默认值为0
String[] array = new String[6]; 初始化6个长度的String类型数组,每个元素默认值为null
15.什么时候使用静态初始化方式,什么时候使用动态初始化方式
当你创建数组的时候,确定数组中存储哪些具体的元素时,采用静态初始化方式
当你创建数组的时候,不确定将来数组中存储哪些具体的元素时,可以采用动态初始化方式,预先分配内存空间。
*/
**代码演示3:**

```java
public class ArrayDemo01 {
public static void main(String[] args) {
//声明一个int类型的数组,使用静态初始化的方式
int[] a = {1, 100, 10, 20, 55, 689};
//所有数据对象都有length属性
System.out.println("数组中元素的个数:" + a.length);
//数组中每一个元素都有下标
//通过下标对数组中的元素进行存和取
//取(读)
System.out.println("第一个元素:" + a[0]);
System.out.println("最后一个元素:" + a[a.length - 1]);
System.out.println("-------我是分割线-------");
//存(改),把第一个元素修改为111
a[0] = 111;
//把最后一个元素修改为0
a[a.length - 1] = 0;
System.out.println("第一个元素:" + a[0]);
System.out.println("最后一个元素:" + a[a.length - 1]);
System.out.println("-------我是分割线-------");
//一维数组怎么遍历
for (int i = 0; i < a.length; i++){
System.out.println(a[i]); //i是从0到5,是下标
//System.out.println(a[6]); //ArrayIndexOutOfBoundsException数组下标越界异常
}
System.out.println("-------我是分割线-------");
//从最后一个元素遍历到第一个元素
for (int i = a.length - 1; i >= 0; i--){
System.out.print(a[i] + ";");
}
}
}
```
输出结果:
数组中元素的个数:6
第一个元素:1
最后一个元素:689
-------我是分割线-------
第一个元素:111
最后一个元素:0
-------我是分割线-------
111
100
10
20
55
0
-------我是分割线-------
0;55;20;10;100;111;
**代码演示4:**

```java
public class ArrayDemo02 {
public static void main(String[] args) {
//声明/定义一个数组,采用动态初始化的方式
int[] a = new int[4]; //创建长度为4的int数据,数组中每个元素的默认值为0
//遍历数组
for (int i = 0; i < a.length; i++) {
System.out.println("数组中下标为" + i + "的元素是:" + a[i]);
}
System.out.println("-------我是分割线-------");
//初始化一个Object类型的数组,采用动态初始化方式
Object[] ob = new Object[3]; //3个长度,动态初始化,每个元素的默认值为null
for (int i = 0; i < ob.length; i++) {
System.out.println(ob[i]);
}
System.out.println("-------我是分割线-------");
String[] strs = new String[3];
for (int i = 0; i < strs.length; i++){
System.out.println(strs[i]);
}
//采用静态初始化的方式
System.out.println("-------我是分割线-------");
String[] strs2 = {"ab", "ac", "ad"};
for (int i = 0; i < strs2.length; i++){
System.out.println(strs[i]);
}
System.out.print("strs2的长度为:" + strs2.length + "," + "元素分别是:");
System.out.println(strs2[0] + "," + strs2[1] + "," + strs2[strs2.length - 1]);
}
}
```
输出结果:
数组中下标为0的元素是:0
数组中下标为1的元素是:0
数组中下标为2的元素是:0
数组中下标为3的元素是:0
-------我是分割线-------
null
null
null
-------我是分割线-------
null
null
null
-------我是分割线-------
null
null
null
strs2的长度为:3,元素分别是:ab,ac,ad
**代码演示5:**

```java
public class ArrayDemo03 {
public static void main(String[] args) {
int[] x = {1, 2, 3, 4};
printArray(x);
String[] printArray = {"ad", "ac", "ad"};
printArray(printArray);
}
public static void printArray(int[] array){
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
public static void printArray(String[] args){
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
}
}
```
输出结果:
1
2
3
4
ad
ac
ad
**代码演示6:**

```java
//当一个方法的参数是一个数组的时候,还可以采用这种方式传
public class ArrayDemo04 {
public static void main(String[] args) {
//静态初始化一维数组
int[] a = {1, 2, 3};
printArray(a);
System.out.println("-------我是分割线-------");
// printArray({1, 2, 3}); 没有这种语法
//如果直接传进一个静态数组的话,语法必须这样写
printArray(new int[]{1, 2, 3});
System.out.println("-------我是分割线-------");
//动态初始化一维数组
int[] b = new int[3];
printArray(b);
System.out.println("-------我是分割线-------");
printArray(new int[3]);
}
public static void printArray(int[] array){
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
```
输出结果:
1
2
3
-------我是分割线-------
1
2
3
-------我是分割线-------
0
0
0
-------我是分割线-------
0
0
0
**代码演示7:**

```java
/*
main方法上面的“String[] args”有什么用
分析谁负责调用main方法--->JVM
JVM调用main方法的时候,会自动传一个String数组过来
所以main方法上面的“String[] args”数组主要是用来接收用户输入参数的
*/
public class ArrayDemo05 {
//这个方法程序员负责写出来,JVM负责调用。JVM调用的时候一定会传一个String数组过来
public static void main(String[] args) {
//JVM默认传递过来的这个数组的长度:默认0
//通过测试得出args不是null。不是空引用
System.out.println("JVM给传递过来的String数组的长度是:" + args.length);
for (int i = 0; i < args.length; i++){
System.out.println(args[i]);
}
}
}
```
输出结果:
JVM给传递过来的String数组的长度是:0
**代码演示8:**

```java
//模拟一个系统,假设这个系统要使用,必须输入用户名和密码
public class ArrayDemo06 {
public static void main(String[] args) {
if (args.length != 2){
System.out.println("使用该系统时必须提供用户名和密码,例如:张三 123");
return;
}
//取出用户名
String usename = args[0];
//取出密码
String password = args[1];
//假设用户名为admin,密码为123表示登录成功。其他一律失败。
if ("admin".equals(usename) && "123".equals(password)) {
System.out.println("登陆成功,欢迎使用");
}else{
System.out.println("登录失败,用户名不存在或者密码错误");
}
}
}
```

输出结果:
登陆成功,欢迎使用

注意:必须先输入admin 123,才会登录成功。

推荐阅读