1、windows相关的DOS命令:
*打开方式
win+R 接着输入cmd就可以打开了
*常见的DOS命令有哪些
- exit 退出当前命令
- cls 清除屏幕
- 复制方法只需要选中即可,这个和视频当中是有区别的
- dir 显示当前文件夹里面包含的目录
- cd 表示进入当前的文件夹
*使用方法 cd+路径
*路径分为绝对路径和相对路径
*绝对路径的指向是给定的,具有完整的路径
*相对路径是在当前目录下进一步延申的路径
*例如绝对路径为cd C:Users19766Desktop,相对路径为cd Desktop
- cd … 表示回到上级目录
- cd 表示回到根目录
- d: 表示切换盘符,但是很明显,我的电脑只有c盘,压根不用这个
2、Java的发展历史:
* Java语言诞生于1995年
* 由微电子公司sun公司提出,后被oracle收购,之前叫Oak语言
* 1996年,第一代JDK1.0诞生,这是最基础的开发包,是做开发必须下载的
* 目前最高版本为Java8/JDK1.8/JDK8
* Java包括三大块:
- JavaSE (Java开发标准版)
- JavaEE (Java企业版)
- JavaME (Java微型版)
其中主要学习JavaSE,后续学习EE,SE是基础,需要先学
3、Java语言特性 【开源、免费、纯面向对象、跨平台】
*简单性:相对而言,java不支持多继承,但是C++是支持的,
java中没有指针,但是C ++当中有指针
Java语言的底层是C++实现的,而不是c语言
*面向对象
纯面向对象,符合人的思维
*可移植性
可以做到跨平台运行,在windows和linux之间可以交互运行。
sun团队想到的一个非常棒的想法:主要就是利用虚拟机的方式来进行编译,JVM虚拟机,让虚拟机和操作系统来打交道
*多线程
*健壮性:
和自动垃圾回收机制有关,和内存的空间的释放有关
*安全性
4、Java注释的几种方式
*单行注释
//注释内容
多行注释
/
注释内容
*/
*doc注释——类型帮助文档,开发功能
5、Java变量的用法
在Java语句当中,类体中只能声明变量,不能写Java语句,同时在运行函数入口main的过程当中,
是先执行类体中的变量内存的,所以即使声明的变量在方法体的下面,也会首先执行类体当中的变量值,
从作用域来看,其变量的内存是根据其最近的来更改的
6、数据类型包括四大类八小种
基本数据类型:
整数型:byte,short,int,long 对应的空间大小分别为:1,2,4,8
浮点型:float,double 对应的空间大小分别为:4,8
布尔型:boolean 对应的空间大小为:1
字符型:char 对应的空间大小为:2 --不太懂为什么字符占两个
在定义字符变量的过程中,字符必须使用单引号,而字符串则需要使用双引号
上述的单位表示的是字节,一个字节能够表达八个二进制编码, 但是这里最重要的一点是1000 0000 表示的值是2的7次方,而不是2的8次方 这里是自己的认知误差导致的错误
7、Java语言采用uicode编码方式,所以里面的标志符号是可以写成中午的,太牛皮了,
class 学生 这行代码在Java语言当中是兼容的
这点太恐怖了吧,也就是说里面的变量也可以使用中文来表达,大吃一惊
8、变量
成员变量是指在Java类体当中声明的,而局部变量则是在方法体当中声明的
成员变量在Java中如果没有赋值,系统会自动的进行初始化,
但是如果局部变量没有初始化,系统会报错
* char变量 转义字符有非常重要的作用,'\'可以输出斜杠,'''可以输出单引号 n表示换行符 t 表示制表符,相当于一个tab u表示的是Unicode编码 *int,long变量 -Java语言当中,对于数字的处理,默认为int类型的数值 -而此时如果在声明long类型时,超过了2147483647的int最大值时,会出现报错 -主要的原因在于此时Java当中存不下这类数值,因此只能使用 long x=2147483648L -在后面加L的主要原因在于为了区分Java当中默认的数值储存数值 -Java语言当中,long和int类型的数据进行转换的过程中,小容量转大容量时,可以随意转换 -但是大容量转小容量时,需要强制类型转换才可以,并且还会损失精度 -在byte,short,int没有超出其范围时,不需要进行类型转换,只需要声明即可,便于程序员操作 *补码解码的过程,这是计算机有关的知识,正数为源码,但是负数为补码,-1之后取反 *float 和double -在Java中,所有的float字面值都默认为double类型 -如果需要float类型,需要在后面加f或者F,或者使用强制类型转换
9、在Java当中,i++和++i是有区别的,主要是在于i++先赋值,后运算,而++i则是先运算,后赋值&&和&两个的逻辑运算符之间是有区别的,主要的原因在于&&是短路与,而&不短路,短路现象是指,如果左边为flase,那么右边不会执行,因此短路与使用的频率更多
10、在进行数据转换的过程中可以使用byte来对变量的类型进行划分,例如(byte)(5),这里的意思就是将int型的变量变为byte来进行后续的运算,这里扩展类的运算符刚好的用处就是保留原有的类型,使用这个来进行运算都不会报错 ,Java当中的三目运算符是可以当作if语句来进行使用的,do while语句在使用的过程当中是先执行do,后执行while,也就是说程序至少需要执行一次,break 默认情况下,终止的是最近的循环
11、在Java语言当中最神奇的是,对于for循环可以命名,然后根据命名来选择break
在Java中,函数在里面的名称为方法,开头为public static ,后面接返回值类型,例如void,int,string
在命名为void的时候,其不能直接写return + 值的形式,但是可以直接写return
包含return的语句执行时,结束整个程序
形参和实参的区别在于,方法当中利用的值是形式参数,而调用时赋予的值则为实际参数
和matlab一样,在调用函数的时候,如果是在同样的一个类中,此时调用的函数就可以,直接使用函数名
但是在不同类,需要加上类名来调用函数
在实际开发的过程中,在源文件当中最好只定义一个class文件,就是public clss,最后不要声明其他的class,虽然程序允许
main是单线程的,后续学习多线程的概念
12、栈数据结构,队列数据结构——数据结构与算法当中常用
栈是先进后出,队列是先进先出
栈数据结构在执行的时候对方法来说有非常重要的意义,例如在执行方法1的过程中,调用了方法2 ,
那么此时栈的内存空间,首先分配方法1 的内存,由于其是最先使用的,因此是在最后进行释放的
而方法2在执行完毕之后,就被释放,因此栈数据结构和方法的执行顺序一样,先进后出
在虚拟机当中,包含有栈内存,堆内存,方法区内存,堆内存后续学习
13、在Java强类型语言当中,最重要的方法是方法重载,即方法名是可以一样的,但是方法对应的实现类型可以是不一样的
即在实现的过程中,只和参数列表有关,因为在弱类型语言当中,对于变量的输入,字符串,int,long,都不会影响程序的执行
14、面向过程和面向对象
面向过程主要是因果关系,逻辑结构,代码复用性较差
面向对象主要是个体,一个一个独立的,比较好,代码复用性较好,但是分割得太死了,编写起来比较麻烦
Java为纯面向对象的编程语言,抽象,封装,继承,多态
OOA面向对象分析,OOD面向对象设计,OOP面向对象编程,OO表示object-oriented
对象和类之间的关系,对象和对象之间存在共同的属性,将共同的属性进行归纳就会形成类
对象表示实例,对象到类为抽象,通过类制造对象
类中包含有状态信息和动作信息
成员变量就是全局变量,在类中
15、在使用IDEA的时候,是可以使用快捷键的,例如
public static void main(String[] args){} 对应的快捷键为psvm
System.out.println() 对应的快捷键为sout
注释和取消注释分别为Ctrl+/
查看具体的方法可以,使用Ctrl,然后点击方法,查看调用的是哪个方法
16、构造方法和普通方法的区别在于构造方法没有返回的函数值
在Java语言当中,构造方法可以在类中不写,如果不写,在系统当中默认为缺省的值
构造方法和普通方法一样,同样支持方法的重载
构造方法在Java语言创建类的时候,主要的作用是对参数进行初始化操作
构造方法可以有不同的参数输入,在发生继承的时候,可以在子类当中调用父类的构造方法
这样即使是私有变量,也可以通过构造方法,来将父类当中的私有变量进行赋值
17、在调用其他函数的时候,带static的普通方法在调用的过程和不带有区别,
不带static的方法在构造时需要引用后调用
不需要类名,之间引用+函数名就可以了,原因在于引用就是类别里面的,所以在使用的时候,计算起来非常的方便
18、Java在参数传递的过程中,字面值和对象所对应的值在传递时是不同的
在对象中,只要你修改值了,那么继承的值,都有修改的权限,因为其对应的是一个地址,而不是字面值
其在栈内存当中进行储存
19、关于Java语言当中的this关键字
一般只需要在this id = id 的时候来表示才不可以省略,其他情况是可以省略的
变量的作用域为自身的大括号内部,出了自身的大括号就找不到了
this关键字和super两个关键字都不能在静态方法当中使用,只能在实例方法当中使用
并且在继承的过程中,super();是默认在第一行的,如果此时没有this和super的话,默认在继承的第一行是存在这个代码的
子类方法在调用的过程中,一定会执行父类的构造方法
初始化方法可以有多个,输入参数不同即可,这也是为什么会存在this关键字的意义
20、static关键字在使用的时候,可以进行类装载执行,即只需要写明白关键字即可
static{}
带static关键字的方法在实际使用的过程中,是不可以访问实例变量,只能访问定义的静态变量,就是静态变量的作用域更加的广,所有的方法都可以访问到,
但是实例变量,只能在没有带static的变量当中使用,也就是需要通过构造对象来进行访问
静态方法和实例方法的区别在于实例方法是需要有对象的
并且静态函数只能访问静态的变量,对应的实例变量是无法访问的,主要的原因在于没有定义对象,所以不能够访问
最近发现在Java语言当中,继承的对象如果省略了引用,居然是可以访问的,太离谱了
也就是说实例变量在实际使用时,是需要构造对象来进行访问的,这句话没有问题
这个是已经构造了对象,但是对象调用了函数,在函数中间是有变量的,此时会默认变量对应的就是调用的对象,省略了this
21、Java只能单继承,不支持多继承,但是可以间接的多继承
22、Java语言方法支持重载,但是实际上的重载还可以在类和类之间进行重载
但是方法重载是多样化,而类和类之间的重载则是更新方法
更新方法的过程当中只是在方法名相同时才发生
静态的方法不存在重载,但是实例方法可以重载,很明显的原因就是静态的是不变的,而有对象的是可以改变的
23、在向下强制类型转换的过程中,容易出现转换的时候和对应的对象不一样,原因在于前面可以向上之间兼容
那么此时如果不管就会出现类型的指向存在异常,因为编译可以通过,但是出现了类型转换的异常
在实际使用的时候,可以用instanceof来进行初次的判定来进行计算
24、final关键字在使用的过程中实际上是为了固定值,可以指向方法,值,引用等
final在修饰实例变量的时候,需要对实例变量进行赋值,因为实例变量会进行初始化操作
final在修饰静态变量的时候,加上static对应的值就是常量,根据命名规范,常量都需要大写
final在修饰引用的时候,固定的只是地址,也就是具体的实例,对于实例当中的值可以进行修改
25、package和import两个在实际使用时,package是创建包,import是引用包
java.lang.*包在实际使用的过程中不需要引用就可以使用,里面包含了基本的数据类型
引入了其他的类,在使用的时候就会非常方便,不需要带包名,这是Java提前为程序员准备好的
26、private<缺省
27、在Java当中,定义一个实际的对象,最后会输出引用的地址,
即继承了类当中的tostring方法,直接返回对应的对象存的地址
28、super.什么时候不能够省略,从结构上看,当父类型和子类型两者之间都有相同的变量和方法,
如果想在子类型当中访问父类型的变量,可以使用super关键字来进行计算
super和this的区别还在于this是存在内存
29、多态当中举的例子就是抽象类,抽象类和普通类的区别在于,抽象类无法创造对象,而普通类是存在对象的
在计算时,抽象类比较便捷的方法在于,可以在构造类的时候,便于继承前面类的情况
abstract 和 final 关键字两个之间不能够同时使用,所以实例化的对象一定是能够存在的具体东西,
而抽象类是将类当中的共同特征来进行计算的,便于后续的计算
abstract 方法在实际使用时可以有抽象方法,但是抽象方法没有方法体,就是只寻找方法名,但是不执行方法体
因为其本身就没有方法体,所以其主要的作用就是为了给继承的类提供一个方法名,让子类自己去写
如果子类不写,就会报错,因为前面的修饰是Abstract,所以需要利用方法重载来实现
30、接口在Java语言当中是一种引用数据类型,并且在继承的过程中是支持多继承的,interface 是接口的关键字
在接口当中进行访问的时候,只有常量和抽象方法,并且接口就是抽象的,是完全抽象的,里面不存在方法体
因此在使用接口时,自动的省略了public abstract ,在定义常量的时候public static final
接口的主要作用是预设一个需要实现的功能,接下来是去实现接口里面的内容进行完成
可以将接口当成类来,继承的关键字是excends来继承,但是接口当中使用implements
接口在使用时的主要作用就是弥补在使用继承的时候,只支持单继承的缺点
在使用时也可以进行类型转换,但是在实际转换的过程当中还是建议使用instanceof来判断
并且接口当中没有继承,因此强制类型装换的过程中可以支持非继承转换,这是使用Java接口的缺点
一个既可以继承也可以实现接口,其中继承在前,实现在后,即excends在前,implements在后
接口的主要作用是增加程序的扩展性,和多态的作用一样,为什么多态好呢,主要的原因是在具体实现时
对于主函数,可以面向父类编程,而子类在构造时,是可以根据父类来命名的,例如:Animal a = new dog
这里就是通过子类的dog,构造了父类的对象Animal,此时程序在执行时,对于对象a,实际执行的方法是dog
这就是多态的主要作用,非常重要
如果不对引用进行初始值的赋值,系统就不会给引用赋值,因为引用也是一个对象
所以在声明引用的变量类型时,需要先给定对象,这样才可以的赋值,或者查看初始化之后的值
其实核心的一点就是在于Java会不会对引用的变量进行初始化,这是一个非常重要的论点
具体来说是不会对引用数据类型作为成员变量时进行里面具体变量的初始化,而只会将引用数据类型赋值为null,而不管是什么类型
只要是引用数据类型作为成员变量来进行初始化,统一将其作为null来进行赋值
继承和接口的区别,还有一点在于,接口主要的目的是实现,而继承主要的目的是多态
这两者目的不同,直接会在使用的时候,产生不同的影响,因为接口的作用是实现方法,所以在实现接口时通常不需要管多态
所以接口通常是解耦合的关键步骤,主要的原因在于进行大项目开发时,调用者和实现者是两拨人,一个负责调用接口,一个负责实现接口
定义为抽象类和接口两者在使用时,不同的点在于,抽象类里面是有信息的,所以包含的是类别,而接口主要体现在方法,即行为
31、常用的Object类函数的使用方法,通常包含有,tostring方法,在Java当中默认的是返回类名哈希值,但是sun
公司建议进行重写,其主要的目的是将对象的特征进行表示
equal方法,可以用于判断两个对象是否相同,不能使用“”来进行判断的主要原因是,此时判断的只是比较两者的内存地址是否相同
但是实际上Sun公司在实际使用时,也是利用的“”来表示,所以和tostring方法一样需要重写
这个在IDEA当中是可以直接生成的
hashcode方法,返回对象内存地址的哈希值
finalize() 方法不需要我们重写,是垃圾回收器自动调用的方法,可以利用System.gc() 来建议程序启动垃圾回收器
32、匿名内部类,其实就是指这种类只使用一次,在接口后面接大括号进行实现,new 接口名(){实现方法}
是局部内部类里面的一种,看着高端而已,实际上增加了算法的冗余
33、数组的表示方式为int[] a; 表示a是一个整型的数组,a={}; 这是赋值的方法,调用使用[]来进行调用,打印使用printArray
日常写的psvm里面的String[] args 其中,args就是输入的参数,即在进入主函数的过程中,可以要求用户输入参数才能够正常的进入系统
在实际上有着重要的意义,当用户输入参数时,即账户密码才可以访问
因此在定义数组的时候,可以通过定义的类来进行,例如定义了Student类,那么此时可以定义Student数组来进行计算,直接进行Student[] a;
数组赋值里还有,arraycopy(),对数组进行赋值
打印应该有printString
34、在Java当中,Object类是所有类的超级父类,因此在创建数组时,可以创建Object数组来储存其他的数据,里面可以包含所有的类型
万能的口袋,Object
但是在编写Java对象时,需要重写的方法有toString方法,equals方法,setter,getter方法
35、Java语言当中,提供了枚举类型enum表示枚举类型,即在返回值的时候,如果返回的是两种类型,可以用true和flase
但是大于三个以上,可以使用enum函数来进行求解,在求解时便于类型的区分,例如一年四季
在Java当中提供了Integer装箱方法和非装箱方法,另外提供了封装好的函数来进行字符串的处理,
在进行字符串的拼接时,常用append来进行拼接,而很少使用“+”来进行拼接,主要的原因还是处理的效率问题
对于在写代码过程中可能出现的异常问题,可以使用两个方法来进行解决
第一种是throws来将异常抛给上一级,直到出现在main方法当中,返回到JVM虚拟机当中
第二种是自己解决,使用try catch来进行异常的捕捉
Java在查看异常信息时,使用printStackTrace来打印异常的信息
通常在main方法当中进行try catch,而在其他情况下抛给上一级
子类不能比父类抛出更多的异常,也就是说在继承父类的时候,如果父类没有抛出异常,那么子类也不可以,这也间接说明了如果程序在执行时
子类出现了异常想抛出到虚拟机当中,此时需要在继承的每一个父类上都加上抛出的异常才可以
也就是说,如果父类抛出了异常,子类的异常要么抓住,要么抛出
—异常和方法覆盖,重写之后的方法不能比重写之前的方法抛出更多的异常,可以更好,就是说在方法覆盖时,不论是接口还是继承
—在实际上,重写的方法都不能够将异常抛给上一级,而是应该自己把异常抓住
在创立文件流输入时,可以使用finally语句来进行输入流的释放,即使块语句当中的数据出现了异常,但是在finally语句当中,语句也会执行
也就是说,finally是保证语句一定会执行,会释放Java当中存在的资源,所以try可以和finally语句一起使用,这样更加的方便,try语句不可以单独使用
finally语句当中,即使之前的语句当中返回了方法的值,finally语句也会执行,也就是说finally语句是方法体当中最后执行的语句
其他的语句在后面无法执行,也就是说return语句是虚假的最后,finally是真实的最后,瞎说,哈哈
上面的两句话是错的,实际上,return语句才是最后执行的,但是finally语句确实是最后的执行的
并且finally语句必须要和try语句联合使用,这是非常重要的,finally语句不可以随便用
从编译器当中调试我发现了,return语句返回的值,是最开始就已经赋值好的,但是实际上并没有将值传出,而是在值已经赋值好后
再去执行finally语句,当finally语句执行完之后,再去执行return语句,这个真的太香了,在实际上符合标准,return语句是最后执行的
并且return语句是方法结束的标志,所以finally语句最后的执行是虚假的
异常方法在代码当中的意义在于,对于可能存在的异常程序,可以通过输出异常的信息来进行提示,也就是程序在实际执行的过程中,
找到代码在哪里可能存在异常,可以自己定义一个异常,这个异常继承Exception,然后在子类中,可以抛异常,也可以处理异常
36、进阶了,集合Study
集合在Java语言当中只储存引用数据类型,而不储存实际的数据,也就是说,只储存地址,是一个容纳很多对象的容器,也就是说
集合当中是可以储存集合的,在集合当中主要包含List,Set两种类型,List里面的数据类型是可重复的,有序的,而Set则是不可重复的,无序的
List下还有其他的类别,在新建数据类型时,主要针对的是List下的数据结构,例如ArrayList,其底层采用了数组的数据结构
linkedList,其底层采用了双向链表的数据结构,Vector也是数组的底层,但是由于其保证绝对的线程安全,使得在实际编程时效率不高,很少使用
Set下包含有HashSet,其底层是一个HashMap集合,HashMap是哈希表的一个数据结构
Set下还有SortedSet ,其实现类为TreeSet,其实现的底层为TreeMap集合当中,底层主要采用了二叉树的数据结构
37、单向的链表结构,对于每一个节点,里面储存了两个信息,一个是当前节点的数据信息,另外一个是下一个节点的内存信息,末尾节点的信息为null
从链表的数据结构来看,其具备有改进数组的缺点,对于增删来说及其的方便,但是在实际查询时不具备有优势,因为需要从头开始遍历,找到自己的查找数据
在Java当中,提供了泛型的方法来解决在数组当中,或者链表当中类型相同,但是在实际储存时Java语言不知道具体的类型,所以在定义集合时,可以通过
<类型>来限制储存的类型,之前如果不加,加入的就是obj对象,便于储存大部分的数据,后续调用对象的方法时,可以避免大量的转型业务
即调用集合当中父类的方法,是不需要转型,但是调用子类的方法时,还是需要将集合当中的对象进行转型,向下转型
另外,向下转型是需要强转的,但是向上转型则是自动转型,原因在于,向下转型可能会转不了,但是向上就不会
在查看源码之后,发现了当中的E表示的是元素,element
在实际的代码写时,几乎向下转型的代码,建议都考虑使用加<>的方法来进行下一步的实现
foreach是增强for循环,还比较好用,当不需要数组下标时可以不需要操作
38、Map数据结构在使用时,是以键值对的方式存在的,即每一组数据,都包含有Key值和Value值,这两个是绑定的,在查询时速度较快
了解哈希表的数据存储以及查找,从哈希表或散列表的结构来看,其具备有两个优势,增删不麻烦,查找速度快
结合了链表和数组的优点来进行结合,其主要的原理是里面有哈希值,通过哈希函数计算出来的哈希值
相当于是将链表的结构和数组结构结合起来,数组将单个的链表串起来,形成一个“二维的数组”,这里的二维只是一个描述
在实际的储存结构上,是依据哈希值对应的数组的下标所对应的,其实原理上就是把数据进行分组
这样在进行储存的时候是根据链表来进行储存的,在增加和删除时的结构是链表,而在进行查询时,其并不是所有进行查询
哈希表添加元素的原理:首先将key值进行传入,利用key值通过哈希函数时计算最终的结果,其对应的结果为数组的索引
在得到数组索引之后,判断数组当中的链表结构是否有元素,如果此时有元素,进行value值的比对,如果值相同进行替换
如果对应的value值不同,此时将key和value放在链表的最后一位
因此在编写哈希函数时需要保证散列均匀,也就是说在数组当中的链表是长度均匀的
在定义HashMap的初始化容量时,需要是2的幂才行,也就是原来容量的2倍
在哈希表当中,进行数据储存时和数据查询时,首先都是计算K值对应的哈希值,哈希值再通过函数计算数组的下标
也就是先利用hashcode方法,再使用equals方法,所以在实际使用时,如果equals方法重写了,实际上hashCode方法也需要重写
两个的重写方法直接按照IDEA方法同时进行生成,实际上当单个数组的地址超过八个链表节点之后,会将链表转化为树结构
看源码是一件比较重要的事,底层的实现逻辑可以更加的清晰
39、在Java当中,以Stream结尾的都是字节流,以Reader和Writer结尾的都是字符流,在输入数据时,如果输入结束了,记得close(),
在使用输出流时,可以使用flush()来进行刷新,在使用时,主要去查看源代码,根据源代码来进行功能的实现
40、Java语言当中的序列化,需要实现Serializable接口,通过接口去实现类别,但是这个接口并没有需要实现的方法,因此在实际意义上
只是一个标志性接口,是给JVM虚拟机看的,如果实现了序列化的接口,最终会实现对序列的序列号,特殊对待
参与序列化其实就是一个复制,将原有的类别进行储存,储存之后进行反序列化来进行下一步的求解,writeObject
transient 关键字是对象的属性不参与序列化
序列化会导致后续不能够修改代码,如果修改了代码,序列化后的版本号,将无法反编译成功,因此在实际上需要手动的给定序列号
自动生成之后,后续修改的时候,虚拟机也不会认错,也就是说在实际编译时,可以实现序列化的接口,手动给定
那么今后在使用时,就不会出现重复,即使在后续修改代码,反序列化时也不会出错,这个很重要
IO + Properties 表示为属性配置文件,在Java当中,对于文件的配置信息,建议以 .properties 结尾,并且在文件当中以等号来进行连接
41、多线程是Java语言的特色,在实际编程时,是多线程的,多个线程之间栈内存是独立的,但是方法区内存和堆内存是共享的,因此在实际上
Java程序也可以实现多线程,例如在实际执行普通代码时,至少会执行main进程,和垃圾回收器进程,因此在实际使用时,即使主线程main方法 结束了
依旧会存在其他程序没有结束,进程和线程的区别在于,进程是一个整体,是一个整体的任务,但是线程相当于是实现任务的方式,可以是多线程来实现的
堆内存当中储存的数据为 new 出来的对象是存在于堆内存的,这个是自己之前没有想到的,而String 字符的关键字在实际内存的储存过程中,是应用在方法区的
因此多线程并发在实际处理时,每一个线程都是不干扰的
实现线程主要有两种方法,实现机制较为简单,第一种是直接继承java.lang.Thread , 接着实现run方法 ,这是实现的一种方法,在主程序当中可以写对象.start()
上述方法实现时,基本实现了并发执行,在实际实验时,重写的run方法会和main方法一起执行
对象.run() 和 对象.start() 两个直接有直接的区别,前者是单线程,后者是多线程,后者开辟了新的栈空间,从此就没有这个方法了
也就是说只要执行到了start(),之后在实际执行时,后面就不管了,接着向下去执行
第二种方法,编写一个类,实现Runnable接口,在Java.lang包下,接着将实现的接口进行封装,封装之后直接加载到Thread当中进行执行,接着对象.start()
在实际开发时,通常使用接口的方法来进行,主要的原因在于继承的方法会限制方法的继承,不利于后续的开发,使用接口较为方便
在实现时还可以使用匿名内部类来进行,因此在使用时,可以new接口{接口的实现方法}来实现多线程
线程的生命周期包含有五个,新建状态,就绪状态,运行状态,阻塞状态,死亡状态
获取当前的线程对象,可以使用静态方法currentThread(),对线程进行命名,可以使用setName和getName,这是之前重写get和set方法导致的
调用方法通常需要使用,类名加方法名,返回值就查看源代码的返回值
在线程当中,有静态方法sleep,让当前的线程进入休眠状态,静态方法的特点是不需要对象也可以执行,当然也可以给定一个对象来进行调用,但是不会影响最终的结果
中断线程的睡眠可以使用interrupt() 方法,来中断睡眠
中断线程则可以使用stop() 方法来进行,此时不会保存线程的数据,因此很少使用
通常的使用方法可以新建一个布尔类型的变量,线程在执行到多久之后,可以将布尔类型再传进去,就可以改变原有线程的执行情况
yield方法是可以实现,线程的让位,还有join方法,合并线程,加入之后,当前线程阻塞合并线程执行
42、在多线程情况下的数据安全问题,实际上项目的实际编译是运行在服务器上的,因此在实际执行时,不需要关注线程的分配,而是数据的安全
满足三个条件就会存在数据安全问题,在多线程环境下,线程之间有共享数据,存在线程对数据进行修改的行为,因此此时需要线程同步执行,排队
可以使用,synchronized 关键字,使用这个关键字的方法,可以直接在后面接括号,括号内部可以将代码当中的对象进行传入即可,任意的成员变量,或者静态变量都可
在实际开发时,可以写字符串,原因在于字符串是一个引用数据类型,或者写this关键字,这里的this指的是同一个对象
Java当中的三大变量以及各自的分区,局部变量,在栈中,实例变量在堆中,静态变量在方法区(特例:字符串就在方法区)
因此局部变量在实际开发时,不存在并发的问题
synchronized 可以修饰实例方法,因此整个的方法体都是不可以并发修改的,Vector里面就是大量的使用了这个关键字,导致方法使用较少,主要是效率不高
我看了Vector的Java源代码,实际上还真是这样
synchronized 在实际使用时,还可以修饰静态方法,此时锁定的对象是类锁,而不是对象锁,这两个的区别在于,类可以声明多个对象
但是实际上类锁对应的类只有一个,导致了只有是这个类,都会把这个方法锁住
突然想到让一个程序执行速度变慢的方法了,那就是疯狂的调用sleep的方法,让程序一直睡觉,摸鱼学习法,其实也可以在科研的时候进行造假,害
死锁情况只会出现在修饰指定的对象时,才会发生,在实际开发时,不会出现在静态方法和实例方法当中,原因在于静态方法会锁定类,第一个占用了,后续也不会使用
多线程的能不能将方法进行传入呢,实际上是可以的,直接类名加方法就可以
守护线程的主要目的是为了保护线程,使用setDaemon方法即可,使用守护线程可以进行数据备份等操作
43、JDK8新特性,在线程的实现方法上,可以使用FutureTask关键字来进行识别,FutureTask需要重写call方法
执行时的逻辑为首先需要实现接口Callable 接着实现 FutureTask,此时将Callable作为参数传入,接着将Future作为参数传入到Thread当中,最后利用新建的Thread对象start
这里需要注意的是,得到的结果,只能够通过FutureTask来接收返回的参数,得到线程的返回值
针对特定的对象,Java提供了wait() 方法和 notify() 方法,一个是让所有线程针对的对象进行暂停,一个是唤醒等待线程对象的方法
44、放射机制在Java语言当中的作用,是操作代码片段,java.lang.reflect.*,表示在相关包下
有三种方法获取字节码文件,
第一种,使用Class 引用名 = Class.forName(“字符串”)
第二种,使用Class 引用名 = 字符串.getClass() //这个的原因是字符串带有属性的功能
第三种,使用Class 应用名 = 任意类型.class()
利用反射机制可以构造对象,相对于直接new对象,更为灵活,结合配置文件,直接对配置文件进行修改,让IO直接读取文件,然后创建对象
路径的获取可以采用实时的方法来进行获取,防止说如果在实际的开发时,由于程序的移植,导致代码找不到路径,而是让代码自己去找路径当中的类
String path = Thread.currentThread().getContextClassLoader().getResource(“字符串:类名”).getPath()
结合IO流,简直不要太香
另外Java还提供了资源绑定器的方法,ResourceBundle方法,之间将属性配置文件进行读取ResourceBundle.getBundle(),这里就已经是获取到了流,利用getString就好了
反射机制在使用时不是特别常见,主要是用于反编译,获取字节码文件,如果得到源代码,以及源代码对应的属性
最离谱的是在实际上,并不需要知道原来的类,因为获取到的是字节码的属性,所以在实际上获取到的字节码属性,里面并不包含有
反射机制可以获得到值,方法,构造方法,也就是说,对应的方法都可以通过反编译得到
也就是说,之前的所有都知道
45、Java语言提供了可变长度参数,即在实际使用时,参数个数为0-N个,并且可变长度参数必须在最后一个位置上,而且在方法的输入参数当中只能有一个
语法 int … 即类型+… ,因此其本质为一个数组,在实际开发时较为常用
反射机制还可以知道,父类,实现的接口
注解,实现的方式,使用Alt+Insert 就可以实现
元注解,主要用于标记注解类型的注解,Target , Retention注解
如果是加入@Deprecated代码的标注,会显示方法已经过时



