数组
定义语法
- int[] hens ={1,2,3,4,5},int[] arr = new int[] {1,2,3,4,5}(静态初始化)
- int[] hens =new int[5];(这里是定义一个有5个位置的int类型数组)
- 先声明数组int[] hens; 再创建数组hens = new int[5];
遍历数组

数组长度
数组名.length
一维数组使用细节
数组创建后如果没有负值,那么会有默认值

增强for循环(补充)
语法 for(数据类型 变量名 : 数组名){}
注意:数组和变量要一个类型
例子(用在枚举上): for(Season season : values){}
运行模式:从values数组依次取一个Season类型的对象,把地址传递给season
方法(成员方法)
成员方法的定义:

成员方法细节
- 如果想接收多个返回值?返回数组。
- 方法不可以嵌套定义。
- 同一个类的方法可以直接调用 直接上例子: Class A { public void print(int n) { System.out.println(“print()方法被调 用 n=” + n); } public void sayOK() { print(10);//在这里方法print就被调 用了 } }
- 跨类调用方法:需要通过对象名调用 public void m1(){//这个方法是A类中的 B b = new B(); b.hi();//这个hi是B类中的 }
- 在成员方法中引用到了main方法中的数组或某个对象 然后再public void test200(Person p){ p = null;行参中的Person p是main方法中的一个对象,但是test200方法中的p与其不同,置空的只是test200中的p(也就是引用置空,实际引用地址是没有变化的)(这里也可以看出null这个代码并不是清空地址,只是取消引用),所以main方法中的p不发生任何变化。 }
方法递归调用
自己调 用自己:在tool方法里调用tool方法(有限套娃)(一定要有递归方法的出口,不然就是无限套娃了)
public void test(int n){if (n > 2){//出口      test(n - 1);}System.out.println("n=" + n);
}//输出什么?2.3.4。
阶乘:
public int factorial(int n){//在前面传入参量 n = 5    if (n == 1){      return 1;    }else{       return factorial(n - 1) * n;     } 
}//阶乘实际计算为1*2*3*4*5每次递归调用都要缩小范围,目标才能达到出口的条件。
方法重载
同一个方法名,有不同的形参
例如System.out.println();这个方法如果方法名不相同,那么就不叫重载。
返回值
return n1 > n2 ? n1 : n2;(这里的意思直接省略了if语句,而是用缩写公式完成了n1与n2的对比),这个语句也可以用在int a = n1 > n2 ? n1 : n2;
方法重载细节
public double max(double n1,double n2,double n3),在这个语句里如果前文给的形参是(double1,double2,int3)那么也是会匹配到上面这个方法,因为int类型可以转换为double。
但是max(double n1,double n2,double n3)与max(double n1,double n2,int n3)是方法重载
可变参数
java允许将同一个类中多个重名同功能但参数个数不同的方法,封装成一个方法。
可以通过可变参数实现。
基本语法:访问修饰符 返回类型 方法名(数据类型…形参名)//这里多个一个数据类型
public int sum(int… nums){}
还可以通过代码查询上面方法接受了几个参数 -> nums.length;
可变参数细节
-  可变参数可以和普通形参一起放在形参列表,但必须保证可变参数在最后 
-  一个形参列表只能出现一个可变参数 
-  可变参数进方法后是以类似数组的方式存在,读取其中数据也是用类似数组的方式读取 
变量作用域(VarScope)
-  主要的变量是属性(成员变量)和局部变量。 
-  局部变量一般指在成员方法中定义的变量 
-  java中作用域的分类 - 全局变量:作用域为整个类体
- 局部变量:也就是除了属性之外的其他变量,作用域为定义它的代码块中!
 
-  全局变量可以不赋值,直接使用,因为有默认值。 局部变量必须赋值后,才能使用,因为没有默认值。 
-  全局变量可以被本类使用,或其他类使用(通过对象调用): -  public void test() { Person p1 = new Person(); System.out.println(p1.name);//jack }
-  public void test2(Person p) { System.out.println(p.name);//jack }但局部变量只能在本方法中使用 
 
-  
-  全局和局部变量可以重名,访问时遵循就近原则(比如在方法中定义了一个name,又在类中定义了一个name,此时在方法中使用到了name,那么这个name属于局部变量) 
-  属性可以加修饰符,局部变量不能加修饰符 
构造器
在先前创建人类的对象时,是先把一个对象创建好后,再给他的年龄和姓名赋值。
现在要求在创建人类对象是,就直接指定这个对象的年龄和姓名,该怎么做?这时就使用构造器。
基本语法
[修饰符] 方法名 (形参列表){ 方法体; }
老韩说明
-  构造器的修饰符可以默认 
-  构造器没有返回值 
-  方法名和类名字必须一样 
-  参数列表和成员方法一样的规则 
-  构造器的调用系统完成 
-  在创建对象时,系统会自动的调用该类的构造器完成对对象的初始化 
构造器细节:
-  构造器也可以重载,使用方法与方法重载一致 
-  构造器是完成对象的初始化,不是创建对象 例子如下 Person p1 = new Person(“king”, 40); //(“king”, 40)就是初始化内容 
-  构造器要让系统自动调用,我们是无法调用的 
-  一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器,除非显式的定义一下, 
即:Dog(){}(这点很重要)
构造器的复用
public Employee(String job, double sal){ this.job = job; this.sal = sal;} 
public Employee(String name, char  gender, int age){  this.name = name; this.gender = gender;  this.age = age; } 
public Employee(String job, double sal,String name, char gender, int age){ this(name, gender, age);//使用到前面的构造器 this. job = job; this.sal = sal;
}
对象创建流程分析
看一个案例
class Person{//类Person         int age = 90;      String name;  Person(String n; int a){//构造器  name = n;//给属性赋值       age = a;//...}
main(){Person p = new Person("小倩",20)
} 
流程分析:
- 先在方法区加载Person类
- 然后在堆内开空间,创建含age和 name变量的地址1(对象)并完成默认初 始化age = 0,name = null
- 然后再完成对age的赋值(90)
- 接着执行构造器 a.在常量池创建一个地址2并接收"小倩" b.让地址1中的name指向地址2 c.再把age重新赋值为20
- 最后才在栈中创建一个p指向地址1
反编译
javap
this关键字——对构造器形参名的优化
this.变量名;//访问this所在成员属性中的成员变量 ThisDetail
-  访问成员方法的语法:this.方法名(参数 列表); 
-  访问构造器语法:this(参数列表); 注意只能在构造器中用且是第一条语句 (即只能在构造器中访问另一个) 
-  this不能在类定义的外部使用,只能在 类定义的方法中使用 
同类不同方法相互调用
A. f1(); B. this.f1();
以上两种方法目前来说都能调用f1,但是具体区别在学到继承的时候
包
包的作用
-  区分相同名字的类 
-  当类很多时可以很好的管理【API文档】 
-  控制访问范围 
包的基本语法
package com.hspedu
package 关键字,表示打包
com.hspedu 表示包名
包的本质分析
就类似文件夹
命名规则
只能包含数字.字母.下划线.小圆点
但不能数字开头或者关键字、保留字
命名规范
一般是小写字母+小圆点
一般是com.公司名.项目名.业务模块名
常用的包
java.lang.* //基本包,默认引入
java.util.* //工具包,工具类(Scanner)
java.net.* //网络包,网络开发
java.awt.* //是做界面开发,GUI
IDEA
文件储存位置说明
-  class文件编译后会储存在\out文件夹内 
-  .java文件在scr文件夹内 
常用快捷键
-  删除当前行,默认ctrl + Y 自己配置ctrl+d 
-  复制当前行粘贴到下一行,Ctrl+alt+向下光标 
-  补全代码alt+/ 
-  导入当前行需要的类alt+enter 
-  快速格式化代码ctrl+alt+L 
-  运行程序 shift + F10(如果想快捷运行, 要先配置主类) 
-  生成构造器alt + insert 
-  查看一个类的层级关系 F4 
-  定位方法源 ctrl+鼠标左键 
-  自动分配变量名,在new Scanner()后面 加.var,然后回车 
模板快捷键
-  sout 
-  fori 
-  …自己找模板 file->settings->editor->Live templates 
IDEA查看jdk源码
老韩文件夹里有doc文档可看
访问修饰符
- Public: java语言中访问限制最宽的修饰符,一般称之为”公共的”,被其修饰的类,属性及方法,不仅可以跨类访问,而且允许跨包(package)访问
- Protected: 介于public和private之间的一种访修饰符,一般称之为”保护型”,被其修饰的类,属性以及方法只能被该类本身的方法及子类访问,即使子类在不同的包中也可以访问.
- **Default: **即不加任何访问修饰符,通常称为”默认访问模式”,即"默认型",该模式下,只允许在同一个包中进行访问.
- Private: java语言中访问权限限制最窄的修饰符,一般称之为”私有的”,被其修饰的类,属性,以及方法只能被该类的对象访问,其子类不能访问,更不允许跨包访问.
访问修饰符图片助解

封装(encapsulation)
封装的理解和好处
理解
封装就是把抽象出的数据(属性)和对数据的操作(方法)封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作(方法),才能对数据进行操作
好处
-  隐藏实现细节 
-  可以对数据进行验证,保证安全合理 
封装的实现步骤
-  将属性进行私有化private【不能直接修改属性】 
-  提供一个公共的set方法,用于对属性判断并赋值 public void setXxx(类型 参数名){//加入数据验证的业务逻辑属性 = 参数名; }
-  提供一个公共的(public)get方法,用于获取属性的值 public 数据类型 getXxx(){//权限判断,Xxx某个属性return Xxx; }
将构造器与封装结合
将set方法写在构造器内
继承
为什么要使用继承?
当多个类的属性和方法大量重复(需要提高代码复用性)
继承的基本语法
class 子类 extends 父类{ }(子类又叫派生类,父类叫基类,超类)
继承的细节问题
a. 子类不能直接引用父类的私有属性,要通过父类 公共的方法去访问
b. 子类必须调用父类的构造器,完成父类的初始化
c. 创建子类对象时,不管使用子类的那个构造器,默认情况下总会去调用父类的无参,如果父类没有无参,则必须在子类的构造器中用 super去指定使用父类的某个构造器完成对父类的初始化工作 //super();
d. 如果希望指定去调用父类的某个构造器,则显示的调用一下super(参数列表)
e. super必须放在构造器第一行
f. super() 和 this()都只能放在构造器第一行,因此他俩不能共存在一个构造器
g. 不能滥用继承,子类和父类之间必须满足:子类 is a 父类
继承的内存布局
public class ExtendsTheory {public static void main(String[] args) {Son son = new Son();  System.out.println(son.name);  System.out.println(son.hobby);}
}
class GrandPa { //爷类String name = "大头爷爷";String hobby = "旅游";
}
class Father extends GrandPa {//父类String name = "大头爸爸";private int age = 39;public int getAge() {return age;}
}
class Son extends Father{ //子类String name = "大头儿子";
}
//当Son son = new Son();这条语句执行时 会先在方法区内加载各个类,并且父类优先然后再堆中开空间从父类优先一个个创建属性并赋值(值来自方法区)
访问属性的原理
优先看子类中有没有需要的属性,如果有并且能访问,则返回信息;如果没有,就向上(父类)查找
super关键字
A. 访问父类的属性,但不能访问父类的private属性//super.属性名
B. 访问父类的方法,也是不能访问private //super.方法名(参数列表)
C. 访问父类的构造器,只能放在构造器的第一句,只能出现一句!只能在构造器!//super(参数列表)
 一般只有子类中定义了与父类重名的属性、方法才会使用到super,如果上一个父类没有super指定的,则继续找父类的父类
super和this的冲突
在构造器中两者都只能写在第一行,所以构造器最多只能有他俩其一
方法重写
是什么?
简单来说子类中的一个方法与父类的某个方法的名称、返回类型、参数都一样,那么这个方法就称为覆盖(重写)了父类的方法
细节
a.返回类型可以不一样,但父类中的返回值得是子类中的返回值的父类,如父类是Object子类是String
b.子类方法不能缩小父类方法的访问权限
多态
为什么要使用多态?
譬如一个项目,有主人有动物,有食物又因为食物很多,喂食所需要的方法就 很多,不利于管理和维护(方法复用性不高,不利于管理与维护)
多态的具体体现
a. 方法的多态(方法重载/重写)
b. 对象的多态
 重要的几句话
 (1) 一个对象的编译类型和运行类型可以不一致比如Animal animal = new Dog();//Dog是Animal的子类
 (2) 编译类型在定义对象时,就确定了,不能改变
 (3) 运行类型是可以变化的
 (4) 编译类型看定义时 = 号的左边,运行类型看 =号的右边
 (5) 编译类型与运行类型的区别
 当Dog是Animal的子类时
      Animal animal = new Dog();
      animal.cry();//这个时候cry运行的是Dog子类中的cry,因为运行时执行到该行时animal的运行类型是Dog,所以cry是Dog的cry
      animal = new Cat();//这个时候运行类型又成了Cat
 (6)把每个方法的形参都改为具体参数的父类,方法的复用性就极大地提高了
多态细节
a. 多态的前提:两个对象存在继承关系
b. 多态的向上转型
 本质:父类的引用指向了子类的对象
 语法:父类类型 引用名 = new 子类类型();
 特点:编译类型看左边,运行类型看右边。
 可以调用父类中的所有成员(遵守访问权限),但不能调用子类中特有成员;
 //比如
 Animal animal = new Cat();
 animal.catchMouse();//这里会报错,无法调用Cat类的catchMouse方法
 最终运行效果看子类的具体体现
c. 多态的向下转型
 语法:子类类型 引用名 = (子类类型) 父类引用
 Cat cat = (Cat) animal
 只能强转父类的引用,不能强转父类的对象
 要求父类的引用必须指向的是当前目标类型的对象
 可以调用子类类型中的所有成员就像是把向上转型给直接换成Cat cat = new cat();
属性重写问题
属性没有重写之说!属性的值看编译类型
instanceOf比较操作符
用于判断对象的运行类型是否为XX类型或XX类型的子类型
语法:aa instanceOf AA;//返回值为boolean
 Sub s = new Sub();
 Base b = s;//Base是Sub的父类
  此时 b == s的返回值是true
java动态绑定机制(非常非常重要)
a.当调用对象方法的时候,该方法会和该对象的内存地址/运行属性绑定
b.当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
多态的应用(多态数组)
 创建了包含多个对象的数组,可以通过循环遍历
 特殊情况:
 Person student = new Student();
 //这里Student是Person的子类
 //Student中有一个study成员方法
 //但Person中没有这个方法,
 //这时候使用student.study就会报错
 //但是可以考虑用if配合instanceof来选择是否
 //让student进行向下转型70.equals方法
equals方法
==和equals比对象比的是运行类型,(也就是判断引用地址是否相同)
区别:当equals比String类型时如果地址不相同,他会继续判断字符串长度是否相同,如果相同,会继续判断每个字符是否一一对应
equals只能判断引用类型
直接上代码:if(name.equals(“丁真”)){……}
重写equals方法
为什么要重写?
Object里面最原始的equals只是比较两个对象是否一样(如person1 != person2),不一样就直接返回false,但是有时候不同对象属性一样,就需要重写新的equals
新需求:equals比较的是两个有可能不是同一个的对象的属性是否一样,一样就返回true。
组织一下语言:
== :比较左右两个东西是不是一个东西
equals(Object):比较左右两个对象是不是一个对象
equals(重写):先比较是不是一个类型,再比较内容
hashCode
老韩的6个小结:
1)提高具有哈希结构的容器的效率
2)两个引用,如果指向的是同一个对象,则哈希值肯 定是一样的
3)两个引用,如果指向的是不同对象,则哈希值是不一样的
4)哈希值主要根据地址号来的,不能完全将哈希值等价于地址.
5)案例演示[HashCode_.java]:obj.hashuCode()
A aa = new A();
A aa2 = new A();
aa3 = aa;
6)后面在集合中hashCode如果需要的话,也会重写
toString方法
默认返回: 全类名 + @ + 哈希值的十六进制
子类往往重写toString方法,用于返回对象的属性信息
调用语法:
1.对象名.toString();
2.对象名;//真就这么简单
重写toString方法
使用快捷键即可alt + insert(IDEA)
finalize
当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法
解释:
-  当对象被回收时,系统自动调用该对象的finalize方法,子类可以重写该方法,做一些释放资源的操作。 
-  什么时候被回收:当某个对象没有任何引用时,则jvm就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用finalize方法 
-  垃圾回收机制的调用,是由系统来决定(GC回收算法),也可以通过System.gc()主动触发垃圾回收机制(不一定能成功触发) 
-  Object类的finalize方法是空的,什么都没干 
ps:实际开发中一般不会用…应付面试官
零钱通

化繁为简:
-  先完成显示菜单,并可以选择菜单,给出相应提示 
-  完成零钱通明细 老韩思路: - 可以把收益入账和消费,保存到数组;
- 可以使用对象
- 简单的话可以使用String拼接
 System.out.println("1 零钱通明细"); System.out.println("————————————零钱通明细————————————");
-  完成收益入账 完成功能驱动程序员增加新的变量和代码 老韩思路:定义新的变量 double money = 0; double balance;//需要获取系统时间1 
-  完成消费信息 定义新变量place//消费地点 
-  完成退出提示 

至此,以上是面向过程的方法完成零钱通的流程。
Chapter08Homeworks







断点调试(IEDA)
当程序运行到断点处时,程序暂停,程序员可以开始一步步往下运行
快捷键:
F7:跳入方法内
F8:逐行执行代码
shift + F8:跳出方法
F9:执行到下一个断点//可以在dubug过程中动态的下断点
进入Jdk源码有问题?
解决方法1:
使用force step into:快捷键 alt + shift + F7
解决方法2:
配置一下(方法在330集)
chapter09
先停在第342集,转枚举
枚举
枚举(enumeration)的引出
现在有个需求:创建季节(Season)对象,请设计并完成
//思路清晰,先建个类,给属性1.name 2.desc(描述)
class Season{private String name;private String desc;//构造器//_get()
}
public class Main{public static void main(String args[]){Season summer = new Season("夏天","炎热");Season spring = new Season("春天","温暖");Season autumn = new Season("秋天","凉爽");Season winter = new Season("冬天","寒冷");Season other = new Season("红天","666");}
}出现问题:因为对于季节而已,他的对象(具体值),是固定的四个,不会有更多
 按上面的设计思路,不能体现季节是固定的四个对象
 甚至可以通过set方法将summer.name改为别的字符串
 因此,这样的设计不好……==>枚举的需求诞生【枚:一个一个 举:列举;即把具体的对象一个一个列举出来】
自定义枚举类

class Season{private String name;private String desc;//1.将构造器私有化,目的防止直接new//2.去掉setXxx的相关方法,只能读,不能修改//3.在Season内部,直接创建固定的对象public static final Season SPRING = new Season("春天","温暖");public static final Season SUMMER = new Season("夏天","炎热");public static final Season AUTUMN = new Season("秋天","凉爽");public static final Season WIMTER = new Season("冬天","寒冷");private Season(String name, String desc) {super();this.name = name;this.desc = desc;}public String getName() {return name;}public String getDesc() {return desc;}@Overridepublic String toString() {return "Season [name=" + name + ", desc=" + desc + "]";}}public class Enumeration02 {public static void main(String args[]) {System.out.println(Season.SPRING);}
}写完发现,代码很长,很费事,那么就需要引出:
使用enum关键字实现枚举类
- 将定义常量对象放在最前面
- 使用关键字 enum 替代 class
- public static final Season SPRING = new Season(“春天”,“温暖”) 直接使用SPRING(“春天”,“温暖”)来替代
- 如果有多个对象,使用","间隔 :SPRING(“春天”,"温暖“),SUMMER(“夏天”,“炎热”),……;
enum关键字实现枚举注意事项
-  当我们使用 enum 关键字开发一个枚举类时,默认会继承 Enum 类[如何证],老师使用 javap 工具来演示 
-  传统的 public static final Season2 SPRING = new Season2("春天”,“温暖”);简化成 SPRING (“春天”,”温暖”),这里必须知道,它调用的是哪个构造器. 
-  如果使用无参构造器创建枚举对象,则实参列表和小括号都可以省略 
-  当有多个枚举对象时,使用,间隔,最后有一个分号结尾 
-  枚举对象必须放在枚举类的行首 
-  enum Gender2{ /父类 Enum 的 toString BOY,GIRL; } Gender2 boy = Gender2.BOY://oK Gender2 boy2 = Gender2.BOY;//枚举类的对象是可以传递的
-  父类Enum的toString方法返回的是枚举对象的对象名,比如上面的代码,boy.toString()就是返回BOY 
enum常用方法说明

valueOf 方法说明

enum细节
-  使用enum关键字后,就不能再继承其他类了,因为enum会隐式继承Enum,而Java是单继承机制 
-  枚举类和普通类一样,可以实现接口,如下形式 enum 类名 implements 接口1,接口2{} 
注解( Annotation )
注解的理解
- 注解( Annotation )也被称为元数据( Metadata ),类、方法、属性、构造器、局部变量等数据信息。
- 和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息。
- 在 JavaSE 中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在 JavaEE 中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替 java EE 旧版中所遗留的繁冗代码和 XML 配置等。
基本的Annotation的介绍

^: SimpleDateFormat formatter = new SimpleDateFormat(“dd-MM-yyyy HH:mm:ss”);
- 获取系统时间:java.util.Date 
 ^: 在Java中,获取当前日期最简单的方法之一就是直接实例化位于Java包java.util的Date类。
 ^: Date date = new Date(); // this object contains the current date value ↩︎
