日历类和日期类转换 并发修改异常 泛型的好处 *各种排序 成员和局部变量 接口和抽象类 多态 new对象内存中的变化

day07

 

  1. ==equals的区别?

==用于比较两个数值 或者地址值是否相同.  equals 用于比较两个对象的内容是否相同

 

  1. StringStringBufferStringBuilder的区别?

String 是一个长度不可变的字符串,不可被修改  StringBuffer是线程不安全的 ,速度慢 StringBuilder是线程安全的.速度快  如果考虑一个字符串需要修改就考虑用StringBuilder.

 

  1. 为什么出现基本数据类型包装类?
  2. 因为基本类型并不具有对象的性质, 包装类具有对象的性质 为其添加了属性和方法

 

  1. 基本数据类型包装类的自动拆装箱是什么?
  2. 是将包装类转换成基本类型  Integer.parseInt()

 

  1. 获取当前时间毫秒值有哪几种方式?
  2. New Date().getTime()   system.cuur time

 

  1. .正则表达式常用的;

 

  1. 日历类和日期类相互转换:

Calendar 转换为Date   

Calendar=Calendar.getInstance()

Date=Calendar.getTime()

 

Date转换为Calendar

Calendar.getInstance()

Calendar.setTime(date)

 

 

  1. DateString类型的转换?

Df=new SimpleDateFormate(格式yyyy-MM-dd)

Date=New Date()

Df.format(date)     

 

String转换成Date

Date=Df.parse(string)

 

 

 

 

1.1 2.并发修改异常

迭代的常规用法中我们要尽量避免在迭代过程中为集合添加/删除数据否则会报错,原因是Java抛出了并发修改异常

迭代过程中并发修改异常的原因为迭代器中”记忆”的集合长度与集合中实际长度不同,而导致出现索引与实际元素不符甚至无限循环的情况发生。

所以在使用Iterator时,避免类似操作,for循环底层为迭代器实现,所以也需要避免类似操作

有些迭代器避免了这样的问题,如ListIterator,但该类并不通用也不常用,实际开发中很少使用,只需要简单了解。

 

1.2 3.增强for循环

增强for循环是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。

1.3 4.使用泛型的好处

l 将运行时期的ClassCastException,转移到了编译时期变成了编译失败。

l 避免了类型强转的麻烦。

 

 

 

Day07

编码表

* a : 97

* A : 65

* 0 : 48

  1. 数组逆序

public static void reverse(int[] arr){

//利用循环,实现数组遍历,遍历过程中,最远端换位

//for的第一项,定义2个变量, 最后,两个变量++ --

for( int min = 0 , max = arr.length-1 ; min < max  ; min++,max--){

//对数组中的元素,进行位置交换

//min索引和max索引的元素交换

//定义变量,保存min索引

int temp = arr[min];

//max索引上的元素,赋值给min索引

arr[min] =  arr[max];

//临时变量,保存的数据,赋值到max索引上

arr[max] = temp;

}

}

 

public class ArrayMethodTest_1{

public static void main(String[] args){

int[] arr = {3,5,7,1,0,9,-2};

//调用数组的逆序方法

reverse(arr);

//看到数组的元素,遍历

printArray(arr);

}

2. 选择排序

解题步骤

* 使用for循环(外层循环),指定数组要循环的圈数(通过图解可知,数组循环的圈数为数组长度 - 1

* 在每一圈中,通过for循环(内层循环)完成数组要比较的第一个元素与该元素后面的数组元素依次比较到数组的最后一个元素,把小的值放在第一个数组元素中

* 在每一圈中,要参与比较的第一个元素由第几圈循环来决定。如上图所示

* 进行第一圈元素比较时,要比较的第一个元素为数组第一个元素,即索引为0的元素

* 进行第二圈元素比较时,要比较的第一个元素为数组第二个元素,即索引为1的元素

* 依次类推,得出结论:进行第n圈元素比较时,要比较的第一个元素为数组第n个元素,即数组索引为n-1的元素

 

 

 

  数组的排序: 一般都是升序排列,元素,小到大的排列

  

  两种排序的方式

 选择排序: 数组的每个元素都进行比较

 冒泡排序: 数组中相邻元素进行比较

 规则: 比较大小,位置交换

*/

public class ArrayMethodTest_2{

public static void main(String[] args){

int[] arr  = {3,1,4,2,56,7,0};

//调用选择排序方法

//selectSort(arr);

printArray(arr);

}

/*

定义方法,实现数组的选择排序

返回值: 没有

参数:  数组

实现步骤:

  1.嵌套循环实现排序

外循环,控制的是一共比较了多少次

内循环,控制的是每次比较了多少个元素

  2. 判断元素的大小值

小值,存储到小的索引

*/

public static void selectSort(int[] arr){

for(int i = 0 ; i < arr.length - 1; i++){

//内循环,是每次都在减少,修改变量的定义

for(int j = i+1 ; j < arr.length ; j++){

//数组的元素进行判断

if(arr[i] > arr[j]){

//数组的换位

int temp = arr[i];

arr[i] = arr[j];

arr[j] = temp;

}

}

}

}

 

 

public static void printArray(int[] arr){

//输出一半中括号,不要换行打印

System.out.print("[");

//数组进行遍历

for(int i = 0 ; i < arr.length ; i++){

//判断遍历到的元素,是不是数组的最后一个元素

//如何判断 循环变量 到达 length-1

if( i == arr.length-1 ){

//输出数组的元素和]

System.out.print(arr[i]+"]");

}else{

//不是数组的最后一个元素,输出数组元素和逗号

System.out.print(arr[i]+",");

}

}

System.out.println();

}

}

 

 

3. 冒泡排序

* b: 解题步骤

* 使用for循环(外层循环),指定数组要循环的圈数(通过图解可知,数组循环的圈数为数组长度 - 1

* 在每一圈中,通过for循环(内层循环)完成相邻的元素值依次比较,把大的值放后面的元素中

* 每圈内层循环的次数,由第几圈循环来决定。如上图所示

* 进行第一圈元素比较时,内层循环次数为数组长度 - 1

* 进行第二圈元素比较时,内层循环次数为数组长度 - 2

* 依次类推,得出结论:进行第n圈元素比较时,内层循环次数为数组长度 - n

 

* c: 案例代码

/*

  数组的排序: 一般都是升序排列,元素,小到大的排列

  

  两种排序的方式

 选择排序: 数组的每个元素都进行比较

 冒泡排序: 数组中相邻元素进行比较

 规则: 比较大小,位置交换

*/

public class ArrayMethodTest_2{

public static void main(String[] args){

int[] arr  = {3,1,4,2,56,7,0};

//调用选择排序方法

//selectSort(arr);

 

//调用冒泡排序方法

bubbleSort(arr);

printArray(arr);

}

/*

   定义方法,实现数组的冒泡排序

   返回值: 没有

参数:  数组

*/

public static void bubbleSort(int[] arr){

for(int i = 0 ; i < arr.length - 1; i++){

//每次内循环的比较,0索引开始, 每次都在递减

for(int j = 0 ; j < arr.length-i-1; j++){

//比较的索引,jj+1

if(arr[j] > arr[j+1]){

int temp = arr[j];

arr[j] = arr[j+1];

arr[j+1] = temp;

}

}

}

}

 

/*

   定义方法,实现功能

   返回值: void

   方法参数: 数组

*/

public static void printArray(int[] arr){

//输出一半中括号,不要换行打印

System.out.print("[");

//数组进行遍历

for(int i = 0 ; i < arr.length ; i++){

//判断遍历到的元素,是不是数组的最后一个元素

//如何判断 循环变量 到达 length-1

if( i == arr.length-1 ){

//输出数组的元素和]

System.out.print(arr[i]+"]");

}else{

//不是数组的最后一个元素,输出数组元素和逗号

System.out.print(arr[i]+",");

}

}

System.out.println(

 

4. 折半查找

* b: 解题步骤

* 定义3个用来记录索引值的变量,变量min记录当前范围最小索引值,初始值为0;变量max记录当前范围最大索引值,初始值为数组长度-1;变量mid记录当前当前范围最中间元素的索引值,初始值为(min+max) / 2

* 使用循环,判断当前范围下,最中间元素值与指定查找的数值是否相等

n 若相等,结束循环,返回当前范围最中间元素的索引值mid

n 若不相等,根据比较结果,缩小查询范围为上一次查询范围的一般

u 中间元素值 要查询的数值大,说明要查询的数值在当前范围的最小索引位置与中间索引位置之间,此时,更新查询范围为:

范围最大索引值 = 上一次中间索引位置 -1

u 中间元素值 要查询的数值小,说明要查询的数值在当前范围的最大索引位置与中间索引位置之间,此时,更新查询范围为:

范围最小索引值 = 上一次中间索引位置 +1

u 在新的查询范围中,更新中间元素值的位置,再次使用最中间元素值与指定查找的数值是否相等。

中间索引值 = (范围最小索引值 +范围最大索引值) / 2;

* 每次查询范围缩小一半后,使用if语句判断,查询范围是否小于0个元素,若小于0个元素,则说明指定数值没有查询到,返回索引值-1

 

###15数组的折半查找代码实现

* A: 案例代码

/*

   数组的查找功能

 在一个数组中,找一个元素,是否存在于数组中,如果存在,就返回索引

 

 普通查询:

   找到元素在数组中出现的索引,如果没有这个 元素,结果就是负数

 

*/

public class ArrayMethodTest_3{

 public static void main(String[] args){

 int[] arr = {1,3,5,7,9,11,15};

 int index = binarySearch(arr,10);

 System.out.println(index);

 

 }

 

 /*

 定义方法,实现,折半查找

 返回值: 索引

 参数: 数组,被找的元素

 实现步骤:

   1. 需要的变量定义

  三个,三个指针

  

   2. 进行循环折半

  可以折半的条件  min <= max

   

   3. 让被找元素,和中间索引元素进行比较

   元素 > 中间索引  小指针= 中间+1

   元素 < 中间索引  大指针= 中间-1

   元素 == 中间索引  找到了,结束了,返回中间索引

   

4. 循环结束,无法折半

  元素没有找到 ,返回-1

 */

 public static int binarySearch(int[] arr, int key){

 //定义三个指针变量

 int min = 0 ;

 int max = arr.length -1 ;

 int mid = 0;

 //循环折半,条件 min<=max

 while( min <= max){

 //公式,计算中间索引

 mid = (min+max)/2;

 //让被找元素,和中间索引元素进行比较

 if(key > arr[mid]){

 min = mid + 1;

 }else if (key < arr[mid]){

 max = mid - 1;

 }else{

 //找到元素,返回元素索引

 return mid;

 }

 }

 return -1;

 }

 

/*

   定义方法,实现数组的普通查询

   返回值: 索引

   参数:   数组, 被找的元素

   

   实现步骤:

 1. 遍历数组

 2. 遍历过程中,使用元素和数组中的元素进行比较

如果相同,返回元素在数组中的索引

如果不同,返回负数

*/

public static int search(int[] arr, int key){

//遍历数组

for(int i = 0 ; i < arr.length ; i++){

//数组元素,被查找的元素比较

if(arr[i] == key){

//返回索引

return i;

}

}

return -1;

}

}

 

Day09

成员变量和局部变量的区别

* 区别一:定义的位置不同

* 定义在类中的变量是成员变量

* 定义在方法中或者{}语句里面的变量是局部变量

* 区别二:在内存中的位置不同

* 成员变量存储在堆内存的对象中

* 局部变量存储在栈内存的方法中

* 区别三:声明周期不同

* 成员变量随着对象的出现而出现在堆中,随着对象的消失而从堆中消失

* 局部变量随着方法的运行而出现在栈中,随着方法的弹栈而消失

* 区别四:初始化不同

* 成员变量因为在堆内存中,所有默认的初始化值

* 局部变量没有默认的初始化值,必须手动的给其赋值才可以使用。

 

 

 c:抽象关键字abstract不可以和哪些关键字共存?

l   1:private:私有的方法子类是无法继承到的,也不存在覆盖,

                 abstractprivate一起使用修饰方法,abstract既要子类去实现这个方法,

                 private修饰子类根本无法得到父类这个方法。互相矛盾。

 

Day11

 

 

3.接口中成员方法的特点

* A: 成员方法特点

* a 接口中可以定义方法,方法也有固定的修饰符,public abstract

* b 子类必须覆盖掉接口中所有的抽象方法后,子类才可以实例化。否则子类是一个抽象类。

4.6实现类还是一个抽象类

A: 接口的实现类

   一个类如果实现类接口,有两种操作方法:

   第一:实现类是非抽象类,就需要重写接口中所有的抽象方法.

   第二:实现类也声明为抽象类,那么实现类可以不重写接口中的抽象方法。

5.* 总结:接口在开发中的它好处

* 1、接口的出现扩展了功能。

* 2、接口其实就是暴漏出来的规则。

* 3、接口的出现降低了耦合性,即设备与设备之间实现了解耦。

6.接口和抽象类区别总结

  相同点:

都位于继承的顶端,用于被其他类实现或继承;

都不能直接实例化对象;

都包含抽象方法,其子类都必须覆写这些抽象方法;

区别:

抽象类为部分方法提供实现,避免子类重复实现这些方法,提高代码重用性;接口只能包含抽象方法;

一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;(接口弥补了Java的单继承)

抽象类是这个事物中应该具备的你内容, 继承体系是一种 is..a关系

接口是这个事物中的额外内容,继承体系是一种 like..a关系

 

二者的选用:

优先选用接口,尽量少用抽象类;

需要定义子类的行为,又要为子类提供共性功能时才选用抽象类;

7.* C: 多态成员变量

当子父类中出现同名的成员变量时,多态调用该变量时:

编译时期:参考的是引用型变量所属的类中是否有被调用的成员变量。没有,编译失败。

运行时期:也是调用引用型变量所属的类中的成员变量。

简单记:编译和运行都参考等号的左边。编译运行看左边。

 

* E: 多态成员方法

编译时期:参考引用变量所属的类,如果没有类中没有调用的方法,编译失败。

运行时期:参考引用变量所指的对象所属的类,并运行对象所属类中的成员方法。

简而言之:编译看左边,运行看右边。

 

8.多态的好处和弊端

* A: 多态的好处和弊端

* 当父类的引用指向子类对象时,就发生了向上转型,即把子类类型对象转成了父类类型。

  向上转型的好处是隐藏了子类类型,提高了代码的扩展性

* 但向上转型也有弊端,只能使用父类共性的内容,而无法使用子类特有功能,功能有限制。

什么时候使用向下转型

当要使用子类特有功能时,就需要使用向下转型。

如:Dog d = (Dog) a; //向下转型

    d.lookHome();//调用狗类的lookHome方法

向下转型的好处:可以使用子类特有功能。

弊端是:需要面对具体的子类对象;在向下转型时容易发生ClassCastException类型转换异常。在转换之前必须做类型判断。

如:if( !a instanceof Dog){}

9构造方法的内存

A:内存加载的过程

有一个Person, 创建Person 对象new Person()

1、首先会将main方法压入栈中,执行main方法中的 new Person(23,"张三");

2、在堆内存中分配一片区域,用来存放创建的Person对象,这片内存区域会有属于自己的内存地址(0x88)。然后给成员变量进行默认初始化(name=nullage=0)。

3、执行构造方法中的代码(age = a ; name = nm;,将变量a对应的23赋值给age,将变量nm对应的”张三赋值给name,这段代码执行结束后,成员变量agename的值已经改变。执行结束之后构造方法弹栈,Person对象创建完成。将Person对象的内存地址0x88赋值给p2

 

10.1、先执行main方法,main方法压栈,执行其中的new Person(“张三”,23);

2、堆内存中开辟空间,并为其分配内存地址0x33,,紧接着成员变量默认初始化(name=null  age = 0);

3、拥有两个参数的构造方法(PersonString nm , int a))压栈,在这个构造方法中有一个隐式的this,因为构造方法是给对象初始化的,那个对象调用到这个构造方法,this就指向堆中的那个对象。

4、由于PersonString nm , int a)构造方法中使用了this(nm);构造方法Person(String nm)就会压栈,并将“张三”传递给nm。在PersonString nm , int a)构造方法中同样也有隐式的thisthis的值同样也为0x33,这时会执行其中name = nm,即把“张三”赋值给成员的name。当赋值结束后PersonString nm , int a)构造方法弹栈。

5、程序继续执行构造方法(PersonString nm , int a)中的age = a;这时会将23赋值给成员属性age。赋值结束构造方法(PersonString nm , int a)弹栈。

6、当构造方法(PersonString nm , int a)弹栈结束后,Person对象在内存中创建完成,并将0x33赋值给main方法中的p引用变量。

注意:

this到底代表什么呢?this代表的是对象,具体代表哪个对象呢?哪个对象调用了this所在的方法,this就代表哪个对象。

调用其他构造方法的语句必须定义在构造方法的第一行,原因是初始化动作要最先执行。

posted @ 2018-04-25 15:23  阿善9  阅读(234)  评论(0编辑  收藏  举报