Java是一门跨平台的面向对象编程语言,Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计语言和Java平台的总称。Java之父是詹姆斯·高斯林(James Gosling),他和同事们共同研发,并在1995年正式推出。
Java的特性有: 简单性、安全性、解释性、健壮性、面向对象、高性能、多线程、分布式、开源和跨平台。
跨平台: java跨平台的关键是JVM,JVM本身并不能跨平台,每个操作系统都要下载对应的JVM。JVM的职责只是加载、执行.class文件。将人能看懂的java文件编译成class文件 ,将class文件加载到内存,生成一个Class对象。以上是一个静态过程,文件的内容没有变化。
JDK(Java开发工具包): JDK是提供给Java开发人员使用的,其中包含了java的开发工具,也包括了JRE。所以安装了JDK,就不用在单独安装JRE了
JRE(Java运行时环境): 包括Java虚拟机和Java程序所需的核心类库等,如果想要运行一个开发好的Java程序,必须安装JRE环境
JVM(Java虚拟机): JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的
因为有JDK的工具包,使得JRE可以被构建出来,一旦JRE成功构建并运行,就产生了JVM。
JDK是所有JAVA环境的基础,首先安装。登录Oracle官网进行下载。
安装JDK后需要配置系统的环境变量。
寻找一个可执行文件,会先从环境中(当前的文件夹,当前的工程)找,如果找不到,就去环境变量里的目录里边找,直到找到为止,找不到就报错。
在外边定义一个 JAVA_HOME
C:\Program Files\Java\jdk1.8.0_221
path 增加一个路径 为了找到对应的exe
%JAVA_HOME%\bin
public class Hello World{}
public static void main(String[] args){}
System.out.rintln("Hello World");
class HelloWorld{
public static void main(String[] args){
System.out.println("HelloWorld");
}
}
计算机要存储数据,就必须将数据进行合理分类,不同类型的数据对应使用不同的方式进行处理
java中的数据类型有:
1、变量名字里不能有空格。
2、避免使用关键字,class public int static
3、避免使用汉字
4、整体是驼峰命名,首字母小写
5、$和_可以到处使用
6、数字不能开头
=就是赋值运算符,目的是将=右边的数据,赋值给=左边的空间。
//即:=右边永远都是数据,或可以得到数据的表达式;=左边永远都是一块可以存放对应数据类型的空间
+、-、*、/、%、++、--、+=、-=、*=、/=、%=
a++和++a的区别❗️❗️❗️
num++: 先赋值 再运算
int num = 10;
int i = num++;
i=10,num=11;
++num:先运算 再赋值
int num = 10;
int i = ++num;
i=11,num=11;
>、<、>=、<=、==、!=、equals
//比较运算符是用来对运算符左右两个变量的值进行比较,得到结果是boolean类型,因为无论是何种比较,结果只有真或假两种。
==和equals的区别: ❗️❗️❗️
与 &
条件1 condition1 | 条件2 condition2 | 结果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
或 |
条件1 condition1 | 条件2 condition2 | 结果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
非 !
条件1 condition1 | 结果 |
---|---|
1 | 0 |
0 | 1 |
短路和长路的区别:
&& 短路运算符 如果是false 直接 结果就是false 不会继续运算
|| 短路运算符 如果是true直接 结果就是true 不会继续运算
条件?结果1:结果2;
条件的结果一定是boolean ,true ,false;
xboolean condition1 = 5 > 3;
boolean condition2 = 5 > 3;
boolean condition3 = 5 > 3;
int num = (condition1 && (condition2 || condition3)) ? 1 : 2;
()>!>算数运算符>比较运算符>&&>|| >赋值运算符
当运算优先级不够时,可以在表达式外边增加小括号()来提升表达式的优先级。
非代码块设置主题和字体
file --》 settings ---》appearance---》theme 更换主题
Use custom font 勾上 选择字体 和 文字大小
file --》 settings --》 plugins --》 installed ---》theme 插件
ctrl art shift +s
修改代码块的字体
file --》 setting --》editor --》font
project ---> project Sdk --> new 找到自己安装的jdk
一定要保存 点击ok
main方法
新版的输入 main
老版的输入 psvm
输出语句 sout
复制一行 ctrl+D
剪切 ctrl+X
自动改错 alt + enter
ctrl+shift+下 和下一行交换位置
ctrl+alt+L 格式化代码
shift+F6 统一改名字
ctrl+单机 直接进入方法
ctrl+shift+U 将所有字符串都大写
alt+insert 生成getter和setter方法
if(){
代码块.....
}
//当if()小括号中的表达式结果如果为true,则执行if(){}大括号内的代码,否则不执行。
//-------------------------------------
if(){
代码块1.....
}else{
代码块2.....
}
//首先判断if()小括号中的表达式结果,如果是true,则执行if(){}大括号内的代码;如果是false,则执行else{}大括号内的代码。必然会也只会执行一个大括号内的代码。
//-------------------------------------
if(){
代码块1.....
}else if(){
代码块2.....
}else{
代码块3.....
}
//功能与三目运算相同。但不能如同三目运算一样直接将结果进行赋值操作,if没有结果反馈,三目运算始终有结果反馈。
//首先判断if()小括号中的表达式结果,如果是true,则执行if(){}大括号内的代码;如果是false,则执行else{}大括号内的代码。必然会也只会执行一个大括号内的代码。
switch(表达式) {
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
default:
语句体n+1;
break;
}
使用switch的注意事项:
1.case后面只能是常量,不能是变量,而且,多个case后面的值不能相同。
2.default可以省略。但一般不建议,除非结果是可以预计且不会发生变化的。
3.break可以省略,一般不建议。
4.default的位置可以出现在switch语句任意位置。
5.switch语句的结束条件必定是遇到break或已经执行到最末尾。
for(声明循环变量;循环条件;迭代){
被循环的代码块
}
for循环可以在循环条件满足的情况下,反复执行{}大括号内的代码块。
执行顺序:声明循环变量——>判断循环条件——>执行循环代码——>迭代——>判断循环条件…
声明循环变量
while(循环判断){
被循环的代码块
迭代
}
for循环语句和while循环语句可以等价转换,循环需要的内容只是换了位置而已。
for循环和while循环的不同:
在for循环中声明的循环变量无法在循环外部使用,而while循环却是在循环结构外部声明的循环变量,所以即便循环结束,也可以继续使用。但更推荐使用for循环,for循环的循环变量在循环结束后会直接被销毁,更合理的使用内存空间。
声明循环变量
do{
被循环的代码块
迭代
}while(循环判断);
for循环与while循环都是先进行循环条件判断,在执行循环内的代码。
而do-while循环更加特殊,它会先执行循环内的代码,再进行循环条件的判断。如果循环条件最一开始就不满足,for循环和while循环一次都不会执行,而do-while循环由于先执行循环体的原因,即便不满足也会执行一次。
增强for循环在遍历数组和集合时会更加方便简洁,但是会有一定的局限性。
//增强for循环(for each)
for(元素类型 元素名称 :遍历数组(集合)(或者能进行迭代的)){
语句
}
无论如何都要结束当前的全部循环,彻底跳出循环,程序会继续向下执行。
跳过本次循环继续下一次循环。
final关键字的规范: 字符串的所有字母都必须大写,单词和单词之间用下划线连接
静态常量: static fifinal 修饰 用来存放某些永远不变的量。
final关键字可以用来修饰引用、方法和类。
(1)用来修饰一个引用
(2)用来修饰一个方法
当使用final修饰方法时,这个方法将成为最终方法,无法被子类重写。但是,该方法仍然可以被继承。
(3)用来修饰类
当用final修饰类时,该类称为最终类,无法被继承。简称“断子绝孙类”。
for循环可已打标签,使用break + 标签名可以 退出 被打标签的循环
flag:for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
if( j > 0 ){
break flag;
}
System.out.println("===="+j);
}
}
switch中当case内的方法体语句一样时,可以简化。
case 1:
case 2:
case 3:
buyGoods(function);
当判断逻辑中内容里只有一句时,可以省略大括号。
if (i > 0)
System.out.println("这是简化的");
数组是存储同一种数据类型多个元素的集合。也可以看成是一个容器
int[] nums = {1,2,3};
int[] nums = new int[3];
类型[] 名字 = new 类型[长度];
1、数组一旦建立不能改变长度。
2、每个位置只能存一个值,多了会覆盖。
3、编号从0开始。
4、他有个长度的属性,最后一个位置的编号是 长度-1。
5、数组里边可以是基本类型,也可以是引用类型。
int[] salary = {4,5,0,6,7,8};
int maxIndex = 0 ;
for (int i = 1; i < salary.length; i++) {
if(salary[i] > salary[maxIndex]){
maxIndex = i;
}
}
System.out.println("经过了n轮比赛得到的最大值得下标是:"+maxIndex+"。值是:"+salary[maxIndex]);
for (int i = 0; i < salary.length; i++) {
System.out.print(salary[i] + " ");
}
int targetIndex = -1;
for (int i = 0; i < salary.length; i++) {
if(salary[i] == 9){
targetIndex = i;
}
}
int[] salary = {4,5,0,6,7,8};
int temp = salary[0];
salary[0] = salary[1];
salary[1] = temp;
每一轮都是在找一个最小值放在未拍好序的元素的第一个
int[] nums = {4,6,0,8,7};
for (int j = 0 ; j < nums.length -1 ; j++){
int minIndex = j;
for (int i = j+1; i < nums.length; i++) {
minIndex = nums[i] < nums[minIndex] ? i : minIndex;
}
int temp = nums[minIndex];
nums[minIndex] = nums[j];
nums[j] = temp;
}
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + " ");
}
每一轮都是两两相比,会将最大的冒到最后边
int[] nums = {3, 7, 4, 9, 5, 4, 1};
for (int j = 0; j < nums.length - 1 ; j++) {
for (int i = 0; i < nums.length - 1 -j ; i++) {
if (nums[i] > nums[i + 1]) {
int temp = nums[i];
nums[i] = nums[i + 1];
nums[i + 1] = temp;
}
}
}
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + " ");
}
Java方法是语句的集合,它们在一起执行一个功能。方法是解决一类问题的步骤的有序组合,方法包含于类或对象中,在程序中被创建,在其他地方被引用。
//权限修饰符 返回值类型(没有返回值写void) 方法名(参数类型 参数名){
// ...
// 方法体
// ...
// return 返回值;(没有返回值可以不写return)
//}
public static void main( String[] args ){
System.out.println("Hello World!")
}
但凡是被static修饰的方法或者变量,都会在类加载的时候,就被初始化。都会赋给那个加载到内存的类对象,类对象的名字就是class 后边跟的那个字符串。
所以调用的时候 类的名字.方法名()实现调用,但如果在同一个类里就可以直接使用
方法名() 调用;
//无参数
test();
//有参数
int number = 3;
test(number);
//有参有返回值
int number = 3;
int result = test(number);
方法名一样,参数数量不一样或者参数类型不一样。和返回值无关。
因为职责不一样,同样的名字往往表示同样的功能。
**形参:**方法定义的时候的参数
**实参:**方法调用时传入的参数
功能组成系统,步骤组成功能
当前写方法的步骤:
**值传递:**不改变原来的变量的值
**引用传递:**因为引用传递操作的是地址,会改变内存中的值
public class Test {
public static void main(String[] args) {
//依然没有被改变
//值传递
int number1 = 3;
int number2 = 5;
swap(number1,number2);
System.out.println("number1 =" + number1);
System.out.println("number2 =" + number2);
System.out.println("-------------------------------------");
//数组被改变了
//引用传递
int[] numbers = {1,2};
swap(numbers);
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]+" ");
}
System.out.println("----------------------------------");
}
public static void swap(int num1,int num2){
int temp = num1;
num1 = num2;
num2 = temp;
}
public static void swap(int[] nums){
int temp = nums[0];
nums[0] = nums[1];
nums[1] = temp;
}
}
**格式:**数据类型…变量名称
**优点:**可以实现不限个数的传入参数,不是无限多,最大个数应该是32个
注意:
public class Test {
public static void main(String[] args) {
int max = findMax("str",1,2,3,4,5,8,7,5);
System.out.println(max);
int max2 = findMax("str",1,2,6,7);
System.out.println(max2);
int max3 = findMax("str",1,5);
System.out.println(max3);
}
public static int findMax(String str,int... nums){
int maxIndex = 0;
for (int i = 1; i < nums.length; i++) {
if (nums[i] > nums[maxIndex]) {
maxIndex = i;
}
}
System.out.println(str);
return nums[maxIndex];
}
}
方法自己调自己,直接或间接调用方法本身。
注意:
**斐波纳契数列(Fibonacci Sequence):**又称黄金分割数列,指的是这样一个数列:1、1、2、3、5、8、13、21…第一个 为 1 第二个 为1 从第三个开始 都等于前两个之和,第三个 就是 1 + 1 第四个 就是 第二个 + 第三个依次类推。
public class Test {
public static void main(String[] args) {
System.out.println("你要看数列的第几个的值:");
Scanner in = new Scanner(System.in);
int index = in.nextInt();
System.out.println("第" + index + "个菲波那切数列的值为:" + fibonacci(index));
}
public static int fibonacci(int index){
if(index == 1 || index == 2){
return 1;
}else{
return fibonacci(index - 2) + fibonacci(index - 1);
}
}
斐波纳契数列原理图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pRu3ONuq-1588762657929)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1584377032158.png)]
java是一个基于栈的指令集,指令在栈上执行,栈帧
**栈:**先放进去的最后被拿出来,最后放进去的先拿出来,像羽毛球筒一样
包是用来装类的,就等于文件夹
**包名:**公司域名倒着写,com.baidu,全部小写,用点隔开
包名的作用:
简单类名:SuperLinked
全类名:com.xinzhi.util.SuperLinked
//该包下的内容全部引入
import com.xinzhi.util.*;
//只引入一个类
import com.xinzhi.util.SuperLinked;
作用域 | 当前类 | 同package | 子孙类 | 其他package |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
friendly(default) | √ | √ | × | × |
private | √ | × | × | × |
注意:
修饰符的作用:
类:类是一个模板,它描述一类对象的行为和状态。例如,动物是一个类,
对象:对象是类的一个实例,有状态和行为。例如,一只狗狗是一个对象,它的状态有:颜色、名字、品种;行为有:叫、吃等;这只狗的是动物的实例。
类是对象的类型,对象是类的实例
每个类都有构造方法。如果没有定义构造方法,Java编译器将会为该类提供一个默认构造方法。
构造方法的名字和类名必须完全一样,目前不能有返回值,一旦你定义了自己的构造方法,系统不会送你空的构造方法
在java中描述类用class,对象是由属性和方法组成,属性是有什么特点,方法是能干什么。new对象其实是调用构造方法,但写的类里并没有构造方法 ,事实上,如果你的类没有构造方法系统会送一个空的构造方法。
setting 和 getting 所有属性都加private,所有属性都用getter和setter
每个方法定义的时候都会默认传入两个变量this和super
this: 代表new出来的那个对象的引用
super: 表示当前类的父类的对象
string是一个引用类型,本来也需要new,但是java给简化了
String name = new String("name");
String name = "name";
既然是个对象就有属性和方法:
他的方法无非就是帮助我们方便的处理这个字符串。
注:使用string一定要注意,必须用一个新的String接受。
常用的String方法:
.contains是否包含,
.substring(1,3)字符串截取,从第2到第3,包前不包后
.split分割字符串
.indexOf查找字符串的位置
.replace 替换字符串中的字符
.toUpperCase将字符串的小写转换成大写
..........
因为基础类型没有方法,不好操作,所有java对每一种基础类型都进行了包装,生成包装类。
基本类型基于数值,对象类型基于引用。
对象类型的变量需要占用更多的内存空间。
int的包装类 Integer
Integer i = 3;
Integer是个对象,本来是要new,但是太常用了,所以简化了定义的方式,和基础类型一样。
**自动装箱:**看见变量是个Integer,而后边没new是自动帮你new了一个。
**自动拆装箱:**看见是个包装类,但这里学要打印的是基础类型,自动转换。
自学其它8种
可以看到,除了 int 和 char 两者的包装类名变化有些大以外,其余六种基本类型对应的包装类名,都是大写了首字母而已。
基本类型 | 包装类 |
---|---|
boolean | Boolean |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aksJ6yEl-1588762657934)(E:\Development4\总结\2、Java面向对象\20200207-类加载、超级数组、封装、栈\类加载运行.png)]
代码案例
package com.xinzhi;
/**
* 画图解释类加载运行
* @auther 王瑞杰
* @date 2020/2/9
*/
public class Test {
public static void main(String[] args) {
Test test1 = new Test();
System.out.println("------第一次------");
System.out.println(test1.num2);
System.out.println(Test.num1);
Test test2 = new Test();
System.out.println("------第二次------");
System.out.println(test1.num2);
System.out.println(Test.num1);
}
public static int num1 = 0;
public int num2 = 0;
public Test(){
this.num2++;
Test.num1++;
}
}
**封装(Encapsulation):**是指一种将抽象性函数接口的实现细节部分包装、隐藏起来的方法。
封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
通过修改属性的权限性来限制对属性的访问(一般限制为private)
//将userName和password属性设置为私有的,只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏。
public class User {
private String userName;
private int password;
}
创建一对赋取值方法,用于对私有属性的访问
public class User {
private String userName;
private String password;
public int getUserName(){
return userName;
}
public String getPassword(){
return password;
}
public void setUserName(String userName){
this.userName = userName;
}
public void setPassword(String password){
this.password = password;
}
}
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
思想:一个对象调用方法的时候,首先去自己的类里边找,找不到的话就去父类找,父类也找不到,就去父类的父类找,直到Object,找到为止。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZxsTyYrH-1588762657937)(E:\Development4\总结\2、Java面向对象\20200210-队列封装、多太、抽象方法、接口\继承.png)]
多态是同一个行为具有多个不同表现形式或形态的能力。
子类继承父类
子类重写父类的方法
使用父类引用指向子类对象时,子类特有的方法就不能再被调用
都是父类引用,指向了不同的子类对象,调用相同的方法,就会有不同的结果,这就叫多态
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心内容重新写!
**重写的好处:**子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
注意:
重载是在一个类里面,方法名字相同,而参数不同(参数个数或类型不一样)。返回类型可以相同也可以不同。
(1)目的不同
重载用于增加程序的可读性(做法不同,但是做的同一事情)。 重写用于提供其超级类已经提供的方法的特定实现。
(2)范围不同
重载在相同的类范围内内执行。 重写发生在两类具有继承(继承)的关系。
(3)参数不同
重载参数必须不同。 重写参数必须相同。
如图所示:
重写在原来的箭上绑上新的箭,重载是多加了几支箭。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rF0S2ze1-1588762657938)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1584387925697.png)]
有些类天然的就是为了让子类继承,而不是为了在父类中调用,这类方法存在的目的就是规定了子类,必须要有这些方法,比如动物就规定,你实现了我这个类,就必须有eat方法,而且逆袭必须重写。
对于这种情况,java提出来抽象类,这种类里边可以有一些方法没有方法体,我们称之为抽象方法,抽象方法必须使用abstract修饰,同时,如果有了abstract抽象方法之后,这个类必须被定义成抽象方法,也是用abstract修饰
抽象方法是对子类的约束,不管是猫还是狗还是其它动物,他必须都能吃东西
注意:
当一个类里全是抽象方法时,我们称这类方法叫做接口,省略abstract,class改为interface,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
注意:
自己封装一个超级数组,对数组添加增删查改的功能。
package com.xinzhi;
/**
* 封装超级数组
* @auther
* @date 2020/2/9
*/
public class SuperArray {
//维护一个数组
private int[] array;
//当前最后一个数字的下标,要为-1,因为数组的下标从0开始
private int currentIndex = -1;
//构造是初始化
SuperArray(){
array = new int[8];
}
//添加数据的方法
public SuperArray add(int data){
currentIndex++;
if (currentIndex > array.length - 1){
array = dilatation(array);
}
array[currentIndex] = data;
//返回当前的对象,把自己返回回去,可以一只调用,方便链式调用,
return this;
}
/**
* 删除
* 1、把末位的删除了,没有参数
* 2、给一个下标删除
* 3、给值删除
*/
//Integer是一个包装类,可以返回null
public Integer delete(){
currentIndex--;
if (currentIndex < -1){
return null;
}else {
return array[currentIndex + 1];
}
}
//修改
public void update(int index,int data){
boolean flag = validateIndex(index);
if (flag){
array[index] = data;
}else {
System.out.println("您要修改的数据不存在!!!");
}
}
//查找数组里有几个改数据
public int findNumber(int data){
int count = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] == data){
count ++;
}
}
return count;
}
//查找这个数据第一次出现的下标
public int findNumberIndex(int data){
for (int i = 0; i < array.length; i++) {
if (array[i] == data){
return i;
}
}
return -1;
}
//根据下表查询数字
public int get(int index){
return array[index];
}
//查看当前有多少个数字
public int size(){
return currentIndex + 1;
}
//打印数组
public void print(){
System.out.println("当前的数组是: ");
for (int i = 0; i <= currentIndex; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
//排序
public void sort(){
for (int i = 0; i < currentIndex; i++) {
for (int j = 0; j < currentIndex; j++) {
if (array[j] > array[j + 1]){
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}
//验证下标是否合法
private boolean validateIndex(int index) {
//只要有一个不满足就返回false
return index <= currentIndex && index >= 0;
}
//自动 数组扩容
private int[] dilatation(int[] oldArray){
int[] newArray = new int[oldArray.length * 2];
for (int i = 0; i < oldArray.length; i++) {
newArray[i] = oldArray[i];
}
return newArray;
}
}
package com.xinzhi;
/**
* 封装超级数组的执行类
* @auther
* @date 2020/2/9
*/
public class SuperArrayTest {
public static void main(String[] args) {
SuperArray superArray = new SuperArray();
//添加
superArray.add(3);
superArray.print();
//自动扩容
//因为方法内自己把自己返回了出去,所以能一直调add方法
superArray.add(4).add(2).add(3).add(4).add(2).add(3).add(4).add(2).add(3).add(4).add(2).add(3);
superArray.print();
//删除末位
int delete = superArray.delete();
System.out.println("你把末位的【" + delete + "】给删掉了!!");
superArray.print();
//修改
superArray.update(5,9);
superArray.print();
superArray.update(22,9);
superArray.print();
//查找数据有几个
int number = superArray.findNumber(3);
System.out.println("查找的3有" + number + "个");
superArray.print();
//查找这个数据第一次出现的下标
int numberIndex = superArray.findNumberIndex(4);
System.out.println("4第一次出现的下标是" + numberIndex);
superArray.print();
//查询有多少个数字
int size = superArray.size();
System.out.println("有【" + size + "】个数字");
//进行排序
superArray.sort();
superArray.print();
}
}
栈是一种先进后出的数据结构,数组和链表都可以生成栈。
**进栈:**当数据进入到栈时会按照规则压入到栈的底部,再次进入的数据会压在第一次的数据上面,以此类推。
**出栈:**在取出栈中的数据的时候会先取出最上面的数据,所以是先进后出。
package com.xinzhi;
/**
* 先进后出
* 封装一个栈
* @auther
* @date 2020/2/9
*/
public class MyStack {
SuperArray superArray;
public MyStack(){
superArray = new SuperArray();
}
//压栈 压入栈顶
public void push(int data){
superArray.add(data);
}
//弹栈
public Integer pop(){
Integer number = superArray.delete();
if (number == null){
System.out.println("栈已经空了!!");
}
return number;
}
}
package com.xinzhi;
import org.omg.CORBA.MARSHAL;
/**
* 封装一个栈的执行类
* @auther 王瑞杰
* @date 2020/2/9
*/
public class MyStackTest {
public static void main(String[] args) {
MyStack myStack = new MyStack();
myStack.push(3);
myStack.push(4);
Integer pop1 = myStack.pop();
System.out.println(pop1);
Integer pop2 = myStack.pop();
System.out.println(pop2);
Integer pop3 = myStack.pop();
System.out.println(pop3);
}
}
队列是一种先进先出的数据结构,数组和链表也都可以生成队列。
**进队列:**当数据进入到队列中时是先进入的在下面后进入的再上面。
**出队列:**出队列的时候是先从下面出,然后才是上面的数据出,最晚进入的队列的,最后出。
package com.xinzhi;
/**
* 封装队列
* 先进先出
* @auther
* @date 2020/2/10
*/
public class MyQueue {
private SuperArray superArray;
public MyQueue(){
superArray = new SuperArray();
}
//入队
public void put(int data){
superArray.add(data);
}
//出队
public Integer take(){
return superArray.delete(0);
}
}
package com.xinzhi;
import java.util.Scanner;
/**
* 封装队列的执行类
* @auther 王瑞杰
* @date 2020/2/10
*/
public class MyQueueTest {
public static void main(String[] args) {
MyQueue myQueue = new MyQueue();
myQueue.put(1);
myQueue.put(5);
System.out.println(myQueue.take());
System.out.println(myQueue.take());
System.out.println("---------------银行取票机--------------------");
for (int i = 0; i < 100; i++) {
myQueue.put(i + 1);
}
while (true){
System.out.println("请出示您的身份证:");
Scanner scanner = new Scanner(System.in);
String name = scanner.next();
System.out.println(name + "拿到的号码是:" + myQueue.take());
}
}
}
**强制转型:**从父类的类型强制转为子类,如果传入的真的是该类型,则强转没有问题;如果不是就会报错
合适的方法是使用instanceof首先进行判断,确定类型之后再处理
//使用instanceof 判断传进来的对象是不是一个Dog类型
//强转成一个子类
if (animal instanceof Dog){
Dog dog = (Dog)animal;
dog.enjoy();
}
当某个类不知道自己内部处理的数据的真实类型时,可以使用泛型,
方法是在类后加,不一定是T,其它字母也行,一般写成T或E。
只有当你去new对象时指定了确定的类型时,代码里的T就会变成实际的类型,具体从代码里思考。
链表像一跟绳子一样,把节点全链起来,手拉手
查询慢,删除快(查询是从第一个开始,依次往后找)(删除是把要删的上一个和下一个连接起来)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OfJIIaaf-1588762657942)(E:\Development4\总结\2、Java面向对象\20200211-超级数据泛型、链表\链表.png)]
两种数据结构均可实现数据的顺序存储,构造出来的模型是线性结构。
**集合的概念:**集合是一个动态的数组,长度可以改变。集合存放的都是对象的引用,而非对象本身,出于表达上的便利,我们称集合中的对象就是指集合中对象的引用(reference)
**集合的类型:**set(集)、list(列表)、map(映射)
**集合的接口有:**Collection和Map、List、Set
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-te7Jdtjr-1588762657944)(E:\Development4\总结\2、Java面向对象\20200212-集合\Java集合框架主要结构图.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Le7VQi0j-1588762657945)(E:\Development4\总结\2、Java面向对象\20200212-集合\集合类特点.png)]
ArrayList和LinkedList分别实现了List,只不过它们的底层一个是数组一个是链表。
**HashMap组成:**hash散列、数组、链表、红黑树
注意:
任何东西一调用HashCode就能生成一个数字
数组长度16,链表上至少能挂8个,挂到8个时进行树化(红黑树)
Hash数据结构已经定死,一定不能根据key排序
TreeMap直接是一个巨大的红黑树
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AQB5FOb2-1588762657949)(E:\Development4\总结\2、Java面向对象\20200212-集合\HashMap.png)]
**特点:**不能重复,如果重复直接覆盖
其他集合可以利用set不能重复对象的特性,达到去重的目的
**HashSet:**元素无序,且唯一,允许存储null元素
**TreeSet:**具有Set的属性和方法,基于TreeMap实现,底层的数据结构是红黑树
Iterator是一个接口,它是集合的迭代器。集合可以通过Iterator去遍历集合中的元素。
object方法:所有类的顶级父类,所有的类都有这个方法
**object里常用的方法:**equals()、hashCode()、toString()、getClass()
方法名 | 作用 | 返回值 |
---|---|---|
hashCode() | 获取对象hash值 | int |
toString() | 将对象信息变为字符串返回 | String |
equals(Pbject obj) | 判断两个内存地址是否一样 | boolean |
getClass() | 获取类名 | Object |
注意:
equals在object里的实现就是==就是在比内存地址
当要比较对象时,要重写equals方法,最好也重写hashCode
hashCode不要自己实现,让人家写,Object.hash()
toString 把所有的对象转换成字符串,如果不转化:类的全类型名@十六进制的数
java.util 包提供了 Date 类来封装当前的日期和时间。 Date 类提供两个构造函数来实例化 Date 对象。
第一个构造函数使用当前日期和时间来初始化对象。
Date()
第二个构造函数接收一个参数,该参数是从1970年1月1日起的毫秒数。时间戳:英国伦敦1970-1-1 0:0:0到现在的毫秒数,在任何地方都可用
Date (long date)
**使用 SimpleDateFormat 格式化日期:**SimpleDateFormat 是一个以语言环境敏感的方式来格式化和分析日期的类。SimpleDateFormat 允许你选择任何用户自定义日期时间格式来运行。例如: 日期格式化 “yyyy-MM-dd HH:mm:ss”(hh是12小时制,HH是24小时制)
Calendar类的功能要比Date类强大很多,而且在实现方式上也比Date类要复杂一些。
Calendar类是一个抽象类,在实际使用时实现特定的子类的对象,创建对象的过程对程序员来说是透明的,只需要使用getInstance方法创建即可。
创建一个代表系统当前日期的Calendar对象
Calendar c = Calendar.getInstance();//默认是当前日期
创建一个指定日期的Calendar对象
//创建一个代表1998年6月6日的Calendar对象
Calendar c1 = Calendar.getInstance();
c1.set(1998, 6, 6);
Calendar类的常用方法:
方法名 | 作用 | 返回值 |
---|---|---|
getInstance() | 获取日期 | Calendar |
get(int field) | 获取年/月/日/时/分/秒 | int |
add(int field,int amount) | 计算时间 | void |
set(int year,int month,int date) | 设置时间 | void |
Math类包含了用于执行基本数学运算的属性和方法,如绝对值、最大最小值、随机数
Math类的方法都被定义为 static 形式,全是静态方法,所以不能new。通过 Math 类可以在主函数中直接调用。
Match常用的方法:
方法名 | 作用 | 返回值 |
---|---|---|
abs(int a) | 取绝对值 | int |
ceil(double a) | 返回最小值 | double |
floor(double a) | 返回最大值 | double |
max(int a,int b) | 取最大值 | int |
pow(double a,double b) | 求幂 | double |
random() | 随机数 | double |
round(float a) | 四舍五入成整数 | int |
sqrt(double a) | 求double值的正平方根 | double |
Java提供了更为灵活的用于获得随机数的Random类,该类在java.util包中,使用Random类的如下构造方法,可以创建Random对象,习惯将Random对象称为随机数生成器。
构造方法:
Random()
创建一个新的随机数生成器。
Random(long seed)
使用单个指定long种子创建一个新的随机数生成器。
Arrays是Java.util.Arrays类能方便地操作数组,它提供的方法时静态的
数组Arrays工具类常用方法:
方法名 | 说明功能 |
---|---|
asList | 将数组转变成ArrayList,但是ArrayList长度不可变化 |
sort | 对数组进行排序。 |
binarySearch | 用于对已排序的数组进行二分查找 |
copyOf | 数组拷贝, |
copyOfRange | 指定范围的复制 |
equals | 比较两个数组中对应位置的每个元素是否相等。 |
toString | 打印一维数组的元素 |
Collections是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。
集合Collections工具类常用方法:
方法名 | 说明功能 |
---|---|
sort | 对指定列表按升序进行排序 |
shuffle | 洗牌方法,将当前集合内的数据进行随机排序 |
reverse | 逆序排序,对当前集合的元素按照相反的顺序进行排序 |
min和 max | 分别返回集合中的最小元素和最大元素 |
indexOfSubList | 返回源列表中第一次出现指定目标列表的起始位置 |
lastIndexOfSubList | 返回源列表中最后一次出现指定目标列表的起始位置 |
rotate | 循环移动指定列表中的元素 |
fill | 替换掉源列表中所有的元素为目标元素 |
copy | 拷贝所有元素,目标列表的长度要大于或等于源列表的长度 |
**垃圾回收(Garbage Collection,GC):**是释放垃圾占用的空间,防止内存泄露。有效的使用可以使用的内存,对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收。
分析:
1、所有新new的对象会放在伊甸园区,伊甸园区到一定的程度就会触发GC,GC进行标记然后进行垃圾回收,
2、先把不被回收的复制到survive1里,复制比移动快,
3、然后将伊甸园区清空,
4、然后继续往伊甸园区new对象
5、再对伊甸园区和survive1区进行GC,然后将伊甸园区和survive1中不被回收的,复制到survive2区中
6、会对survive2区中的对象标个年龄(刚从survive1中过来的标1,从survive2中过来的标2)
7、再将伊甸园区和survive2清空
…
8、当对象的年龄达到某个值时 ( 默认是 15 岁)这些对象就会成为老年代。
9、老年代一般不动了,有很少一部分也会进行清除,清除掉后将后面的往前挪
10、永久代一般不进行GC,一般存放class、类对象、元数据
File 类是 java.io 包中唯一代表磁盘文件本身的对象。
File 类定义了一些与平台无关的方法来操作文件,File类主要用来获取或处理与磁盘文件相关的信息,像文件名、 文件路径、访问权限和修改日期等,还可以浏览子目录层次结构。
File 类表示处理文件和文件系统的相关信息。也就是说,File 类不具有从文件读取信息和向文件写入信息的功能,它仅描述文件本身的属性。
不可以空参构造!!
File(String pathname)
//通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
方法 | 作用 | 返回值 |
---|---|---|
createNewFile() | 创建名称的空文件,不创建文件夹 | boolean |
isDirectory() | 判断是否是目录 | boolean |
isFile() | 判断是否是文件 | boolean |
exists() | 判断文件或目录是否存在 | boolean |
getAbsolutePath() | 返回此对象表示的文件的绝对路径名 | String |
getPath() | 返回此对象表示的文件的相对路径名 | String |
getName() | 返回此对象表示的文件或目录的名称 | String |
length() | 返回文件的长度,单位为字节 | long |
路径应该用左斜杠/ 或者 两个右斜杠\ \
/左斜杠在java中表示路径,右斜杠\在java中表示转译符,所有如果要用右斜杠需要给他转译成左斜杠
java的io是实现输入和输出的基础,可以方便的实现数据的输入和输出操作。在java中把不同的输入/输出源(键盘,文件,网络连接等)抽象表述为“流”(stream)。
按照不同的分类方式,可以把流分为不同的类型。常用的分类有三种:
可以分为输入流和输出流
可以划分为字节流和字符流
字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。
字节流和字符流的区别:
结论:
设备上的数据无论是图片或者视频,文字,它们都以二进制存储的。二进制的最终都是以一个8位为数据单元进行体现,所以计算机中的最小数据单元就是字节。意味着,字节流可以处理设备上的所有数据,所以字节流一样可以处理字符数据。
只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。
划分为节点流和处理流
总结:
**注:**下表中带下划线的是抽象类,不能创建对象。粗体部分是节点流,其他就是常用的处理流。
流分类 | 使用分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
---|---|---|---|---|---|
抽象基类 | InputStream | OutputStream | Reader | Writer | |
节点流 | 访问文件 | FileInputStream | FileOutStream | FileReader | FileWriter |
访问数值 | ByteArrayInputStream | ByteArrayOutStream | CharArrayReader | CharArrayWriter | |
访问管道 | PipedInputStream | PipedOutStream | PipedReader | PipedWriter | |
访问字符串 | StringReader | StringWriter | |||
处理流 | 缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
转换流 | InputStreamReader | OutputStreamWriter | |||
对象流 | ObjectInputStream | ObjectOutputStream | |||
抽象基类(过滤) | FilterInputStream | FilterOutputStream | FilterReader | FilterWriter | |
打印流 | PrintStream | PrintWriter | |||
推回输入流 | PushbackInputStream | PushbackReader | |||
特殊流 | DataInputStream | DataOutputStream |
异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止,其实异常本身也是一个类。
注意:异常不是语法错误,语法错误是无法通过编译也就不会产生字节码文件也就不能运行。
异常类的结构图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1GYd8Ogx-1588762657958)(E:\Development4\总结\2、Java面向对象\20200217-异常、数组集合工具类\异常类的结构图.png)]
所有的异常都是从Throwable继承而来的,是所有异常的共同祖先,Throwable有两个子类,Error和Exception
异常类型 | 说明 |
---|---|
Exception | 异常层次结构的父类 |
ArithmeticException | 算术错误情形,如以零作除数 |
ArrayIndexOutOfBoundsException | 数组下标越界 |
NullPointerException | 尝试访问 null 对象成员(空指针异常) |
ClassNotFoundException | 不能加载所需的类 |
IllegalArgumentException | 方法参数错误 |
ClassCastException | 对象强制类型转换出错 |
NumberFormatException | 数字格式转换异常,如把"abc"转换成数字 |
**抛出异常throw:**throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。
使用格式:
throw new 异常类名(参数)
**声明抛出异常throws:**运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常
使用格式:
修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2 ... { }
注意事项:
try {
... //监视代码执行过程,一旦发现异常则直接跳转至catch,
// 如果没有异常则直接跳转至finally
} catch (SomeException e) {
... //可选执行的代码块,如果没有任何异常发生则不会执行;
//如果发现异常则进行处理或向上抛出。
} finally {
... //必选执行的代码块,不管是否有异常发生,
// 即使发生内存溢出异常也会执行,通常用于处理善后清理工作。
}