目录
-
韩顺平自学Java资源:
-
链接: https://pan.baidu.com/s/1eP3aPSVUtnN2FPl60gXZ5w?pwd=3s93 提取码: 3s93 复制这段内容后打开百度网盘手机App,操作更方便哦
-
Static知识点:
当方法中不涉及到任何和对象相关的成员,则可以将方法设计成静态方法,提高开发效率。
细节解析:
- 类方法和普通方法都是随着类的加载而加载,将结构信息存储在方法区; 类方法中无this的参数; 普通方法中隐含着this的参数
- 类方法可以通过类名调用,也可以通过对象名调用
- 普通方法和对象有关,需要通过对象名调用,比如对象名.方法名(参数),不能通过类名调用
- 类方法中不允许使用和对象有关的关键字,比如this和super。普通方法(成员方法)了可以。
- 类方法(静态方法)中,只能访问 静态变量
- 普通成员方法,即可以访问 得静态变量,也可以访问静态变量
小结:静态方法,只能访问静态的变量,非静态的方法,可以访问静态成员和非静态成员(必须遵守访问权限)。
类变量也叫静态变量/静态属性。是该类的所有对象共享的变量,任何一个该类的对象去访问他时,取到的都是相同的值,同样任何一个类的对象去修改它时,修改的也是同一个变量,类变量不能通过类名,
定义语法:static数据类型 变量名: [ 推荐]
Static 访问修饰符 数据类型 变量名;
Static变量是对象共享不管static变量在哪里,static变量是同一个对象共享static类变量,在类加载的时候就生成了。
方法重写与方法重载:
名称 | 发生范围 | 方法名 | 形参列表 | 返回类型 | 修饰符 |
重载(overload) | 本类 | 必须一致 | 类型,,个数或者顺序至少有一个不同 | 无要求 | 无要求 |
重写 (override) | 父子类 | 必须一样 | 相同 | 子类重写的方法和父类返回的类型一致,或者是其子类 | 子类方法不能缩小父类方法的访问范围 |
面向对象编程——多态:
多态的具体体现:
对象的多态:(核心重点、难点)
- 一个对象的编译类型和运行类型可以不一致;
- 编译类型在定义对象时,就确定了,不能改变;
- 运行类型时刻以变化的
- 编译类型看定义时 = 的左边,运行看类型 = 的右边
案例:
Anmial animal = new Dog();【animal编译类型是Animal,运行类型Dog】
Animal = new Cat();【animal的运行类型变成了Cat,编译类型仍然是Animal】
hashCode方法
(1)提高哈希结构的容器的效率;
(2)两个引用1,如果指向的是铜鼓和对象,则哈希值肯定是一样的;
(3)两个引用,如果指向的是不同的对象,则哈希值是不一样的
(4)哈希值主要根据地址号来的!,不能完全将哈希值等价于地址
(5)后面在集合,中hashCoder如果需要的话,也会重写
断点调试机制
-
代码块使用注意事项和细节讨论
- static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,并且只会执行一次,如果普通代码块,每创建一个对象,就执行
- 类什么时候被加载:创建对象实例时(new);创建子类对象实例,父类也会被加载;使用类的静态成员时(静态属性,静态方法)
- 普通的代码块,在创建对象时调用,创建一次,调用一次
4.创建一个对象时没在意一个类调用顺序是:
- 调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果有多个静态代码块和多个静态变量初始化,则按照他们定义的顺序调用)
- 调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通属性初始化,则按照定义顺序调用)
- 调用构造方法
5.构造器的最前面其实隐含了super()和调用普通代码块,新写一个类演示,静态相关的代码块,属性初始化,在类加载时,就执行完毕,因此是优先于构造器和普通代码块执行的
6.创建一个子类对象时(继承关系),他们的静态代码块,静态属性初始化,普通代码块普通属性初始化,构造方法的调用顺序如下:
- 父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
- 子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
- 父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
- 父类的构造方法
- 子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
- 子类的构造方法
7.静态代码块只能调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员
单例模式-饿汉式-懒汉式
单例模式-饿汉式
1.将构造器私有化
2.在类的内部直接创建对象(该对象时是static)
3.提供一个公共的static方法,返回gf对象
对象,通常是重量级的对象,饿汉式可以造成创建了对象,但没有使用
单例模式-懒汉式
1.仍然构造造器私有化
2.定义一个 static 静态属性对象
3.提供一个 public 的 static 方法,可以返回一个 Cat 对象,需要判断是否创建对象
4.懶汉式,只有当用戶使用 getInstance 时,才返回 cat 对象, 后面再次调用时,会返回上次 创建的 cat 对象 ,从而保证了单例
饿汉式VS懒汉式
- 二者最主要的区别在于创建对象的时机不同:饿汉式实在类加载就创建了对象实例,而懒汉式时在使用时才创建
- 饿汉式不存在线程安全问题,懒汉式存在线程安全问题
- 饿汉式存在资源浪费的问题 ,因为如果程序员一个对象实例都没有使用,那么饿汉式创建的对象就浪费了,懒汉式是使用时才创建,就不存在这个问题
- 在我们JavaSE标注类中,java.lang.Runtime就是经典的单例模式
Final关键字
抽象类
当父类的一些方法不确定时,可以用abstract关键字来修饰该方法,这个方法就是抽象方法,用abstract来修饰该类即使抽象类
抽象方法:
即:父类的不确定性的问题
抽象方法就是没有实现的方法==>没有方法体
当类中存在抽象方法时,需要将该类声明为abstract类
一般来说,抽象类会被继承,有其子类来实现抽象方法
抽象类使用的注意事项和细节讨论:
- 抽象类不能被实例化
- 抽象类不一定要包含abstract方法,也就是说,抽象类可以没有abstract方法
- 一旦包含了abstract方法,则这个类必须声明为abstract
- abstract只能修饰类和方法,不能修饰属性和其他的
接口implemens
接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,再根据具体情况把这些方法写出来
小结:接口是更加抽象的抽象的类,抽象类里的方法可以有方法体,接口里的所有方法都没有方法体【jdk7.0】.接口体现了程序设计的多态和高内聚低耦合的设计思想。
特别说明:【jdk8.0】后接口类可以有静态方法,默认方法,也就是说接口中可以有方法的具体实现
注意事项和细节:
1.接口不能被实例化
2.接口中所有的方法是public方法,接口中抽象方法,可以不用abstract修饰
void aaa(); 实际上是 abstract void aaa();
3.一个普通类实现接口,就必须将该接口的所有方法都实现
4.抽象类实现接口,可以不用实现接口的方法
5.一个类可以实现多个接口
class Pig implements IB,IC{}
6.接口中的属性,只能是fianl的,而且是Public static final 修饰符。
egg: int a=1; 实际上是 public static final int a=1;
7.接口中属性的访问形式:接口名.属性名
8.一个接口不能继承其他的类,但是可以继承多个别的接口
interface A extends B,C{}
9.接口的修饰符 只能是public 和 默认,这一点和类修饰符是一样的
继承和接口:
继承:
当子类继承了父类,就自动的拥有了父类的功能
如果子类需要扩展功能,就可以通过实现接口的方式扩展
可以理解实现接口是对Java单继承机制的一种补充
- 比继承更加灵活是满足is-a的关系,而接口只是like-a的关系
- 接口在一定程度上实现代码解耦
- 继承的价值主要在于:解决代码的复用性和可维护性
- 接口的价值主要在于:设计,设计好各种规范(方法),让其他类实现这些方法,即更加的灵活
类的五大成员:属性、方法、构造器、代码块、内部类
内部类:
基本介绍:一个类的内部又完整的嵌套了另一个类结构。被嵌套的类被成为内部类(inner class),嵌套其他类的类被称为外部类(outer class)。是我们类的五大成员【属性、方法、构造器、代码块、内部类】,内部类的最大大特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系,底层源码,有大量的内部类。
局部内部类:
- 局部内部类是定义在外部类的局部位置,通常在方法中,且有类名
- 可以直接访问外部类的所有成员,包含私有的
- 不能添加访问修饰符,但是可以使用final修饰,因为局部变量也可以使用final
- 作用域:仅仅在定义他的方法或代码块中
- 局部内部类可以直接访问外部类的成员
- 外部其他类---不能访问---->局部内部类(因为局部内部类地位是一个局部变量)
- 如果外部类和局部内部类的成员重名时,遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问 egg:sout("外部类的n2"+外部类名.this.n2);
匿名内部类:
本质是类 内部类 无名字(系统会分配) 同时还是一个对象
说明:匿名内部类时定义在外部类的局部位置,比如方法中,并且没有类名
jdk底层在创建匿名内部类OuterO4$1,立即马上就创建了Outer04$1,并且把地址返回给对象(tiger)
匿名内部类只能使用一次,但是创建过的对象(tiger)依旧存在
匿名内部类注意细节:
- 匿名内部类的语法比较奇特,因为匿名内部类既是一个类的定义,同时他本身也是一个对象,从语法上看,它既有定义类的特征,也有创建对象的特征,对前面代码分析可以看出这个特点,因此可以调用匿名内部类方法;
- 可以直接访问外部类的所有成员,包含私有的
- 不能添加访问修饰符,因为它的地位就是一个局部变量
- 作用域:仅仅在定义它的方法或代码块中
- 匿名内部类----访问------>外部类成员【访问形式:直接访问】
- 外部其他类-----不能访问---->匿名内部类(因为它的地位就是一个局部变量)
- 如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
成员内部类:
- 注意:成员内部类,是定义在外部内的成员位置上
- 可以添加任意访问修饰符【public、protected、默认、private】,因为他的地位就是一个成员变量
- 作用域:同其成员,为整个整体
- 静态内部类----访问----->外部类(比如:静态属性)【访问方式:直接访问所有静态变量】
- 外部类----访问----->静态内部类 访问方式:创建对象,再访问
- 外部其他类----访问----->静态内部类
- 如果外部类和静态内部类重名时,静态内部类访问时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.成员)去访问
静态内部类:
静态内部类:
- 放在外部类的成员位置
- 使用static修饰
- 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
- 可以添加任意访问修饰符【public、protected、默认、private】
- 作用域:同其他的成员,为整个类体。
- 外部其他类----访问----->静态内部类
- 如果外部类和静态内部类重名时,静态内部类访问时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.成员)去访问
小结:
- 内部类有四种 局部内部类,匿名内部类,成员内部类,静态内部类
- 重点还是掌握 匿名内部类使用!!!
- 成员内部类,静态内部类 是放在外部类的成员位置,本质就是一个成员
enum:
常用方法:
注解 :
注解的理解
- 注解(Annotation)也被称为元数据(Metadata),用于修饰解释 包、类、方法、属性、构造器、局部变量等数据信息。
- 和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息。
- 在 JavaSE 中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在 JavaEE 中注解占据了更重要的角 色,例如用来配置应用程序的任何切面,代替 java EE 旧版中所遗留的繁冗代码和 XML 配置等。
基本的 Annotation 介绍:
使用 Annotation 时要在其前面增加 @ 符号, 并把该 Annotation 当成一个修饰符使用。用于修饰它支持的程序元素三个基本的 Annotation:
- @Override: 限定某个方法,是重写父类方法, 该注解只能用于方法
- @Deprecated: 用于表示某个程序元素(类, 方法等)已过时
- @SuppressWarnings: 抑制编译器警告
-
@Override:
- @Override 注解放在 fly 方法上,表示子类的 fly 方法时重写了父类的 fly
- 这里如果没有写 @Override 还是重写了父类 fly
- 如果你写了@Override 注解,编译器就会去检查该方法是否真的重写了父类的 // 方法,如果的确重写了,则编译通过,如果没有构成重写,则编译错误
- 如果发现 @interface 表示一个 注解类
@Deprecated:
- @Deprecated 修饰某个元素, 表示该元素已经过时
- 即不在推荐使用,但是仍然可以使用
- 查看 @Deprecated 注解类的源码
- 可以修饰方法,类,字段, 包, 参数 等等
- @Deprecated 可以做版本升级过渡使用
@SuppressWarnings:
- 当我们不希望看到这些警告的时候,可以使用 SuppressWarnings 注解来抑制警告信息
- 在{""} 中,可以写入你希望抑制(不显示)警告信息
- 可以指定的警告类型有:
4.. 关于 SuppressWarnings 作用范围是和你放置的位置相关 // 比如 @SuppressWarnings 放置在 main 方法,那么抑制警告的范围就是 main
5. 看看 @SuppressWarnings 源码
- 放置的位置就是 TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE
- 该注解类有数组 String[] values() 设置一个数组比如 {"rawtypes", "unchecked",
元注解:
JDK 的元 Annotation 用于修饰其他 Annotatio
元注解的种类:
- Retention //指定注解的作用范围,三种 SOURCE,CLASS,RUNTIME
- Target // 指定注解可以在哪些地方使用
- Documented //指定该注解是否会在 javadoc 体现
- Inherited //子类会继承父类注
try-catch
运行异常:
异常体系图
常见的运行时异常包括:
- NullPointerException 空指针异常
- ArithmeticException 数学运算异常
- ArrayIndexOutOfBoundsException 数组下标越界异常
- ClassCastException 类型转换异常
- NumberFormatException 数字格式不正确异常[]
编译异常:
编译异常是指在编译期间,就必须处理的异常,否则代码不能通过编译
异常处理:
当异常发生时对异常处理的方式
示意图:
try-catch异常处理:
- Java提供try和catch块来处理异常。try块用于包含可能出错的代码块。catch块用于处理try块中发生的异常。可以根据需要在程序中有多个try-catch块
- 基本语法
try-catch方式处理异常的注意事项:
- 如果异常发生了,则异常发生后面的代码不会执行,直接进入到catch块。
- 如果异常没有发生,则顺序执行try的代码块,不会进入到catch
- 如果希望不管是否发生异常,都指向某段代码(比如关闭连接,释放资源等)则使用如下代码-finally{}
4.可以有多个catch语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,比如(Exception在后,NullPointerException在前),如果发生异常,只会匹配一个catch
包装类:
String对象:
细节:
- String 对象用于保存字符串,也就是一组字符序列
- "jack" 字符串常量, 双引号括起的字符序列
- 字符串的字符使用 Unicode 字符编码,一个字符(不区分字母还是汉字)占两个字节
- String 类有很多构造器,构造器的重载 常用的有
- String s1 = new String();
- String s2 = new String(String original);
- String s3 = new String(char[] a);
- String s4 = new String(char[] a,int startIndex,int count)
- String s5 = new String(byte[] b)
- String 类实现了接口 Serializable【String 可以串行化:可以在网络传输】 // 接口 Comparable [String 对象可以比较大小]
- String 是 final 类,不能被其他的类继承
- String 有属性 private final char value[]; 用于存放字符串内容
- 一定要注意:value 是一个 final 类型, 不可以修改(需要功力):即 value 不能指向 // 新的地址,但是单个字符内容是可以变化
- String是一个final类,代表不可变的字符序列
- 字符串是不可变的。一个字符串的对象一旦被分配,其内容是不可变的
- String s1 = "hello";
- s1 = "haha";
- 先创建了一个对象”hello“,再从常量池中找"haha",如果找到了,就直接指向“haha”,否则,就创建一个新对象
创建方式:
内存分布图:
String、StringBuffer和StringBuilder的选择:
使用的原则:
- 如果字符串存在大量的修改操作,一般使用StringBuffer或StringBuilder
- 如果字符串存在大量的修改操作,并在单线程的情况,并在单线程的情况,使用StringBuilder
- 如果字符串存在大量的修改操作,并在多线程的情况下,使用StringBuffer
- 如果我们字符串很少修改,被多个对象引用,使用String,比如配置信息等
ArrayList和LinkedList的比较:
如何选择ArrayList和LinkList:
- 如果我们改查的操作很多,选择ArrayList:
- 如果我们增删的操作很多,我们选择LinkList
- 一般来说,在程序中80%-90%都是查询,因此大部分情况下会选择ArrayList
- 在一个项目中,根据业务灵活选择,也可能是这样,一个模块使用的是ArrayList,另外一个模块是LinkList,也就是说,要跟韩剧业务来进行选择。
set:
同Collection的遍历方式一样,因为Set接口时Collection接口的子接口。
- 可以使用迭代器遍历
- 增强for
- 不能使用索引的方式来获取
试分析HashSet和TreeSet分别如何实现去重的:
- HashSet的去重机制:hashCode()+equals(),底层先通过存入对象,进行运算得到一个hash值,通过hash只得到对应的索引,如果发现table索引所在的位置,没有数据,就直接存放,如果有数据,就进行equals比较【遍历比较】,如果比较后,不相同,就加入,否则就不加入。
- TreeSet的去重机制:如果你传入了一个Comparator匿名对象,就使用实现的compare去重,如果方法返回0,就认为是相同的元素/数据,就不添加,如果你没有传入一个Comparator匿名对象,则以你添加的对象实现的Comparable接口的compareTo去重。
试写出Vector和ArrayList的比较:
底层结构 | 版本 | 线程安全(同步)效率 | 扩容倍数 | |
ArrayList | 可变数组 | jdk1.2 | 不安全,效率高 | 如果使用有参构造器按照1.5倍扩容,如果是无参构造器 1.第一次扩容10 2.从第二次开始按照1.5倍 |
Vector | 可变数组Object[] | jdk1.0 | 安全,效率不高 | 如果是午餐,默认10,满后,按照连个比扩容 如果是指定大小创建的Vector,则每次按照2倍扩容 |
节点流和处理流
节点流:可以从一个特定的数据源读写数据,如FileReader、FileWriter
处理流:(也叫包装流)是“连接”在已存在的流(字节流或处理流)之上,为程序提供更为强大的读写功能,也更加灵活,如BufferedReader、BufferedWriter
节点流和处理流一览图:
TCP网络通信编程
netstat指令:
- netstat -an 可以查看当前主机网络情况,包括端口监听情况和网络连接情况
- netstat -an|more 可以分页显示 使用空格键 切换下一页
- 要求在dos控制台下执行 win+r
说明:
- Listening表示某个端口在监听
- 如果有一个外部程序(客户端)连接到该端口,就会显示一条连接信息
- 可以输入ctrl+c退出指令
UDP网络编程原理:
-
没有明确的服务端和客户端,演变成数据的发送端和接收端
-
没有数据和发送数据是通过DatagramSocket对象完成
-
将数据分装到DatagramPacket对象/装包
-
当接受到Datagrampacket对象,需要进行拆包,取出数据
-
DatagramSocket可以指定在哪个端口进行接受数据
类加载:
反射机制是Java实现动态语言的关键,也就是通过反射实现类的动态加载。
- 静态加载:编译时加载相关的类,如果没有则报错,依赖性太强
- 动态加载:运行时加载需要的类,如果运行时不用该类,即使不存在该类,则不报错,降低了依赖性