本人自己总结的corejava的知识点如下
环境变量的搭建
人与人沟通 自然语言 汉语、英语、日语、韩语…
人机对话 编程语言
低级: 机器语言
中级:汇编语言、C语言
高级:Java、Python
Oak 中小型消费电子产品 (收音机、微波炉)
—》 Java
Java运行机制:先编译,后解释
编译:将源文件(.java文件)
编译成 .class文件
(字节码文件,无限接近于二进制的文件)
解释并运行: 将.class文件
解释并运行
特点 : 跨平台,执行效率高
理念:Write Once Run Anywhere 一次编写,到处运行
**JVM(Java虚拟机) **: 屏蔽底层操作系统(OS)差异
JRE运行环境: JVM+解释器
JDK开发环境:JRE + 编译器+开发工具包(JDK类库+调试工具)
JAVA_HOME : jdk的安装目录, 例: C:\Program Files\Java\jdk1.8.0_92
Path : JDK 安装目录下的bin目录,例:C:\Program Files\Java\jdk1.8.0_92\bin
classpath : .
类路径
win+r cmd
dir
cd 文件夹名称
d:
cls
exit
创建.java
文件
代码
class HelloWorld{
public static void main(String[] args){
System.out.println("9班的同学们,你们好"); //换行打印
System.out.print("晚上要好好敲代码..."); //不换行打印
}
}
编译:javac 源文件名称.java
javac A.java
运行/解释:java 类名
java HelloWorld
注意:
1. 一个类中只能定义一个主函数
公开类
被public
修饰的类,称为公开类
public class Test{
public static void main(String[] args){
System.out.println("早上好");
}
}
作用:管理.class
文件
语法:package 包名
位置:源文件有效第一行
带包编译:javac -d . 源文件名称.java
带包运行 : java 包名.类名(全限定名)
书写格式
层级之间要有缩进(一个制表符(tab))
一行只写一句代码
代码注释
单行注释 // 注释内容
多行注释 /* 多行注释内容 */
文档注释 (生成外部文档javadoc -d 文件夹名称 源文件名称.java)/**文档注释内容 */
【了 解】
注意:注释不参与编译
标识符的命名规范
HelloWorld
helloWorldTest
.
隔开。采用域名倒置 , www.baizhi.com
--> com.baizhi.entity
_
隔开 HELLO_WORLD
**概念:**计算机内存中的一块存储空间,用来存储数据
变量的组成:变量名、变量类型、变量值
变量类型 变量名;
int a;
变量名 = 变量值;
a = 10;
System.out.println(a);
变量声明的多种方式
声明的同时并赋值 int b = 20;
同时声明多个变量并赋值
int b = 10,c,d = 40;
c = 30;
注意: Java是强类型的语言,数据类型
必须和变量类型
保持一致
基本|原始数据类型
整数
数据类型 | 字长 | 取值范围 | |
---|---|---|---|
byte | 1Byte (字节) | -128~127 | |
short | 2B | -32768~32767 | |
int | 4B | -2147483648~2147483647 | |
long | 8B | -9223372036854775808 ~9223372036854775807 -90京 ~ 90京 |
需要在字面值后追加L或l |
注意:整数的默认类型是int
小数,浮点数
数据类型 | 字长 | 精度 | |
---|---|---|---|
float | 4B | 单精度 | 必须在字面值后追加F或者f |
double | 8B | 双精度 | D或d 可加可不加 |
注意:浮点数的默认类型是double
字符型
char
字长2B 0~65535
采用 Unicode字符集 万国码
字面值形式 :
字符型 ‘A’
整数型 65-‘A’ 97 - ‘a’ 48-‘0’
16进制 ‘\u0041’ - ‘A’
转义字符:
转义字符 | 描述 |
---|---|
\n |
换行符 |
\t |
缩进(制表位) |
\\ |
反斜线 |
\' |
单引号 |
\'' |
双引号 |
布尔类型
boolean
true( 真 )\false(假)
注意:布尔类型不参与算数运算
引用|对象数据类型
字符串 String String s = "ashdjasd";
注意:字符串可以是0-n个字符组成
自动类型提升
两种类型相互兼容
目标类型 范围大于 源类型
byte --> short --> int --> long --> float --> double
char --> int
强制类型转换
两种类型相互兼容
目标类型 范围小于 源类型
int a = 10;
short s = (short)a;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6zgUBbAq-1574690630589)(D:/feiq/Recv Files/CoreJava/day02 ----变量及运算符/笔记/1571734285201.png)]
算数运算时类型提升
double + double/其他类型 --> double
float +其他类型(不含double) – > float
long + 其他类型(不包含double+float) --> long
int + 其他类型(不包含double+float+long) --> int
byte、short之间进行运算 --> int
注意: String类型可以和任意类型进行+
运算 , 结果自动提升为String类型 --》字符串拼接
表达式:使用运算符连接的变量或字面值,并可以得到一个最终结果。
算数运算符: + - * /(除) %(求模)
一元运算符: ++ 、-- 让自身+1 或者-1
a++ : 先取值,后自增 ; ++a : 先自增,后取值
赋值运算: = 、-=、+=、*=、/=、%= (不会进行类型转换)
关系运算符:< 、>、<= 、>=、==(判断是否相等)、!=(不等于) ——> 布尔表达式
逻辑运算符:
&&(并且|与) 两者都为true --> true
|| (或者|或) 有一个为true --> true
! (取反) !true --> false ; !false–>true
三元运算符: ? :
布尔表达式?值1:值2
思考:如何让a+1, 小于原来的a ??? [面试题]
//创建扫描仪
java.util.Scanner sc = new java.util.Scanner(System.in);
//让用户在控制台输入数据
//并且进行接收
String s = sc.next(); //接收一个字符串
int a = sc.nextInt(); //接收一个整数
double d = sc.nextDouble(); //接收一个小数
**注:**如果输入了不匹配的数据,则会产生java.util.InputMismatchException
定义位置:package 语句下方,class语句上方
语法:import 包名.类名;
import java.util.*; //导入 java.util包下的所有类
**注意:**默认导入java.lang包,String、System 都位于java.lang包;同包下的类不需要导入
概念:根据某个条件是否成立,来决定某段代码是否执行。
分支语句的执行次数0-1
次
if(布尔表达式){
//if代码块
}else{
//else代码块
}
if(布尔表达式1){
代码块1 }
else if(布尔表达式2){
代码块2 }
else if(布尔表达式3){
代码块3 }
else{
代码块4 }
后续代码...
if(){
if(){
}else if(){
}else{
}
}else{
} //当外层条件满足时,才会判断内层条件
if(){
}
if(){
}else{
}
if(){
}else if(){
}else{
}
if(){
if(){
}else if(){
}else{
}
}else{
if(){
}else if(){
}else{
}
}
switch(int表达式){
case 值1:代码块1
case 值2:代码块2
case 值3:代码块3
...
}
后续代码...
break
: 跳出switch代码块(手动添加出口)default
: 当所有的case不匹配时执行// 5 6 7差 8 9良好 10优秀
Scanner sc = new Scanner(System.in);
int score = sc.nextInt();
switch(score){
case 5:
case 6:
case 7:System.out.println("差");break;
case 8:
case 9:System.out.println("良好");break;
case 10:System.out.println("优秀");break;
default:System.out.println("输入有误");
}
细节:
int
以及所有能够提升为int
的数据类型 , byte、short、char、int对比:
用switch case 能做的,用if else 一定能做
用if else能做的 , 用switch case 不一定能做
概念:声明在函数内部的变量,称之为局部变量
特点:必须先赋值,后使用
作用范围:从定义行开始,到所在的代码块结束
注意:相同作用范围内
不允许命名重复
概念:根据某个条件是否成立,来多次执行同一段代码
循环的四部分:
执行次数:0-n次
while(布尔表达式){
//若布尔表达式为true,则执行逻辑代码;直至布尔表达式为false,则执行后续 代码
//逻辑代码
}
...
//打印10遍HelloWorld
int i = 0; //循环变量的初始化
while(i<10){
//循环条件 -- 决定了循环次数
System.out.println("HelloWorld"+i); //循环体
i++; //循环变量的迭代
}
while(true){
//死循环 -- 无限循环,没有结束的出口
System.out.println(111111);
}
int i = 0;
while(i<10){
System.out.println(111111);
}
执行次数:1-n次
do{
//逻辑代码
}while(布尔表达式);
for(循环变量的初始化;循环条件;循环变量的迭代){
//循环体 逻辑代码
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n6jN92MO-1574690630590)(D:/feiq/Recv Files/CoreJava/day04 ----循环/笔记/1571901148280.png)]
i = 0;i<10 执行10遍
i = 0;i<=10 11遍
i = 1;i<10 9遍
i = 1;i<=10 10遍
for(;;){
//死循环
System.out.println(1111);
}
break;
跳出switch代码块、循环结构
continue;
跳出本次循环
for(int i=0;i<3;i++){
//外层循环决定行数
for(int j=0;j<5;j++){
//内层循环决定列数
System.out.print("*");
}
System.out.println(); //换行
}
// i=0 j=0 1 2 3 4 * * * * *
// i=1 j=0 1 2 3 4 * * * * *
// i=2 j=0 1 2 3 4 * * * * *
outer:for(int i=1;i<=5;i++){
//label标签 给循环起的名字
inner:for(int j=1;j<=4;j++){
if(j==2) break outer; //跳出的时候 指定跳出的循环
System.out.print("i="+i+",j="+j+"\t");
}
System.out.println();
}
函数的声明 约定了函数的功能 public static 返回值类型 函数名(形参列表)
参数【重点】:调用者向被调用者传递的数据
形式参数(形参):变量的声明,相当于函数内部的局部变量
实际参数(实参):为形参赋值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LhPSfH9x-1574690630590)(D:/feiq/Recv Files/CoreJava/day05 ----函数/笔记/1571986656196.png)]
注意:实参和形参必须保证,数量、类型、顺序
一致
返回值【重点】:被调用者返回给调用者的数据
返回值类型 :
void : 没有返回值
八种基本数据类型、String
public static void main(String[] args){
int d = add();
System.out.println(d);
}
//计算两个数的和
public static int add(){
return 10; //return value; 将数据value进行返回
}
return 关键字:
return value;
语句后不要定义代码return value;
语句被执行return value;
语句return
关键字,控制函数执行流程函数的实现 实现约定的功能 { //代码块 }
定义位置 类以内,与主函数并列
函数的调用【重点】
无参调用:函数名();
有参调用:函数名(实参列表);
有返回值调用:数据类型 变量名 = 函数名(实参列表);
注意:数据类型
跟返回值类型
一致
public static 返回值类型 函数名(形参列表){
//函数的实现代码
}
返回值类型、函数名、形参列表 ---》 函数三要素
在一个函数内部调用另外一个函数
一个函数调用了它本身,称之为递归调用
注意:需要为递归函数手动添加出口,否则会无穷递归,运行报错
报错信息为java.lang.StackOverflowError
(内存溢出)
递归的思想:
当解决一个大问题时,可以分解为多个小问题;而且小问题的解决方案跟大问题一致。可以使用递归
相同
数据类型的数据声明数组 : 数据类型[] 变量名;
int[] a; int []a; int a[];
声明数组的多种方式
声明的同时并分配空间:数据类型[] 数组名 = new 数据类型[长度];
声明的同时并为元素赋值:int[] a = new int[]{
元素值1,元素值2,元素值3,...};
注意:不再为其分配长度
int[] a = {
元素值1,元素值2,元素值3,...};
注意:
int[] a ;
a = {
元素值1,元素值2,元素值3,...}; //error
分配空间: 变量名 = new 数据类型[数组的长度];
a = new int[5];
数组的下标范围: 0 - 数组名.length-1
元素访问 : 数组名[下标];
当访问超出下标范围的元素,则运行报错:
报错信息为:java.lang.ArrayIndexOutOfBoundsException(下标越界)
数组的长度:数组名.length
数组的遍历:一一获取所有元素
for(int i=0;i<a.length;i++){
System.out.print(a[i]+"\t");
}
System.out.println();
数组元素具有默认值:
byte\short\int\long 0
float\double 0.0
char 空字符|0
boolean false
String null
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r7IWApB3-1574690630590)(D:/feiq/Recv Files/CoreJava/day06 ----数组01/笔记/1572234738834.png)]
优点:便于通过数组的首地址,计算出每一个元素的地址 查询快
a[i] = 首地址+字长*i
缺点:长度固定
数组的扩容
一、【理解】
1. 定义一个新数组,长度大于原数组
2. 将原数组中的元素一一挪到新数组
3. 更新地址
int[] a = {
10,20,30,40};
int[] b = new int[a.length*2];
for(int i=0;i<a.length;i++){
b[i] = a[i];
}
a = b;
二、使用Arrays工具类【开发重点】
int[] a = {
10,20,30,40};
a = java.util.Arrays.copyOf(a,a.length*2); //返回一个扩容后的数组
三、了解
//将原数组中的元素 挪到新数组
System.arraycopy(原数组,起始下标,新数组,存储元素的起始下标,长度);
数组应用于参数:实参为形参赋值时,传递的是地址
数组应用于返回值:需将函数内部数组的地址进行返回
概念:可接收多个同类型
实参的参数 , 不限个数
语法:数据类型…参数名
使用方式和数组相同
public static void m1(int...a){
//可变长参数a
//遍历数组
for(int i=0;i<a.length;i++){
System.out.print(a[i]+"\t");
}
System.out.println();
}
注意:可变长参数只能定义在形参列表最后,而且只能定义一个
冒泡排序 : 相邻的两个元素比较大小,互换位置【面试重点】
//实现将数组进行从小到大进行排列
//相邻的两个元素进行比较,大的后挪
int[] a = {
8,7,6,4,3};
/* 8 7 6 4 3
0-1 7 8 6 4 3 比较轮数 长度-1
1-2 7 6 8 4 3 每一轮做的事 a[i]>a[i+1] 交换位置
2-3 7 6 4 8 3
3-4 7 6 4 3 8
0-1 6 7 4 3 8
1-2 6 4 7 3 8
2-3 6 4 3 7 8
0-1 4 6 3 7 8
1-2 4 3 6 7 8
0-1 3 4 6 7 8
*/
for(int i=0;i<a.length-1;i++){
//外层循环控制比较轮数
//每一轮的内容
for(int j=0;j<a.length-1-i;j++){
//内层循环表示元素下标
if(a[j]>a[j+1]){
int temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
选择排序:拿固定元素和后面的元素做比较【面试重点】
for(int i=0;i<a.length-1;i++){
//固定下标
for(int j=i+1;j<a.length;j++){
//表示后面的元素对应的下标
if(a[i]>a[j]){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
JDK排序【开发重点】
java.util.Arrays.sort(数组名称); //将数组按升序排序
概念:一维数组中的一维数组。一维数组的元素又是一个一维数组。
使用流程:
[][]
a; int[][] a;
a = new int[行数|高维数组的长度][列数|低维数组的长度];
二维数组的多种声明方式
int[][] a = new int[3][4];
int[][] a = new int[][]{
{
10,20,30},{
1,2},{
10,30,50,60},...}; //不规则二维数组
int[][] a = {
{
10,20,30},{
1,2},{
10,30,50,60},...};
int[][] a = new int[3][];
a[0] = new int[3];
a[1] = new int[2];
a[2] = new int[5];
元素访问:数组名[行号|高维数组的下标][列号|低维数组的下标];
二维数组的遍历
数组名.length --> 高维数组的长度
for(int i=0;i<a.length;i++){
for(int j=0;j<a[i].length;j++){
//表示低维数组的下标
System.out.print(a[i][j]+"\t");
}
System.out.println();
}
5.二维数组的内存特点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vLwCuC0l-1574690630591)(D:/feiq/Recv Files/CoreJava/day06 ----数组01/笔记/1572333835072.png)]
面向过程:自顶向下、逐步求精
面向对象:
类
来去描述对象属性:代表有什么 ——> 实例变量、成员变量
语法:数据类型 变量名;
定义位置:类以内,方法外部
属性具有默认值:
数值类型:0/0.0
布尔类型:false
引用类型:null
成员变量和局部变量的区别???
成员变量 | 局部变量 | |
---|---|---|
定义位置 | 类以内,方法外部 | 方法内部 |
是否具有默认值 | 具有默认值 | 必须先赋值,后使用 |
作用范围 | 类的内部 | 定义行开始,到所在的代码块结束 |
命名冲突 | 成员变量和局部变量命名冲突时,局部变量优先 | 相同作用范围内,不允许命名冲突 |
方法:代表行为 ——> 成员方法
语法:public 返回值类型 方法名(形参列表){
//方法实现
}
定义位置:类以内,其他方法外部
创建对象 : 在内存中开辟连续的空间
new关键字
类名 对象名 = new 类名();
Student s = new Student();
访问属性:对象名.属性名
访问方法:对象名.方法名(实参);
概念:在一个类内部,定义了多个相同名字的方法
要求:方法名相同,但是参数列表不同(类型不同、顺序不同、个数不同)
作用:会根据传入的参数,精确匹配对应的方法
注意:若不能精确匹配,则就近向上匹配
;但是要避免混淆
public void m1(double d,int a){
System.out.println("m1(double,int)");
}
public void m1(int a,double d){
System.out.println("m1(int,double)");
}
----------------------------------------------
m1(10,10); //混淆 -- 编译报错
好处:使代码更加灵活、屏蔽差异
public 类名(){ }
构造方法名必须和类名保持一致;没有返回值类型,连void都没有[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VG8PcuYl-1574690630591)(D:/feiq/Recv Files/CoreJava/day08 ----面向对象/笔记/1572425174639.png)]
this.
: this 代表当前对象 ,可以在成员方法、构造方法
中使用
this.属性名: 获取当前对象的属性
this.方法名(实参) : 调用当前对象其他方法
this()
: 调用本类其他构造方法,只能使用在构造方法
中
this() : 调用本类的无参构造
this(实参):调用本类的有参构造
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bkuMMh40-1574690630591)(D:/feiq/Recv Files/CoreJava/day08 ----面向对象/笔记/1572493516402.png)]
注意: 1. 必须定义在构造方法有效第一行
2. 避免递归调用构造方法
```java
public B(){
this(10);
}
public B(int a){
this();
} //erro 递归调用构造方法
#### 引用
1. 对象类型的变量称之为引用
`类名 引用名 = new 构造方法名();`
***注意:*** 引用数据类型必须和对象类型保持一致
2. 引用中存储的是对象的首地址
3. 每个对象空间在堆空间中,相互独立
4. 引用之间相互赋值赋的是地址
基本数据类型之间传递的是数值
5. 当引用值为null时,使用属性和方法,会运行报错:
报错信息为:`java.lang.NullPointerException(空指针异常)`
6. 引用的应用:应用于参数、返回值、数组
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3cwiKo2b-1574690630592)(D:/feiq/Recv Files/CoreJava/day08 ----面向对象/笔记/1572507779188.png)]
private 修饰属性 --> 私有属性
只能在本类中访问
需要提供对应的方法
public void setXXX(形参){
//setXXX set+属性名,属性名首字母大写
属性 = 参数值;
}
public 返回值类型 getXXX(){
//getXXX get+属性名,属性名首字母大写
return 属性值;
}
private int age; //属性私有化
//提供set方法 --》 为age赋值
public void setAge(int age){
if(age>0&&age<150){
this.age = age;
}else{
System.out.println("请输入合法的年龄");
}
}
//提供get方法 -- > 获取属性值
public int getAge(){
return this.age;
}
***注意:***一个get方法只能获取一个属性值;一个set方法只能为一个属性赋值
红笔 is a 笔
狗 is a 动物
学生 is a 人
is a
关系extends
class Student extends Person{}
Student 继承于 Person
子类 继承于 父类
在子类中定义和父类中一致的方法
要求:方法三要素(返回值类型、方法名、参数列表)相同
访问修饰符 要求相同或更宽
注意:若形参列表不同,则不会编译报错,而是构成方法重载
若子类中覆盖了父类中的方法,则实际运行是子类中覆盖后的方法
Java中的类是单继承,一个子类只能有一个直接父类;
但是可以多级继承,一个子类可以有多个间接父类。
属性和方法是逐级叠加的
构造方法不能被继承
属性和方法由访问修饰符决定是否被继承:
访问修饰符访问权限
本类 | 同包 | 非同包子类 | 非同包非子类 | |
---|---|---|---|---|
private(私有的) | √ | × | × | × |
[default] (默认的) |
√ | √ | × | × |
protected(受保护的) | √ | √ | √ | × |
public(公开的、公共的) | √ | √ | √ | √ |
从严到宽
哪些属性、方法可以被继承:
private修饰 不可被继承
[default] 修饰 同包子类可以被继承
protected 可以继承
public 可以继承
在创建子类对象时,会先构建父类对象
分配空间 (父类+子类)
递归的构建父类对象
i. 初始化父类属性
ii.调用父类构造方法
初始化子类属性
调用子类构造方法
super() : 调用父类中的构造方法
super(); 调用父类无参构造
super(实参); 调用父类有参构造
注意:
super();
super.
super 代表父类对象
super.父类属性名;
调用父类的属性
super.父类方法名(实参);
调用父类的方法
多态
Animal a = new Dog();
父类引用 子类对象
类型提升 ---->向上转型
Dog d = new Dog();
Animal a = d; //多态
强制类型转换 ---->向下转型
Animal a = new Dog();
Dog d = (Dog)a;
注意【重点】:
1. 若转换双方存在继承关系,则强转一定编译通过;但是若引用中存储的实际对象类型和目 标类型不匹配,则运行报错 , 报错信息为:java.lang.ClassCastException(强制类型转换异常)
Animal a = new Cat();
Dog d = (Dog)a; //运行报错 强制类型转换异常
2. 若转换双方没有继承关系,则编译报错
如何避免强制类型转换异常??? 【重点】
关键字:instanceof
用法: 引用名 instanceof 对象类型(目标类型)
判断引用中存储的实际对象类型和目标类型是否一致;
若一致,则为true;若不一致,则为false
屏蔽了子类差异,使代码更加灵活
public abstarct 返回值类型 方法名(参数列表);
修饰属性 ——> 静态属性、类变量
全类共有的,与创建多少对象无关
访问方式:类名 . 静态属性名
——>常用
对象名 . 静态属性名
修饰方法 ——> 静态方法
语法: public static 返回值类型 方法名(参数列表){ //方法实现 }
注意:public 和 static 没有先后顺序
访问方式:类名.静态方法名(实参)
——> 常用
对象名 . 静态方法名 (实参)
注意:
静态方法中不能访问非静态成员(属性、方法)
静态方法中只能访问静态成员(属性、方法)
非静态方法可以访问非静态成员和静态成员
静态方法中不能使用this和super关键字
静态方法允许被覆盖,但是只能被静态方法覆盖;而且没有多态
class MyClass{
public static void m1(){
System.out.println("m1()...");
}
}
class SubClass extends MyClass{
public static void m1(){
System.out.println("子类m1()...");
}
}
--------------------------------------------
MyClass mc03 = new SubClass();
mc03.m1(); //m1()...
修饰初始代码块 ——> 静态代码块
初始化代码块【了解】:
定义位置:类以内,方法外部
执行:在创建对象的第二步执行,与初始化属性,根据定义的先后顺序来去执行
静态代码块【开发应用重点】:
定义位置:类以内,方法外部,被static修饰
执行:在类加载时执行,与初始化静态属性,按照定义的先后顺序来去执行。
只执行一次。
类加载【理解+面试重点】
当JVM第一次使用一个类时,会通过classpath(类路径)加载它的所有信息(包名、类名、父类、方法、属性、构造方法…),保存在JVM内存中。这个过程称之为类加载。
类加载只会执行一次。
类加载的时机:
i. 第一次创建对象时:先进行类加载,再创建对象
ii. 第一次通过类名访问静态属性、静态方法
iii. Class.forName(“类全限定名”);
iv. 当创建子类对象时
先进行父类类加载,再进行子类类加载;
先创建父类对象,再创建子类对象;
修饰变量(属性、局部变量、类变量)
被final修饰的变量称之为作用范围内的常量
:只允许赋值一次;不可被更改
修饰属性:
被final修饰的属性没有默认值
赋值时机:显示初始化,初始化代码块,构造方法
注意:三个机会,只能选其一
修饰类变量(静态变量)
被final修饰的静态变量(static final int b; //静态常量)
没有默认值
赋值时机:显示初始化,静态代码块
注意:只能任选其一
被final修饰的基本数据类型 值不可以更改
被final修饰的引用数据类型 指向的地址不可以更改
修饰方法
语法:访问修饰符 final 返回值类型 方法名(形参列表){ }
注意:访问修饰符和 final不分先后
可以继承,不允许覆盖
修饰类(断子绝孙类)
注意
interface 接口名{}
interface MyInter{
int a = 10; //public static fianl int a = 10;
void m1(); //public abstract void m1();
}
注意:接口不是类
class MyClass implements 接口名{}
实现类必须实现接口中的所有方法。访问修饰符只能是public
使用 :
//接口类型的引用 指向 实现类类型的对象 -->多态
MyInter mi = new MyClass();
类和类之间是单继承
接口和接口之间是多继承
interface 接口名1 extends 接口名2,接口名3,...{}
一个类可以实现多个接口
class 类名 implements接口1,接口2,...{}
一个类可以继承父类的同时,实现多个接口
class 类名 extends 父类名 implements接口1,接口2,...{}
互相强转的双方,若一方是接口类型,则强转编译一定通过;
但是运行时会判断,引用中指向的实际对象类型和目标类型是否匹配,
若匹配,则编译通过,运行通过;
若不匹配,则编译通过,运行报错:
报错信息为:java.lang.ClassCastException
(类型转换异常)
先有接口的使用者,后有接口的实现者。
所有类的超类、根类、父类
Object类型的引用可以指向任意类型的对象。
Object o = new Student();
Object类中方法,是所有类所共有的
getClass()
: 获取引用中存储的实际对象类型【重点】
通常用于判断两个引用中指向的实际对象类型是否一致
//o引用中指向的实际对象类型是否和p引用中指向的实际对象类型一致
if(o.getClass()==p.getClass()) {
System.out.println("一致...");
} else {
System.out.println("不一致...");
}
int hashCode()
: 返回该对象的哈希码值(对象的整数表现形式)
String toString()
: 返回该对象的字符串表现形式(所有的属性内容)[重点]
要求:需要重写toString()方法
public String toString(){
return 属性值拼接成的字符串;
}
boolean equals(Object o)
: 比较对象的内容是否相同[重点]
==:比较基本数据类型,比较的是数值
比较引用数据类型,比较的是地址
对象之间比较内容(属性值)是否完全相同,需通过equals方法,自定义类型需要重写equals
重写规则:
public boolean equals(Object o) {
//1. 自反性(比较this和o是否指向同一对象)
if(this==o) return true;
//2. 非空判断 判断o是否为null
if(o==null) return false;
//3. 判断当前对象和o是否是同一类型
if(this.getClass()!=o.getClass()) return false;
//4. 强制类型转换
Dog d = (Dog)o;
//5. 逐一比较属性
if(this.age==d.age&&this.sex==d.sex&& this.name.equals(d.name)) {
return true;
}
return false;
}
finalize()
:垃圾回收器回收垃圾对象时调用的方法【不要在这个方法中定义逻辑代码】
垃圾对象:没有引用指向的对象,称之为垃圾对象
垃圾回收:销毁垃圾对象,清理内存空间
垃圾回收器回收垃圾 对象的时机【了解】:
自动回收机制:当JVM内存耗尽时,垃圾回收器会自动回收所有垃圾对象
手动回收机制:通过System.gc();
手动的通知垃圾回收器做垃圾回收。
若垃圾收器空闲,则回收;若忙,则不回收。
**概念:**在一个类的内部定义了一个完整的类。
特点 :
Outer$Inner.class
定义位置 : 类的内部,方法外部
如何创建对象:
//创建外部类对象
//依赖外部类-->创建内部类对象
Outer o = new Outer();
Outer.Inner inner = o.new Inner();
注意事项:
外部类对象 外部类类名.this
访问外部类对象的属性 外部类类名.this.属性名
成员内部类中不能定义静态成员(属性、方法)
定义位置:类的内部,方法外部,被static修饰
如何创建对象:
Outer.Inner inner = new Outer.Inner();
注意事项:
定义位置 : 方法内部
如何创建对象:
在定义它的方法内部创建,要创建在类定义完成之后
public static void main(String[] args) {
class Inner{
//局部内部类
int a = 10;
public void m1() {
System.out.println(111);
}
}
new Inner(); //创建局部内部类对象
}
注意事项:
它可以访问它所在方法的局部变量,但是这个变量必须被final修饰(语法规定)
在JDK 1.8开始, 局部变量默认被final修饰(语法糖)
好处:做到接口公开,实现隐藏;实现弱耦合
定义位置:定义方法内部,一个特殊的局部内部类(局部内部类具有的特点它都有)
创建对象:
没有类名,必须实现一个接口或者继承一个父类
new 接口名(){
//匿名内部类的内容-->必须实现的接口的方法
}
------------------------------
new 父类类名(){
//类的内容
}
注意:
坏处:可读性差
好处:使代码更加灵活 , 减少代码量
**概念:**为八种基本数据类型提供的对象数据类型。
基本数据类型 | 包装类类型(java.lang) |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
int <——>Integer
int a = 10;
Integer i1 = new Integer(a); //通过构造方法
// static Integer valueOf(int i) :将整数转换为Integer对象
Integer i2 = Integer.valueOf(a);
// int intValue() 返回Integer对象的int值
int b = i2.intValue();
String <——> Integer
String s = "123";
Integer i3 = new Integer(s); //通过构造方法
// static Integer valueOf(String s)
Integer i4 = Integer.valueOf(s);
String s1 = i3+"";
String s2 = i3.toString();
String <——>int
// static int parseInt(String s)
int c = Integer.parseInt(s);
int a = 10;
String s = a+"";
注意: String 转换为 数值类型时,String字面值必须是纯数字格式;
否则,会运行报错,报错信息为:java.lang.NumberFormatException(数字格式转换异常)
Since JDK 5.0 提供了自动拆箱和自动装箱的功能。基本数据类型和包装类类型之间可以自动转换。
自动拆箱:包装类类型——>基本数据类型
自动装箱:基本数据类型——>包装类类型
在自动装箱时,默认调用valueOf方法;对-128~127之间的数做了预先包装,存放在缓冲区内(常量池)。提高效率。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hyXn4i9I-1574690630593)(D:/feiq/Recv Files/CoreJava/day16 ----常用类/笔记/1573454017007.png)]
用于区分0和null,用于区分有效数据和无效数据
char charAt(int index):
根据下标返回对应的字符
int length()
: 返回值字符串的长度
*注意:*s.length() , 调用方法获取长度
数组名.length :获取数组长度
int indexOf(String str):
返回字符串str在当前字符串中第一次出现的下标;
若不存在此字符串,则返回 -1
int lastIndexOf(String str)
: 返回字符串str在当前字符串中最后一次出现的下标;
若不存在此字符串,则返回 -1
String substring(int beginIndex,int endIndex)
: 返回beginIndex ~ endIndex组成的字符串
(包含beginIndex ,不包含endIndex )
String[] split(String str):
根据str 对字符串进行拆分,返回拆分后的数组
String toUpperCase()
: 将字符串转换成全大写
String toLowerCase()
: 将字符串转换成全小写
boolean endsWith(String str) :
判断字符串是否以str结尾
boolean contains(String str)
: 判断字符串中是否包含str;若包含-true,若不包含-false
String s = "abc"; 字面值形式
只会产生一个对象 存放在串池中
String s = new String("abc"); 构造方法创建
产生两个对象 一个存放在串池中,一个存放在堆空间中
intern() : 返回 s 对象在串池中的字符串对象
String s1 = "abc";
String s2 = s1;
s1+="bcd"; //s1指向的地址发生改变
System.out.println(s2); //abc
System.out.println(s1); //abcbcd
String类型在做拼接时,不会在原有的对象上进行改变,而是创建新的空间存储拼接后的对象。
导致,字符串拼接效率过低
StringBuffer
: JDK 1.0 线程安全,运行效率低
StringBuilder
: JDK 5.0 线程不安全,运行效率高
常用:
append(String s)
:拼接字符串 (类似于String的+)
BigDecimal bd=new BigDecimal(“1.0”);(推荐使用)
BigDecimal add(BigDecimal bd)
加
BigDecimal subtract(BigDecimal bd)
减
BigDecimal multiply(BigDecimal bd)
乘
BigDecimal divide(BigDecimal bd)
除
BigDecimal bd6 = new BigDecimal("10");
BigDecimal bd7 = new BigDecimal("3");
// 2 :表示取小数点后两位
//BigDecimal.ROUND_HALF_UP:四舍五入
BigDecimal bd8 = bd6.divide(bd7,2,BigDecimal.ROUND_HALF_UP); // bd8 = bd6/bd7
注意: 若不能整除则需指定取舍位数,否则运行报错
**概念:**存储多个对象的容器,本身也是一个对象。
add(Object o):
增加一个元素
contains(Object o):
判断集合中是否包含元素o
remove(Object o):
删除元素o
int size():
返回有效元素个数
特点:有序有下标元素可以重复
常用方法:
* add(Object o):
增加一个元素
* add(int index,Object o)
: 向指定位置处插入一个元素
* remove(int index):
根据下标删除元素
* set(int index, Object o)
: 将index下标处对应的元素,替换为o
* get(int index)
: 根据下标获取对应的元素
* int size():
返回有效元素个数
contains(Object o):
判断集合中是否包含元素o
indexOf(Object o)
: 返回元素第一次出现的下标,若不包含则返回-1
lastIndexOf(Object o)
: 返回元素最后一次出现的下标,若不包含则返回-1
subList(int fromIndex, int toIndex)
: 返回fromIndex(包含)~toIndex (不包含)
之间元素组成的List集合
实现类:ArrayList
实现类之间的区别???【面试重点】
ArrayList
JDK 1.2 线程不安全 效率高
数组实现 内存空间连续,查询快,增删慢
Vector
JDK 1.0 线程安全 效率低
LinkedList
链表实现 内存空间不连续,查询慢,增删快
查询多 ——> ArrayList
增删多 ——> LinkedList
遍历
下标遍历:
for(int i=0;i<list.size();i++) {
System.out.println(list.get(i));
}
for-each遍历
for(数据类型 变量名:集合名称|数组名称){
// 变量名 --> 表示元素
}
注意: 数据类型和泛型类型保持一致
概念:类型安全的集合,强制集合元素类型一致
List
注意:
自定义泛型类 [了解]
class MyClass<T>{
//自定义泛型类
private T a;
public T getA() {
return a;
}
public void setA(T a) {
this.a = a;
}
}
注意:
泛型的类型 在创建对象时决定
MyClass<String> mc = new MyClass<>(); //决定泛型为String类型
通常使用T/K/V/E作为泛型标识
interface IA<K,V>{
void m1(K k);
void m2(V v);
}
class MyClass01<K,V> implements IA<K,V>{
public void m1(K k) {
}
public void m2(V v) {
}
}
-------------------------------------------------
IA<Integer,String> ia = new MyClass01<>();
概念:一个工具类,提供了操作集合的方法
static void reverse(List list)
: 反转集合中的元素
static void shuffle(List list)
: 将集合中的元素 , 随机重置
static void sort(List list):
对集合中的元素进行升序排序
注意:若集合中元素是自定义类型,则需要自定义类实现Comparable接口,实现comparTo方法
public int compareTo(Student o) {
//定义排序的规则
//拿当前对象的属性 和 参数o的属性值 做对比
//如果当前对象的属性值 > 参数O对象的数值 则返回正整数 1
//如果当前对象的属性值 < 参数O对象的数值 则返回负整数 -1
//如果当前对象的属性值 == 参数O对象的数值 则返回0
if(this.age>o.age) return 1;
else if(this.age<o.age) return -1;
else {
//代表年龄相等的情况
return this.name.compareTo(o.name);
}
}
特点:无序无下标,元素内容不可以重复
常用方法:全部继承于Collection
实现类:HashSet
***HashSet如何实现元素内容不重复???***【面试重点】
基于hashCode值实现元素内容不重复
当hashCode值相同时 , 会调用equals方法进行比较内容是否一致
hashCode的重写规则: 目的是保证属性值相同的两个对象,哈希码值相同
public int hashCode() {
//把所有的属性值进行计算出一个整数 进行返回
return name.hashCode()+age+(int)score;
}
遍历方式:
for-each
迭代器遍历
//1. 获取迭代器对象 iterator():返回迭代器对象 Iterator:表示迭代器
//2. 调用方法 判断指针后是否还有元素 hasNext():判断是否还有元素 若有- true;若没有-false
//3. 调用方法 使指针后移一位,并且将跨过的元素进行返回 next():返回下一个元素
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()) {
String s = iterator.next();
System.out.println(s);
}
概念:在程序运行过程中,产生的意外情况
**异常处理:**提高程序的容错性,提前准备好应对异常的代码,正常情况下不执行
try{
插入银行卡
输入密码和金额
金额-=2000
吐钱2000
}catch(){
金额+=2000
}finally{
退卡
}
Throwable
:所有异常的父类,位于java.lang
包下
Error : 严重错误,无法处理
java.lang.StackOverflowError
内存溢出
Exception
RuntimeException
运行时异常|未检查异常
可以避免,可处理可不处理
NullPointerException
: 空指针异常
IndexOutOfBoundsException
: 下标越界异常
ClassCastException
: 类型转换异常
NumberFormatException
: 数字格式转换异常
非RuntimeException
非运行时异常|已检查异常
不可避免,必须处理
FileNotFoundException
: 文件找不到异常
EOFException
: 文件到达结尾异常
自动产生:程序运行过程中,遇到错误的代码,导致程序终止。
手动产生:
throw new 异常类名(); //手动产生异常
1)定义在方法内部
2)相当于return语句,导致方法的终止
按着方法的调用链方向反方向传递,直至JVM,最终导致程序终止。
throws: 定义在方法声明之后
public static void m2(int i) throws 异常名1,异常名2{
}
注意 : 只是推卸责任的处理方式,最终异常并没有得到解决
方法覆盖(终极版)
返回值类型、方法名、参数列表 要和父类保持一致
访问修饰符 相同或更宽
不能比父类抛出更多、更宽的异常
try{
//可能出现异常的代码
}catch(异常类名1 e){
//当异常出现时会执行的代码
}catch(异常类名2 e){
// 当另外一个异常出现时会执行的代码
}
try{
//有可能发生异常的代码 }
catch() {
//异常发生时执行的代码 }
finally{
//不管是否发生异常 都一定会执行的代码 }
//常用结构小结
try{
}catch(){
}
try{
}catch(){
}catch(){
}catch(){
}
try{
}catch(){
}finally{
}
try{
}catch(){
}catch(){
}catch(){
}finally{
}
try{
}finally{
}
try{
try{
}catch(){
}finally }catch(){
}
try{
}catch{
try{
}catch(){
}finally{
} }
try{
}catch(){
}finally{
try{
}catch(){
}finally{
} }
1. try 后必须跟一个catch或者finally代码块
2. 若catch和finally同时出现,则finally必须定义在catch之后
要继承于Exception|RuntimeException ;
继承于Exception 表示已检查异常;继承于RuntimeException 未检查异常
提供有参无参构造
class CheckPasswordException extends Exception{
public CheckPasswordException() {
super();
}
public CheckPasswordException(String message) {
super(message);
}
}
按方向划分(以JVM为参照物):
输入流:从外部存储设备 ——> JVM内存 读
输出流:从JVM内存——>外部存储设备 写
按单位划分
字节流:以字节为单位,可以操作任意类型的文件
字符流:以字符为单位,只能操作文本类型的文件;
文本类型的文件:使用记事本能够打开的文件.txt, .java , .html…
按功能划分
节点流 : 只具有基本的读写功能
过滤流: 在节点流的基础上,增加新的功能。
字节流抽象父类
OutputStream
(字节输出流) --> 写操作
|- write(int b):向外部存储设备 写入一个字节
|- write(byte[] b) : 写入b.length个字节
|- write(byte[] b, int off, int len): b表示数组,off表示开始下标,len表示写入的长度
InputStream
(字节输入流) --> 读操作
|- int read() : 从外部存储设备读取一个字节。若没有读取到 则返回-1。
|- read(byte[] b) : 一次性读取多个字节,并且将读取到的数据存放在b数组中
|- read(byte[] b, int off, int len):一次性读取len个字节,并且将读取到的数据存放在b数· 组中;存储的位置从off开始,
文件字节流
FileOutputStream
: 文件字节输出流创建对象
FileOutputStream fos = new FileOutputStream("文件路径");
注意:
1. 文件路径中指定的文件,若文件存在则选择已经存在的,若不存在则新创建一个;
若文件夹不存在,则不新创建,而是运行报错:
报错信息为:java.io.FileNotFoundException
2. 路径可以定义为绝对路径或者相对路径
绝对路径:E:/CoreJava/day20 ----流IO/笔记/a.txt
相对路径: a.txt 产生的文件在当前项目的根目录下
3. FileOutputStream fos = new FileOutputStream("文件路径",true);
true 代表在原有的文件上进行追加
false 代表在原有的文件上进行覆盖,默认为false
FileInputStream
: 文件字节输入流FileInputStream fos = new FileInputStream("文件路径");
注意:
1. 路径中指定的文件必须存在,否则运行报错
报错信息为:java.io.FileNotFoundException
如何实现文件复制???
FileInputStream fis = new FileInputStream("E:\\CoreJava\\day20 ----流IO\\上课录屏\\文件字节输入流.wmv");
FileOutputStream fos = new FileOutputStream("file\\文件字节输入流.wmv");
//一边读一边写
while(true) {
int i = fis.read(); //一次性读取一个字节
if(i==-1) break;
fos.write(i); //写一个字节 90m = 90*1024*1024B
}
fis.close();
fos.close();
FileInputStream fis = new FileInputStream("E:\\CoreJava\\day20 ----流IO\\上课录屏\\文件字节输入流.wmv");
FileOutputStream fos = new FileOutputStream("file\\文件字节输入流.wmv");
byte[] bs = new byte[1024];
while(true) {
//一次循环读取 1024个字节 = 1KB
int read = fis.read(bs);
if(read==-1) break;
//一次循环写入 1024个字节 = 1KB
fos.write(bs);
}
fis.close();
fos.close();
BufferedInputStream/BufferedOutputStream
//1. 创建一个文件字节输入输出流
FileInputStream fis = new FileInputStream("E:\\CoreJava\\day20 ----流IO\\上课录屏\\文件字节输入流.wmv");
FileOutputStream fos = new FileOutputStream("file\\文件字节输入流.wmv");
//2. 创建过滤输入输出流
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos);
//3. 边读边写
while(true) {
int i = bis.read();
if(i==-1) break;
bos.write(i);
}
//4. 关流
bis.close();
bos.close();
数据包装流 DataOutputStream/DataInputStream
可以操作八种基本数据类型
WriteByte(int n)/readByte()
、writeShort(int n)/readShort()
writeInt(int n)/readInt()
、writeLong(long n)/readLong()
writeFloat(float f)/readFloat()
、writeDouble/readDouble()
可以操作String数据:writeUTF(String str)/readUTF()
对象过滤流 ObjectInputStream/ObjectOutputStream
增强了基本的读写功能
可以操作八种基本数据类型、字符串类型
增强了读写对象的功能
readObject()
: 从流中读取一个对象
writeObject(Object obj):
向流中写入一个对象
Serializable
接口 2. 当读取超出数量的对象时,会运行报错,报错信息为:java.io.EOFException
文件到达结尾异常
3. 若自定义类型的属性也是自定义类型,那么属性类型也需实现Serializable
接口
4. 在传输集合对象时,若元素是自定义类型,则元素对应的类也必须实现Serializable
接口
5. transient
:修饰属性,代表此属性不参与序列化
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-obkiuTCR-1574690630593)(D:\feiq\Recv Files\day20 ----流IO\笔记\IO流总结.jpg)]
乱码:编码方式和解码方式不一致导致。
常用的编码集
ANSCII 美国
ISO8859 - 1 西欧
GBK 简体中文
BG2312 简体中文
BIG5 繁体中文
UTF-8 万国码
Reader(字符输入流) ——>读操作
int read()
: 读取的字符内容,若没有则返回-1
int read(char[] c)
: 一次读取多个字符,存放在char数组中
int read(char[] b,int off,int len)
:一次读取多个字符,存放在char数组中;
存储的起始下标是off,初始数量len
Writer(字符输出流) ——>写操作
write(int n)
: 写入一个字符write(String s)
: 写入一个字符串write(char[] c )
: 将数组中的字符 写入到文件中FileWriter
文件字符输出流FileReader
文件字符输入流BufferedReader
: 过滤字符输入流
String readLine()
: 一次性读取一个文本行;若文件到达结尾则返回null
PrintWriter
: 过滤字符输出流
println(String s)
: 换行写入一个字符串
当使用缓冲流写入一个对象时,写入的实际上是 对象的字符串表现形式(toString方法的返回值)。
InputStreamReader
/ OutputStreamWriter
// 1. 创建字节流对象
FileInputStream fis = new FileInputStream("file/e.txt");
// 2.创建桥转换流 将字节流——>字符流
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
步骤总结:
创建字节节点流
创建桥转换流,同时设置编解码方式包装过滤流,
方便读写操作读/写操作
关闭流:只需要关闭最外层流
进程:在os(操作系统)中并发的一个任务。
并发:由cpu分配时间片,决定当前执行哪个任务。微观串行(交替执行),宏观并行。
线程:进程中并发的一个任务。
Thread(java.lang)
:表示线程类
1. 定义一个任务类 实现Runnable接口
2. 创建任务对象
3. 创建Thread对象,提交线程任务
class MyTask implements Runnable{
//重写run方法
public void run(){
}
}
------------------------------------
MyTask mt = new MyTask();
Thread t1 = new Thread(mt);
1. 继承Thread类,重写run方法
2. 创建线程子类对象
class MyThread extends Thread{
public void run(){
}
}
------------------------------------
Thread t2 = new MyThread();
start():
启动线程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iD92Jn82-1574690630594)(D:/feiq/Recv Files/day22 ----线程01(1)]/笔记/1574155841632.png)
sleep(long mills)
: 让当前线程陷入有限期的休眠状态。
t.join()
: 让当前线程陷入等待,等待 t 线程执行完毕。
注意: JDK 5.0 开始 就绪状态和运行状态 统称为Runnable状态
线程不安全【面试重点】
当多个线程并发访问同一个对象(临界资源)时,破坏了不可被分割的操作(原子操作),会导致数据不一致。
同步代码块
synchronized(Obj){
//obj表示Object对象
//不可分割的代码(原子操作)
}
同步方法
public synchronized 返回值类型 方法名(){
//不可分割的代码(原子操作)
}
类的对象
:根据一个类实例化的对象(new出来的对象
类对象
:类加载的产物,保存在这个类的所有信息(类名、包名、父类、属性、方法、接口、构造方 法…)
对象名.getClass()
;Student s = new Student();
Class c1 = s.getClass();
类名.class
Class c2 = Student.class;
Class.forName("类的全限定名");
Class c3 = Class.forName("demo.Student"); //全限定名:包名+类名
Filed : 属性
Method : 方法
Constructor : 构造方法
getFields()
: 获取公开属性(父类+子类)c.getDeclaredFields()
: 获取所有属性(只包含本类)getMethods()
: 获取公开方法(父类+子类)c.getDeclaredMethods()
: 获取所有方法(只包含本类)c.getConstructors()
: 获取所有的构造方法Class c = Class.forName("类的全限定名");
Object o = c.newInstance(); //根据类对象获取实例对象
//饿汉式
class B{
private static final B b = new B();
private B() {
}
public static B getInstance() {
return b;
}
}
//懒汉式
class C{
private static C c = null;
private C() {
}
public static synchronized C getInstance() {
if(c==null) {
c = new C();
}
return c;
}
}
饿汉式:浪费空间。 懒汉式:效率较低
class D{
private static class Inner{
static D d = new D();
}
public static D getInstance() {
return Inner.d;
}
private D() {
}
}
public class TestFactory {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
String name = sc.next();
Animal a = getAnimal(name);
a.m1();
}
//工厂 : 参数表示类的全限定名
public static Animal getAnimal(String className) throws Exception {
Class c = Class.forName(className); //类对象
Object o = c.newInstance(); //根据类对象获取实例对象
Animal a = (Animal)o; //类型转换
return a;
}
}
public class TestFactory {
public static void main(String[] args) throws Exception {
Animal a = getAnimal();
a.m1();
}
public static Animal getAnimal() throws Exception {
// className 使用流进行读取
// 1. 创建字节流
FileInputStream fis = new FileInputStream("config.xml");
// 2. 创建Properties集合 调load方法
Properties p = new Properties();
// 将配置文件中的数据加载集合中 以=为分割 =前是key =后是value
p.load(fis);
String className = p.getProperty("className"); //根据key获取value
Class c = Class.forName(className); //类对象
Object o = c.newInstance(); //根据类对象获取实例对象
Animal a = (Animal)o; //类型转换
return a;
}
}
同步方法*
public synchronized 返回值类型 方法名(){
//不可分割的代码(原子操作)
}
类的对象
:根据一个类实例化的对象(new出来的对象
类对象
:类加载的产物,保存在这个类的所有信息(类名、包名、父类、属性、方法、接口、构造方 法…)
对象名.getClass()
;Student s = new Student();
Class c1 = s.getClass();
类名.class
Class c2 = Student.class;
Class.forName("类的全限定名");
Class c3 = Class.forName("demo.Student"); //全限定名:包名+类名
Filed : 属性
Method : 方法
Constructor : 构造方法
getFields()
: 获取公开属性(父类+子类)c.getDeclaredFields()
: 获取所有属性(只包含本类)getMethods()
: 获取公开方法(父类+子类)c.getDeclaredMethods()
: 获取所有方法(只包含本类)c.getConstructors()
: 获取所有的构造方法Class c = Class.forName("类的全限定名");
Object o = c.newInstance(); //根据类对象获取实例对象
//饿汉式
class B{
private static final B b = new B();
private B() {
}
public static B getInstance() {
return b;
}
}
//懒汉式
class C{
private static C c = null;
private C() {
}
public static synchronized C getInstance() {
if(c==null) {
c = new C();
}
return c;
}
}
饿汉式:浪费空间。 懒汉式:效率较低
class D{
private static class Inner{
static D d = new D();
}
public static D getInstance() {
return Inner.d;
}
private D() {
}
}
public class TestFactory {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
String name = sc.next();
Animal a = getAnimal(name);
a.m1();
}
//工厂 : 参数表示类的全限定名
public static Animal getAnimal(String className) throws Exception {
Class c = Class.forName(className); //类对象
Object o = c.newInstance(); //根据类对象获取实例对象
Animal a = (Animal)o; //类型转换
return a;
}
}
public class TestFactory {
public static void main(String[] args) throws Exception {
Animal a = getAnimal();
a.m1();
}
public static Animal getAnimal() throws Exception {
// className 使用流进行读取
// 1. 创建字节流
FileInputStream fis = new FileInputStream("config.xml");
// 2. 创建Properties集合 调load方法
Properties p = new Properties();
// 将配置文件中的数据加载集合中 以=为分割 =前是key =后是value
p.load(fis);
String className = p.getProperty("className"); //根据key获取value
Class c = Class.forName(className); //类对象
Object o = c.newInstance(); //根据类对象获取实例对象
Animal a = (Animal)o; //类型转换
return a;
}
}