面向对象
类和对象
java实现跨平台是因为它编译为字节码之后,可以在Java虚拟机上运行,通过Java虚拟机可以编译为其他想要的编程语言,非常方便。
类:抽象出来的行为(方法) 和 特征(属性)的模板;
对象是什么:该类的具体实现,对象,看得见摸得着
类名的首字母大写,见文知意 属性名首字母小写 人: 名字 年龄 身高 性别
封装
封装的概述
-
是指隐藏对象的属性和方法的细节,仅对外提供公共的访问方式
封装的好处
-
隐藏实现细节,提供对外的公共的访问方式
-
提高了代码的复用性
-
提高了安全性
封装的原则
-
将不需要对外提供的内容都隐藏起来
-
把属性隐藏,提供公共方法对其访问
private关键字概述和特点
特点
-
一个权限修饰符,本类中可用
-
修饰成员变量和成员方法(可以)
-
针对整个类,在方法中使用没有意义
this关键字
特点
-
代表当前对象的引用
简单讲解
-
this应用场景:目前而言代表当前类,用来区分成员变量和局部变量
封装表现
属性私有化,公开get、set方法
方法组成
访问权限 返回值类型 方法名(参数列表)
构造方法(构造器)
作用:为属性赋初始值;
特征:
-
1方法名与类名一致
-
2没有返回类型
-
3当一个类没有任何构造方法时,则系统默认给一个无参的构造方法
-
4当一个类中有带参的构造方法,则系统默认的无参构造方法失效,想再使用,需要显式声明
static静态关键字
特点
-
随着类的加载而加载
-
静态优先于对象
-
被类的所有对象共享
-
可以用类名直接调用,也可以用对象调用
-
静态修饰的内容我们一般称之为与类相关的,类成员
成员变量和静态变量的区别
1、所属不同
-
静态变量属于类,称为类变量
-
成员变量属于对象,可以称为对象变量
2、存储位置不同
-
静态变量存储于方法区的静态区
-
成员变量存储在堆内存中
3、内存出现的时间不同
-
静态随着类的加载而加载
-
成员变量随着对象的对象的创建而存在
4、调用不同
-
静态可以可以被类名和对象调用
-
成员变量只能通过对象调用
mian方法和格式
1、格式
public static void main(String[] args){
}
2、格式解释
-
public 被jvm调用,访问权限足够大
-
static 被jvm调用,不用创建对象,直接类名访问比较快
-
void 被jvm调用,不需要给jvm返回值
-
mian 一个通用名称,虽然不是关键字,但是被jvm识别
-
String[] args
get/set方法
-
set没有返回值
-
get有返回值
-
要有测试类
面向对象之构造方法概述与格式
概述和作用
-
给对象的属性值进行初始化赋值、
特点
-
1方法名与类名一致
-
2没有返回类型
-
3当一个类没有任何构造方法时,则系统默认给一个无参的构造方法
-
4当一个类中有带参的构造方法,则系统默认的无参构造方法失效,想再使用,需要重新声明
全局变量和局部变量的区别
全局变量
成员变量:全局变量==》在这个类中谁都可以用
位置:类中 方法外
生命周期:随着类的加载而加载,随着类的消失而消失·
存储位置:在堆中
初始值:可以不赋值 因为本身就有初始值
局部变量:
位置:在方法中 在方法上
生命周期:随着方法的加载而加载,随着方法的消失而消失
存储位置:在栈中
初始值:没有初始值,如果要使用必须给初始值
局部变量需要使用必须赋值才能使用。
当全局变量和局部变量相同的时候(全局和局部变量可以相同),有一个优先级关系:就近原则。
面向对象--匿名对象概述和使用
1、什么是匿名对象
大白话说:就是没有名字的对象
2、匿名对象的应用场景
-
调用方法的时候,仅仅只能调用一次,好处:节省代码调用多次的时候,千万别用调用完就变成垃圾了,可以被垃圾回收
//例如
new Student.run();
匿名对象可以作为参数对象
//例如
public void a1(Student s){
}
创建对象的步骤逻辑
b/s 和c/s
b /s:浏览器服务器
c/s :客户端服务器
第一章
Java简介
查看JDK是否配置成功
cmd ->javac:出现一堆东西即配置成功 1.首先查看系统是否安装有jdk,打开cmd在DOS窗口输入 java -version查看jdk版本信息 2.你也可以输入 java -verbose查看jdk安装路径: 3.查看是否配置JAVA_HOME环境变量,输入 set JAVA_HOME,若已经配置,会出现配置路径 4.配置JAVA_HOME环境变量,输入set JAVA_HOME=C:\Program Files\Java\jdk1.8.0_102,回车,然后,输入set JAVA_HOME查看
在cmd下运行Java源文件
-
首先进入相应的盘
-
然后相应的源文件路径
-
编译源文件:javac 源文件名
-
运行编译后的字符码文件:java 编译后字节码的源文件名,此处不用写后缀
-
提取文档:javadoc 源文件名
第二章
8种数据类型
数据类型 | 所占的字节(byte) {1 byte = 8 bit} |
---|---|
整型 byte | 1 范围: {-2的7次方~2的7次方} |
整型 short | 2 范围: {-2的15次方~2的15次方} |
整型 int | 4 |
整型 long | 8 特殊符号: 整型默认是int型所以要在数后加"L" |
浮点型 float | 4 特殊符号: 浮点型默认是double型所以要在数后加"F" |
浮点型 double | 8 |
字符型 char | 2 |
布尔型 boolean | 1,4,1/8 |
数据类型之间的优先级
很清楚啦,byte、short、char是一个级别的,它们之间的运算都会转换为int类型,注意,自己跟自己运算也会转为int类型。int之后从小到大依次为:long、float、double。至于boolean,他是个比较特殊的类型。
String不是基本数据类型,是引用类型;变量是存储数据的基本单元
变量名规则
-
变量名前面不能是数字
-
变量名前面可以是字母、下划线、$,其他符号不行
-
变量明前面单词字母要小写后面单词首字母大写(标准写法)
-
变量名后面数字也可以添加了,除了¥后面不能跟其他符号
-
中间不可以有空格
-
变量名不能是关键字
-
变量得先赋值才能用
-
避免第二个字母大写(细节)
&& 与 &的区别
-
&& 条件1 && 条件2:条件1为假,条件2就不执行了(比&效率高)
-
& 不管有几个条件都走一遍(效率低)
|| 与 |的区别
-
|| 条件1 || 条件2:条件1为真,条件2就不执行了(比|效率高)
-
| 不管有几个条件都走一遍(效率低)
!
-
条件为真,结果为假
-
条件为假,结果为真
第三章
while循环
//先判断后执行
while(循环的条件){
循环体
}
do-while循环
//先执行后判断 循环一次
do{
循环体
}while(循环的条件);//不能忘了分号
for循环
for(循环的条件){
循环体
}
break
直接跳出整个循环体。
continue
结束本次循环过程,接着进行下一次循环过程。
if 和switch的区别:
-
if 主要针对于不确定的值
-
switch主要针对于确定的值
if-else if
区间越小的放在越上前。
第四章
数组的遍历
一维数组的增强for循环遍历方式
for(int i:array){
System.out.println(i);
}
二维数组的增强for循环遍历方式
for(int[] i:array){//返回数据类型多加了一个中括号,遍历二位数组中一维数组
//获得二维数组中的一维数组的地址
for(int j:i ){//把数组里面的数遍历出来
System.out.println(j);
}
}
//如下可以输出二维表
public class Test02 {
public static void main(String[] args) {
int[][] arr = new int[10][10];
arr[1][2]=11;
arr[0][0]=11;
for(int[] i:arr){
for(int j:i){
System.out.print(j+"\t");
}
System.out.println();
}
}
}
//结果
11 0 0 0 0 0 0 0 0 0
0 0 11 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
获取二维数组的长度的方法
-
获取第一维数组的长度
int a = array.length;
获取第二维数组的长度的方法
int b = array[i].length;
栈、堆和方法区
详解:java存储机制(栈、堆、方法区详解)_王小的博客-CSDN博客_java堆栈方法区
堆区:
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令) 2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身 。
栈区:
1.每个线程包含一个栈区,栈中只保存基础数据类型的值和对象以及基础数据的引用 2.每个栈中的数据(基础数据类型和对象引用)都是私有的,其他栈不能访问。 3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
方法区:
1.又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。 2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。
继承
1、继承的格式
public class 子类 extends 父类{
}
2、继承的好处和弊端
-
好处:提高了代码的复用性,提高了代码的维护性,让类与类之间产生了关系,是多态的前提
-
弊端:类的耦合性增强了,Java的核心思想是高内聚低耦合
-
耦合:就是类与类的关系
-
内聚:就是自己完成某件事的能力要高
3、java中继承的特点
-
只支持单继承,不支持多继承
-
支持多层继承
4、Java中继承注意事项
-
子类只能继承父类非私有成员方法及成员变量
-
子类不能继承父类的构造方法,但是可以通过super关键字去访问父类的构造方法
-
不要为了部分功能去继承
-
什么时候使用继承:类A是类B的一种,或者类B是类A的一种
-
子类中的方法的权限必须高于父类中的方法(方法名相同的时候)
-
有同名时采用就近原则
this和super的区别
super
是子类局部范围访问父类成员变量的关键字
区别
1、调用成员变量
-
this.成员变量:可以调用本类和父类的成员变量(有同名时采用就近原则)
-
super.成员变量:调用父类的成员变量
2、调用构造方法
-
this(...) 调用本类中的构造方法
-
super(...) 调用父类中的构造方法
3、调用成员方法
-
this 可调用父类和本类中的成员方法(有同名时采用就近原则)
-
super 调用父类中的成员方法
-
super要写到方法中才能调用父类成员方法
4、继承中构造方法的关系
-
实例化子类对象(假如是无参构造),须先执行父类构造,其次子类构造(因为子类无参构造中首行隐藏 super();)
-
子类中super(参数);中的参数必须和父类的参数数据类型对应,其中的参数数据类型和参数名和子类本构造方法中的参数相同;
-
有参构造中没有隐藏的super(参数),但是首行要有super(参数);
-
如果父类没有的构造样式,子类不能有
5、静态代码块和构造代码块
-
static代码块-->构造代码块-->构造方法
-
static:父类-->子类
-
构造代码块和构造方法(在一块),父类-->子类
方法重写
概念:
子类中出现了和父类的方法名相同,返回值必须一致
应用:
当子类需要父类的功能的时候,而功能主题特有自己的功能的时候,可以重写
方法重写注意事项
-
父类中私有方法不能重写
-
子类重写的方法权限要高于或等于父类中的方法
-
父类中是静态方法必须用静态方法重写
-
参数列表中个数相同,顺序一致,参数类型一致,返回值必须一致
Overload和Override的区别
-
Override:参数相同(范围),返回值相同,静态多态,调用的函数在编译时被选中
-
Overload: 参数不同(范围),返回不同 ,运行时是多态性的
final关键词
final修饰变量的初始化时机
-
在对象构造完成之前完成
-
定义变量时,修饰的变量是不可变的,变量必须给
-
定义对象时
final Person p = new Person("张三",22);
p = new Person("李四",21);//错误,不可改变里面的属性值
//如果要强行改变,调用set方法
p.setName = "李四";
p.setAge = 21;
-
一般不定义方法,不对里面的参数起到作用
多态
1、概述
-
事物存在的多种形态
2、前提
-
要有继承关系
-
要有方法重写
-
要有父类引用指向子类对象
3、多态中成员访问特点
成员变量
-
编译看左边,运行看左边
成员方法
-
编译看左边,运行看右边,因为子类对该成员方法进行了重写
静态方法
-
编译看左边,运行看左边
4、动态的好处和弊端
好处
-
提高了代码的维护性(继承保证)
-
提高了代码的扩展性(多态保证)
弊端
-
不能使用子类特有的属性和行为
抽象类
格式
abstract class 类名{//抽象类
public abstract void aaa();//抽象方法
}
-
抽象类中不一定有抽象方法
-
在一个类中出现了抽象方法必定是一个抽象方法或者是一个接口
-
抽象类不能实例化
-
抽象类的子类要吗是抽象类
-
要吗是重写抽象类中所有的抽象方法
抽象类如何实例化
-
按照多态的方法,父类引用指向子类对象
特征
-
抽象方法:是强制要求子类完成的
-
非抽象方法:子类继承的事情,提高代码的复用性
接口
什么是接口
-
侠义角度:接口就是interface
-
广义角度:对外提供规则的都是接口
特点
-
用关键字interface表示
-
格式:interface + 接口名{}
-
类实现接口 implements
-
格式:class 类名 implements 接口名称1,接口名称2...{}
-
接口不能实例化,要实例化就得按照多态的思想
-
接口的子类可以是抽象类,意义不大
-
可以是具体的实现类,重写接口中所有的抽象方法
-
接口可以继承接口,继承的接口的所有需要被实现类实现的方法都被继承过来了
-
接口中的成员变量永远是 public、static、final 的
-
接口不会有构造方法
-
默认修饰符 public、abstract\
异常
1、异常的简介
-
运行期间发生错误,而不是编译期间发生错误
2、异常类的继承关系
-
异常的根类:Throwable
-
两个子类为Error、IOError(两重大错误、底层、低级的、不可恢复的严重错误)和Exception(普通异常)
-
异常的分类
-
检查性异
必须写出相应的处理,否则无法运行
-
非检查性异常
没必要写出相应的处理,可编译运行
-
3、异常的处理机制
-
try{}catch(){},catch来捕获try抛出的异常
-
有try的情况下,可以有多个catch,捕获不同类型的异常
-
Throws 异常名称,抛给下一个调用者处理
关键字finally
-
放在try{}catch(){}的后面
-
finally所封装的语句,不管是否捕获成功,都是要执行的
-
通常是作为进行资源的清除工作
-
对应finally代码中的语句块,即使try{}catch(){}中使用了return、break、continue,它还是会执行,只要代码没运行到它前面退出虚拟机(System.exit(0);)它都执行。
4、自定义异常
集合
1、集合的由来
-
数组长度的固定,当数组增加或者减少元素的时候,太麻烦了,所以Java给我们提供了集合。
-
数组在内存中开辟等量空间,效率高,数组可以理解为无夹心的,集合可以理解为有夹心的
Collection<String> collection = new ArrayList<>();//只可以存储String类型的东西
Collection collection2 = new ArrayList();//可以存储任何类型的东西
2、迭代器
-
迭代器的概念:查看集合元素的就叫迭代器
InteraIterator inte = collection2.iterator();
while(inte.hasNext){
System.out.println(inte.next);
}
3、List里面的迭代器(ListIterator)
List list = new ArrayList();
ListIterator iListIterator = list.listIterator();
while(!iListIterator.hasNext()){
list.add("word");
}
-
hasNext()和hasPrevious()是一对,想要用hasPrevious(),必须先用hasNext(),涉及到指针问题,刚开始指针都指向下标0;
4、Vector
Vector v =new Vector();
v.addElement("a");
v.addElement("b");
v.addElement("c");
//迭代
Enumeration enumeration = v.elements();//Enumeration是Vector的迭代器
while (enumeration.hasMoreElements()) {
System.out.println(enumeration.nextElement());
}
5、Set集合
1、HashSet
-
当HashSet调用add方法存储对象的时候,先调用对象的hashcode方法得到一个哈希值,然后在集合中查找是否有和哈希值相同的对象
-
(1)如果得到一个相同的哈希值,就逐个比较,相同的抛出,不同的存入
-
(2)如果没有相同的就直接存入
2、LinkedHashSet
-
怎么存怎么取
-
用底层链表实现
-
保证元素的唯一性
3、TreeSet原理
-
特点:treeset是用来排序的,可以指定一个顺序,对象存入之后会按照顺序排序
-
自然排序 comparable
TreeaSet类的add方法中把存入的对象提升为comparable类型调用对象的compareTo()方法和集合中的对象进行比较,根据compareTo()方法返回的结果进行存储
-
比较器顺序 comparator
创建treeSet 的时候可以制定一个comparator,如果传入了comparator子类对象,那么treeSet就会按照比较器的顺序排序,add()会自定调用comparator中的compare()方法排序,调用的对象是compare方法的第一个参数,集合中的对象是第二个参数。
-
区别
TreeSet构造函数什么都不传,按照默认类中的comparable的顺序
TreeSet如果传入comparator,就会先安装comparator
6、Map
package Demo_Map;
import java.util.HashMap;
import java.util.Map;
public class MyMap {
public static void main(String[] args) {
Map myMap = new HashMap();
System.out.println(myMap.put(1,"hello"));
myMap.put(2,"hi~");
System.out.println(myMap.put(1,"world"));
System.out.println(myMap.containsKey(1));
System.out.println(myMap.containsKey("hello"));
System.out.println(myMap.isEmpty());
System.out.println(myMap.entrySet());
System.out.println(myMap.values());
System.out.println(myMap.keySet());
System.out.println(myMap.get(2));
}
}
//运行结果
null
hello
true
false
false
[1=world, 2=hi~]
[world, hi~]
[1, 2]
hi~
Map的遍历
package Demo_Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class MyMap {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("张三",12);
map.put("李三",12);
map.put("王三",12);
map.put("奥三",12);
map.put("常三",12);
Set<String> keyset = map.keySet();
Iterator<String> it = keyset.iterator();
while (it.hasNext()){
String key = it.next();
Integer value = map.get(key);
System.out.println("key:"+key+"-->value:"+value);
}
Set<Map.Entry<String,Integer>> entrySet = map.entrySet();
Iterator<Map.Entry<String,Integer>> iterator = entrySet.iterator();
while(iterator.hasNext()){
Map.Entry<String,Integer> en = iterator.next();
String str = en.getKey();
Integer num = en.getValue();
System.out.println("str:"+str+"num:"+num);
}
}
}
//结果
key:王三-->value:12
key:张三-->value:12
key:李三-->value:12
key:常三-->value:12
key:奥三-->value:12
str:王三num:12
str:张三num:12
str:李三num:12
str:常三num:12
str:奥三num:12
基本类型包装类
1、为什么会有基本数据类型包装类
-
将基本数据类型包装成对象的好处可以在对象中定义更多的功能,这些功能或者是方法可以操作数据
2、常用的操作
-
用于基本数据类型与字符串之间的转换
3、 基本数据类型对应的包装类
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
double | Double |
long | Long |
float | Float |
char | Character |
boolean | Boolean |
-
Integer构造器可以放String类型的数据,但是得是数字型的数字
泛型
1、好处
-
提高安全性
-
省去了强转
2、泛型的基本使用
-
<>里面的类型必须是引用数据类型
-
前后反省必须一致,后面的泛型可以不写内容,自动跟前面一致
3、泛型通配符
-
<?>
-
? extends E,向下限定,E 及其子类
-
? super E,向上限定,E 及其父类
设计模式
装饰设计模式
-
接口
package Demo_shejimoshi;
public interface Coder {
public void code();
}
-
Student类
package Demo_shejimoshi;
public class Student implements Coder{
@Override
public void code() {
System.out.println("发现能力不足以找工作");
}
}
-
TengtaiStudent类
package Demo_shejimoshi;
public class TengTaiStudent implements Coder{
/*
获取被装饰的引用
*/
private Student s;
public TengTaiStudent(Student s){
this.s = s;
}
@Override
public void code() {
s.code();
System.out.println("来滕泰学习来咯");
}
}
/
线程
1、什么是线程?
-
线程是程序的一个执行的路径,一个进程包含多个线程,多线程并发执行,提高程序的效率,可以同时完成多项工作,
2、多线程并行和并发
-
并行:两个任务同时进行,就是甲任务运行时,乙任务也在运行
-
并发:两个任务都请求运行,处理器只能接受一个任务,就把两个任务安排轮流执行,cpu效率高间隔断,使人感觉不到切换,以为两个任务都在运行。
3、Java运行程序的原理和JVM的启动是多线程吗?
-
原理:Java命令会启动虚拟机,等于说启动了一个应用程序,也就是启动了一个进程,该进程会自动启动一个主线程,然后主线程去调用某个类的main方法。
-
jvm启动是的多线程吗:启动至少启动了垃圾回收的一个线程、主线程,所以是多线程。
4、线程应用实现方式
thread类
-
定义类继承Thread
-
重写run方法
-
在里面写要实现的东西
-
创建线程对象
-
开启新线程.start();内部会自动执行run方法
-
好处:可以直接使用里面的方法,代码简单
-
弊端:如果有父类就不能用
//主线程和myTread的线程回会互抢着运行
package Demo_Throw;
public class Demo1 {
public static void main(String[] args) {
myTread myTread = new myTread();
myTread.start();
for (int i = 0;i<3000;i++){
System.out.println("bbb");
}
}
}
class myTread extends Thread{
@Override
public void run() {
for (int i = 0;i<3000;i++){
System.out.println("aaa");
}
}
}
Runnable接口
-
定义实现类实现接口
-
实现run方法
-
把新线程要做的是写在run方法中
-
创建自定义的runnable的子类对象
-
创建一个Thread对象传入Runnable
-
开启线程.start();会自动执行run方法
-
好处:有父类也能用
-
弊端:不能直接使用Thread类中的方法,比较复杂
package Demo_Throw;
public class MyRunnable implements Runnable{
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
for (int i = 0;i<10000;i++){
System.out.println("aaaaaaaaa");
}
}
@Override
public void run() {
for (int i = 0;i<10000;i++){
System.out.println("bbbbbbbb");
}
}
}
5、匿名内部类实现线程的方式
package Demo_Throw;
public class Demo2 {
public static void main(String[] args) {
//1、继承Thread类
new Thread(){
@Override
public void run() {
for (int i = 0;i<10000;i++){
System.out.println("aaaaa");
}
}
}.start();
//2、实现Runnable接口
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0;i<10000;i++){
System.out.println("bbbbb");
}
}
}).start();
}
}
6、获取名字和设置名字
获取名字
-
通过getName()方法获取线程的名字,默认从0到1命名
设置名字
-
通过构造函数传入String类型的名字
-
通过setName()方法设置名字
7、获取当前线程的对象
currentThread();//获取当前正在所执行的线程对象的引用
8、休眠线程
Thread.sleep(毫秒);//控制当前线程休眠多少毫秒
new Thread(){
@Override
public void run() {
this.setName("渣渣辉");
for (int i = 0;i<10;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("aaaaa");
}
}
}.start();
9、守护线程
对象.setDaemon(true or false);//设置指定线程方法
package Demo_Throw;
import java.io.IOException;
public class Demo2 {
public static void main(String[] args) throws IOException {
Thread t1 = new Thread(){
@Override
public void run() {
this.setName("渣渣辉");
for (int i = 0;i<2;i++) {
System.out.println("aaaaa");
}
}
};
Thread t2 = new Thread(){
@Override
public void run() {
this.setName("张学友");
for (int i = 0;i<10;i++) {
System.out.println("bbbbb");
}
}
};
t1.setDaemon(true);
t1.start();
t2.start();
}
}
10、加入线程
-
join():当前线程暂停,等待指定线程执行后当前线程再继续
-
join(int ):等待指定毫秒后再继续
package Demo_Throw;
public class Demo3 {
public static void main(String[] args) {
Thread t1 = new Thread(){
@Override
public void run() {
for (int i = 0;i<10;i++){
System.out.println("aaa");
}
}
};
Thread t2 = new Thread(){
@Override
public void run() {
for (int i = 0;i<100;i++){
try {
if(i == 5){
t1.join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("bb");
}
}
};
t1.start();
t2.start();
}
}
11、设置线程的优先级
对象.setPriority(1);//设置优先级,开发时候不要用这种方法,不好使,用if-else
12、同步代码块
-
关键字:synchronzed加上一个锁对象来定义一段代码,这就叫同步代码块。
-
多个代码块如果使用相同的锁对象,那么他们就是同步的
package Demo_Throw;
public class Demo4 {
Demo3 dd = new Demo3();
public void print(){
synchronized (dd) {//dd为对象锁芯,如果要用当前对象为锁芯的话,dd用this,如果当前有多个对象的话,用当前类.class
//当前类.class表示加载一次,如果有多个对象用this的话会加载多次
//而且当方法为静态的,不能用this因为static优先于对象
//方法为静态时候相当于上锁了
System.out.println("你好");
System.out.println("你好");
System.out.println("你好");
System.out.println("你好");
System.out.println("\r\n");
}
}
public void print1(){
synchronized (dd) {
System.out.println("再见");
System.out.println("再见");
System.out.println("再见");
System.out.println("\r\n");
}
}
public static void main(String[] args) {
final Demo4 demo4 = new Demo4();
new Thread(){
@Override
public void run() {
while(true){
demo4.print();
}
}
}.start();
new Thread(){
@Override
public void run() {
while(true){
demo4.print1();
}
}
}.start();
}
}
//输出的时候一个锁一个锁的来,没有锁的话会抢着来
//方法同步时
package Demo_Throw;
public class Demo4 {
Demo3 dd = new Demo3();
public static void print(){
System.out.println("你好");
System.out.println("你好");
System.out.println("你好");
System.out.println("你好");
System.out.println("\r\n");
}
public static void print1(){
System.out.println("再见");
System.out.println("再见");
System.out.println("再见");
System.out.println("\r\n");
}
public static void main(String[] args) {
final Demo4 demo4 = new Demo4();
new Thread(){
@Override
public void run() {
while(true){
demo4.print();
}
}
}.start();
new Thread(){
@Override
public void run() {
while(true){
demo4.print1();
}
}
}.start();
}
}
13、线程安全问题
举例:卖火车票,4个窗口,100张票
//继承Thread类
package Demo_Throw;
public class Demo5 extends Thread{
private static int ticket = 100;
public void run(){
while(true){
synchronized (Demo5.class){//
if(ticket == 0){
break;
}
System.out.println("这是第"+ticket--+"张票");
}
}
}
public static void main(String[] args) {
new Demo5().start();
new Demo5().start();
new Demo5().start();
new Demo5().start();
}
}
//另一
package Demo_Throw;
public class Demo5 extends Thread{
private static int ticket = 100;
public void run(){
while (true) {
buy();
if (ticket <= 0){
break;
}
}
}
public static synchronized void buy(){//this-->类.class
if (ticket >= 0) {
System.out.println("这是第:" + ticket-- + "张票");
}
}
public static void main(String[] args) {
new Demo5().start();
new Demo5().start();
new Demo5().start();
new Demo5().start();
}
}
//实现Runnable接口
package Demo_Throw;
public class Demo5 implements Runnable{
private static int ticket = 100;
public void run(){
while (true) {//while写在锁外面,避免死锁
buy();
if (ticket <= 0){
break;
}
}
}
public static synchronized void buy(){//this-->类.class
if (ticket >= 0) {
System.out.println("这是第:" + ticket-- + "张票");
}
}
public static void main(String[] args) {
Demo5 demo5 = new Demo5();
new Thread(demo5).start();
new Thread(demo5).start();
new Thread(demo5).start();
new Thread(demo5).start();
}
}
14、死锁
-
不能用锁去嵌套锁
反射
-
通过类名获取该类的属性和方法、构造方法等
-
动态地获取类的信息
-
运行的时候,获取类的对象信息并创建对象,调用方法
-
class类型:java.lang.Class
-
JVM运行的时候,把类加载到内存中,同时会创建这个类的Class类型的对象
-
该类封装了所有类的信息,包括属性方法、构造方法等
-
通过getXxx获取该Class类型对象的封装信息
//Computer类
package Demo_File1;
public class Computer {
public String name;
private String logo;
private String color;
private double price;
}
//获取Computer类的属性、方法
package Demo_File1;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class TestClass {
public static void main(String[] args) throws ClassNotFoundException {
//获取class类型的对象
//1、类名.class
Class c1 = Computer.class;
//Class.forName("类的路径")
Class c2 = Class.forName("Demo_File1.Computer");
//3、对象
Computer computer = new Computer();
Class c3 = computer.getClass();
//Filed成员变量
//获取成员变量
Field[] arrFs = c1.getFields();//获取公有成员变量
for(Field f:arrFs){
System.out.println(f.getName());
}
//获取属性
Field[] arrFD = c2.getDeclaredFields();//获取属性
for(Field f1:arrFD){
f1.setAccessible(true);
System.out.println(f1);
System.out.println(f1.getName());
}
//获取方法
Method[] arrM = c3.getMethods();
for (Method m:arrM){
System.out.println(m.getName());
}
//获取构造方法
Constructor[] arrC = c1.getConstructors();
for(Constructor c:arrC){
System.out.println(c.getName());
}
//获取内部类
Class<?>[] arrInnerClass = c2.getDeclaredClasses();
for(Class<?> c:arrInnerClass){
System.out.println(c.getName());
}
//获取接口
Class<?>[] arrInnerfaces = c3.getInterfaces();
for(Class<?> c:arrInnerClass){
System.out.println(c.getName());
}
}
}
创建对象
package Demo_File1;
public class TestNewInstance {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
//newInstance 创建对象
Class c = null;
c = Class.forName("Demo_File1.Computer");
Computer computer = (Computer) c.newInstance();//调用无参构造方法,创建之后就可以调用属性和方法了
/*
new 和 newInstance的区别
new可以调用有参和无参构造,强类型,效率高,可以调用任何public修饰的构造方法
newInstance调用无参构造,弱类型,效率低
*/
}
}
javabean
-
类中没有业务逻辑,类处理对象,进行封装
-
属性私有
-
有无参public修饰的构造方法
-
私有属性提供setter、getter方法
-
-
getXxx首字母大写,没有返回值
-
vo model pojo entity等
Inspector(内省机制)
-
内省机制就是通过getXxx、setXxx方法来判断Xxx是一个属性,内省机制会把Xxx的首字母变小写xxx
数据库链接步骤
-
1.加载驱动类
Class.forName(类的路径)
导入外部jar包
-
2.获取连接通道
DrvierManager.getConnection
url ip地址 端口号 数据库名字 3306 1521
user 用户名
password
-
3.创建载体
Statement
PreparedStatement extends Statement
预编译 效率高 防止sql注入
setInt(1,empno)
-
4.执行指令
executeUpdate
executeQuery ResultSet rs.next
getString(列名)
-
5.关闭资源
rs.close
pst.close
conn.close
//获取链接通道
public static Connection getConnection(){
Connection conn = null;
String url = "jdbc:oracle:thin:@localhost:1521:orcl";
// String url = "jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true";
String user = "scott";
String password = "tiger";
// String user = "root";
// String password = "123456";
//1、加载驱动类
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
// Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection(url,user,password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e1){
e1.printStackTrace();
}
return conn;
}