顺序结构
- Java的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句的执行
- 顺序结构是最简单的算法结构
- 语句与语句之间,框与框之间按从上到下的顺序进行的,它是若干个依次处理步骤组成的,他是任何一个算法都离不开的一种基本结构
switch选择结构
- 多选择结构的实现方式还有就是switch case语句
- switch case语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支
正常:
package javabase.struct;
public class SwitchDemo01 {
public static void main(String[] args) {
//switch匹配一个具体的值,然后返回case
char sorce ='1';
switch (sorce){
case 'a':
System.out.println("A1");
break;
case 'b':
System.out.println("B2");
break;
case 'c':
System.out.println("C3");
break;
case 'd':
System.out.println("D4");
break;
default:
System.out.println("未知等级");
}
}
}
case穿透现象:
package javabase.struct;
public class SwitchDemo01 {
public static void main(String[] args) {
//case穿透
char sorce ='b';
switch (sorce){
case 'a':
System.out.println("A1");
break;
case 'b':
System.out.println("B2");
case 'c':
System.out.println("C3");
case 'd':
System.out.println("D4");
default:
System.out.println("未知等级");
}
}
}
字符串类型的比较(jdk7特性)
反编译:
字节码文件------>Java文件------>IDEA可以实现
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package javabase.struct;
public class SwitchDemo02 {
public SwitchDemo02() {
}
public static void main(String[] args) {
String s = "刘某人";
byte var3 = -1;
switch(s.hashCode()) {
case 21040386:
if (s.equals("刘某人")) {
var3 = 1;
}
break;
case 657950066:
if (s.equals("liuyueyang")) {
var3 = 0;
}
}
switch(var3) {
case 0:
System.out.println("false");
break;
case 1:
System.out.println("true");
}
}
}
if语句
if 语句的语法如下:
if(布尔表达式)
{
//如果布尔表达式为true将执行的语句
}
如果布尔表达式的值为 true,则执行 if 语句中的代码块,否则执行 if 语句块后面的代码。
if()else…语句
if(布尔表达式){
//如果布尔表达式的值为true
}else{
//如果布尔表达式的值为false
}
if…else if…esle语句
if…else if…else 语句
if 语句后面可以跟 else if…else 语句,这种语句可以检测到多种可能的情况。
使用 if,else if,else 语句的时候,需要注意下面几点:
- if 语句至多有 1 个 else 语句,else 语句在所有的 else if 语句之后。
- if 语句可以有若干个 else if 语句,它们必须在 else 语句之前。
- 一旦其中一个 else if 语句检测为 true,其他的 else if 以及 else 语句都将跳过执行。
if(布尔表达式 1){
//如果布尔表达式 1的值为true执行代码
}else if(布尔表达式 2){
//如果布尔表达式 2的值为true执行代码
}else if(布尔表达式 3){
//如果布尔表达式 3的值为true执行代码
}else {
//如果以上布尔表达式都不为true执行代码
}
嵌套的 if…else 语句
使用嵌套的 if…else 语句是合法的。也就是说你可以在另一个 if 或者 else if 语句中使用 if 或者 else if 语句。
嵌套的 if…else 语法格式如下:
if(布尔表达式 1){ 如果布尔表达式 1的值为true执行代码 if(布尔表达式 2){ 如果布尔表达式 2的值为true执行代码 } }
循环
while循环
while(布尔表达式){
//循环内容
}
-
只要布尔表达式为true ,循环会一直下执行下去 -
我们大多数情况会让循环停止下来,我们需要让这个表达式失效 -
少部分一直循环,比如服务器请求响应监听等 -
循环条件一直为true就会造成死循环,会让我们的业务编程中应该避免死崩溃。会影响程序性能或者造成程序卡死奔溃。 test:1+…+100? package javabase.struct;
public class WhileDemo01 {
public static void main(String[] args) {
int i=0;
int sum=0;
while(i<=100){
sum=sum+i;
i++;
}
System.out.println(sum);
}
}
死循环案例:
package javabase.struct;
public class WhileDemo02 {
//死循环
public static void main(String[] args) {
int i=0;
while (true){
i++;
System.out.println(i);
}
}
}
do while 循环
-
对于while而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也让程序至少执行一次 -
do … while循环和while循环相似,不同的是,do…while循环至少执行一次。 test: package javabase.struct;
public class DoWhileDemo02 {
public static void main(String[] args) {
int i=0;
while (i<0){
System.out.println(i);
}
System.out.println("=============================");
do {
i++;
System.out.println(i);
}while(i<0);
}
}
输出结果: ============================= 1 -
证明了程序是按照顺序执行的 do {
//循环内容
}while(循环条件);
test: package javabase.struct;
public class DoWhileDemo01 {
public static void main(String[] args) {
int i=0;
int sum=0;
do {
sum=sum+i;
i++;
}while (i<=100);
System.out.println(sum);
}
}
for循环
-
for循环使循环结构变得更加简单 -
for循环语句是支持迭代的一种通用结构,是最有效,最灵活的循环结构 -
for循环执行的次数是在执行前就确定的,语法格式如下 for(初始化;布尔表达式;更新){
//循环内容
}
注意:
-
最先执行初始化步骤,可以生命一种类型,但可初始化一个或者多个循环控制变量,也可以是空语句。 -
检查布尔表达式的值。如果为true,循环体被执行。如果为false,循环终止,开始循环体后面的语句。 -
执行一次循环后,更新循环控制变量(迭代因子控制循环变量的增减) -
再次检验布尔表达式,循环执行上面的过程。 -
IDEA快捷键-------100.for test1: package javabase.struct;
public class ForDemo01 {
public static void main(String[] args) {
//条件都存在
int sum=0;
for (int i = 0; i < 100; i++) {
sum=sum+i;
System.out.println(sum);
}
//无条件
for(;;){
System.out.println(sum++);//sum==99
//sum==100
if (sum==100){
break;
}
}
}
}
test2:计算1-100之间的奇数和偶数的和 package javabase.struct;
public class ForDemo02 {
public static void main(String[] args) {
int oddSum=0;
int evenSum=0;
for (int i = 0; i <=100; i++) {
//奇数运算
if (i%2==1){
oddSum=oddSum+i;
}else{
//偶数
evenSum=evenSum+i;
}
}
System.out.println(oddSum);
System.out.println(evenSum);
}
}
test3:用while 或者for循环输出1-1000之间能被5整除的数,并且每行输出3个 for循环
package javabase.struct;
public class ForDemo03 {
public static void main(String[] args) {
for (int i = 1; i <= 1000; i++) {
if (i%5==0){
System.out.print(i);
System.out.print("\t");
}
if(i%15==0){
System.out.print("\n");
}
}
}
}
while
package javabase.struct;
public class WhileDemo03 {
public static void main(String[] args) {
int i=1;
while (i<=1000){
if(i%5==0){
System.out.print(i+"\t");
}
if (i%15==0){
System.out.print("\n");
}
i++;
}
}
}
补充print和println
print输出完不会换行
println输出完换行
break
-
break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(break语句在switch语句中使用,不使用会造成case穿透现象) test: package javabase.struct;
public class ForDemo04 {
public static void main(String[] args) {
int i=0;
while (i<100){
i++;
if (i==50){
break;
}
System.out.println(i);
}
}
}
-
continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否循环的判定。
test:
package javabase.struct;
public class WhileDemo05 {
public static void main(String[] args) {
int i=0;
while (i<100){
i++;
if (i%2==1){
System.out.println(i);
continue;
}
}
}
}
goto关键字
- goto关键字很早就出现在程序设计语言中。尽管goto仍是一个保留字,但并未在语言中得到广泛的应用;然而在break和continue依然能看见goto的影子,带有标签的break和continue
- 标签是值后面跟一个冒号的标识符,例如latel
- 对于Java来说唯一用到标签的地方是在循环语句之前。而在循环语句之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue通常只中断当前循环但若是随着标签使用,他们就会中断到存在标签的地方。
Scanner类
-
通过scanner类获取用户的输入 -
通过next()或者nextLine()方法来获取用户输入的字符串类型 -
通过hasnext()或者hasnextLine()方法判断是否还有要输入的字符串
next方法
package javabase.scanner;
import java.util.Scanner;
public class Demo01 {
public static void main(String[] args) {
Scanner s=new Scanner(System.in);
//创建一个扫描器对象,用于接受键盘数据
System.out.println("使用方法next接收:");
//判断用户有没有输入字符串
if (s.hasNext()){
//使用next方法接收
String str = s.next();
System.out.println("使用next方法输出:"+str);
}
//凡是属于io流的类如果不关闭会一直占用资源,要养成好的代码习惯,用完关闭
s.close();
}
}
nextLine方法
package javabase.scanner;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import java.util.Scanner;
public class Demo02 {
public static void main(String[] args) {
Scanner s=new Scanner(System.in);
System.out.println("使用nextLine方法输入:");
if (s.hasNextLine()) {
String str = s.nextLine();
System.out.println("使用nextLine方法输出:" + str);
}
s.close();
}
}
其他数据类型
package javabase.scanner;
import java.util.Scanner;
public class Demo04 {
public static void main(String[] args) {
double d=0.0;
Scanner scanner=new Scanner(System.in);
//输入
System.out.println("请输入一个数字:");
if (scanner.hasNextDouble()){
d=scanner.nextDouble();
System.out.println("输出:"+d);
}
scanner.close();
}
}
9 *9乘法表
package javabase.struct;
public class Test {
public static void main(String[] args) {
//九九乘法表
/*
1. 先打印输出1列
2. 然后再用循环包起来
3. 重复
4. 调整样式
通过99乘法表可以看出外边的for循环控制这乘法表的行,里面的控制着行,外边的控制着列
*/
for (int j=1;j<=9;j++) {
for (int i = 1; i <= j; i++) {
System.out.print(i + "*" + j + "=" + (j * i)+"\t");
}
System.out.println();
}
}
}
数组1
声明和创建
- 首先必须生命数组变量,才能在程序中使用数组。下面是声明数组的语法:
dateType(数组的数据类型)[] 变量名;//首选
dateType(数组的数据类型) 变量名[];//为c语言开的后门
dateType [] arrRefVar=new dateType[arraySize(数组长度大小)];
- 数组通过索引访问的,数组索引从0开始。
- 获取数组长度
arrays.length
- 如果数组没有实例化,那就是默认值(0或者0.0或者false或者\u0000)。
test:
package javabase.array;
public class Demo01 {
public static void main(String[] args) {
int [] flower=new int[5];
flower[0]=10;
System.out.println(flower[0]);
System.out.println(flower[1]);
for (int i = 0; i < flower.length; i++) {
flower[i]=0;
System.out.println(flower[i]);
}
}
}
内存分析(数组)
- 声明数组
int [] add;
- 创建数组
add=new int [5];
内存分析:1.先在栈中开辟一块空间,定义叫add这个名字的数组。2.在堆中开辟一块空间,将这一块空间开始分配,从数组的下标0开始,并给他们赋予上相对应的值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2SwEUinN-1631964754379)(C:\Users\35122\Desktop\java学习\Java学习图片\内存分析\内存分析.png)]
三种初始化
package javabase.array;
public class Demo03 {
public static void main(String[] args) {
//静态初始化 创建+赋值
int [] i={0,10,20,30};
System.out.println(i[1]);
//动态初始化:包含默认初始化
int[] i1=new int [10];
i1[0]=10;
System.out.println(i1[0]);
System.out.println(i1[1]);
}
}
数组是引用类型,他的元素相当于类的实例变量,因此数组一经分配空间,其中每个元素也被按照实例变量同样的方式被隐式初始化。
四个基本的特点
-
其长度是确定的。数组一旦被创建,他的大小就是不可以改变的 -
其元素唏嘘是相同类型,不允许出现混合类型 -
数组中的元素可以是任何数据类型,包括基本类型和引用类型。 -
数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。 数组本身就是对象,Java中对象实在堆中的,因此数组无论是原始类型还是其他对象类型 数组对象本身是在堆中的 异常:下标越界 下标的合法区间:【0,arrays.length-1】,如果越界就会报错; 代码示例: package javabase.array;
public class Demo04 {
public static void main(String[] args) {
int [] i=new int[1];
System.out.println(i[3]);
}
}
报错:Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at javabase.array.Demo04.main(Demo04.java:6)
数组下标越界:ArrayIndexOutOfBoundsException
小结
- 数组是相同类型(数据类型也可以是任意类型)的有序集合
- 数组也是对象。数组相当于对象的成员变量
- 数组的长度是确定的,不可变的。如果越界,会报异常ArrayIndexOutOfBoundsException
数组2
数组的使用
代码示例:
package javabase.array;
import javax.swing.*;
public class Demo05 {
public static void main(String[] args) {
int [] i=new int[10];
for(int i1=0;i1<i.length;i1++){
i[i1]=i1;
System.out.println(i[i1]);
}
}
}
- For-Each循环—打印全部元素jdk5,没有下标
示例:
package javabase.array;
public class Demo06 {
public static void main(String[] args) {
int [] i={1,2,3,4,5};
for (int i1 : i) {//讲数组中的每个元素赋值给int i1
System.out.println(i1);
}
}
}
package javabase.array;
public class Demo07 {
public static void main(String[] args) {
int [] arrays={1,2,3,4,5};
printArrays(arrays);
}
//打印数组中的各个元素
public static void printArrays(int [] sum){
for (int i = 0; i < sum.length; i++) {
System.out.println(sum[i]);
}
}
}
反转数组:
package javabase.array;
public class Demo07 {
public static void main(String[] args) {
int [] arrays={1,2,3,4,5};
int [] reverse= reverse(arrays);
printArrays(reverse);
}
//反转数组
public static int [] reverse(int [] arrays){
int [] reault =new int[arrays.length];
for (int i = 0,j= reault.length-1; i < arrays.length; i++,j--) {
reault[j]=arrays[i];
}
return reault;
}
//打印数组中的各个元素
public static void printArrays(int [] sum){
for (int i = 0; i < sum.length; i++) {
System.out.println(sum[i]);
}
}
}
多维数组
- 多维数组可以看成数组的数组,比如二维数组就是一个特殊的
一维数组,其每一个元素都是一个数组
package javabase.array;
public class Demo08 {
public static void main(String[] args) {
int [][] arrays=new int[2][2];
//获取长度
System.out.println(arrays.length);
System.out.println(arrays[0].length);
System.out.println(arrays[1].length);
//打印每个元素
int [] [] arrays1={{10,10}, {10,10}};
System.out.println(arrays1.length);
System.out.println(arrays1[0].length);
for (int i = 0; i <arrays1.length ; i++) {
for (int j = 0; j < arrays1[i].length; j++) {
System.out.println(arrays1[i][j]);
}
}
}
}
arrays类
查看jdk帮助文档
冒泡排序
冒泡排序无疑是最为出名的排序算法之一,总共有8大排序!
冒泡的代码还是相当简单的,两层循环,外层冒轮数,里面依次比较,江湖中人人尽皆知!
我们看到嵌套循环,应该立马就可以得出这个算法的时间复杂度为O(n2)!
代码如下:
package javabase.array;
import java.util.Arrays;
public class Demo09 {
public static void main(String[] args) {
int [] a={16,6,3,2};//4
int []b=sore(a);
System.out.println(Arrays.toString(b));
}
//冒泡排序
//
public static int [] sore(int [] arrays){
int temp=0;
for (int i = 0; i < arrays.length-1 ; i++) {
//下面的i参数加不加都可以得出正确答案,但是加上可以减少程序的负担;原因:当走完内循环的时候,已经有一个数排到了正确的位置,可以减少一轮的输出
for (int j = 0; j < arrays.length-1-i; j++) {
if (arrays[j+1]<arrays[j]){
temp=arrays[j+1];
arrays[j+1]=arrays[j];
arrays[j]=temp;
}
}
}
return arrays;
}
}
稀疏数组
案例
原始:
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 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 0 0 0 0 0 0 0 0
输出稀疏数组:
解读:11行11列有效值2
第一行第二列值为1
…
11 11 2 1 2 1 2 3 2
代码
package javabase.array;
public class Test {
public static void main(String[] args) {
System.out.println("原始数组");
int[][] array = new int[11][11];
array[1][2] = 1;
array[2][3] = 2;
for (int[] anInt : array) {
for (int anInt1 : anInt) {
System.out.print(anInt1 + "\t");
}
System.out.println();
}
System.out.println("================================================");
System.out.println("稀疏数组");
int sum = 0;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++) {
if (array[i][j] != 0) {
sum++;
}
}
}
System.out.println("有效值的个数" + sum);
int[][] array2 = new int[sum + 1][3];
array2[0][0] = 11;
array2[0][1] = 11;
array2[0][2] = sum;
int count = 0;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
if (array[i][j] != 0) {
count++;
array2[count][0] = i;
array2[count][1] = j;
array2[i][2] = array[i][j];
}
}
}
System.out.println("输出稀疏数组:");
for (int[] anInt : array2) {
for (int anInt1 : anInt) {
System.out.print(anInt1 + "\t");
}
System.out.println();
}
System.out.println("========================");
System.out.println("还原稀疏数组:");
int[][] array3 = new int[array2[0][0]][array2[0][1]];
for (int i = 1; i < array2.length; i++) {
array3[array2[i][0]][array2[i][1]] = array2[i][2];
}
for (int[] anInt : array3) {
for (int anInt1 : anInt) {
System.out.print(anInt1 + "\t");
}
System.out.println();
}
}
}
面向对象1
比较:
定义
-
面向对象编程(Object-Oriented Programming,OOP) -
面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据。 -
抽象:抽象是从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征的过程。具体地说,抽象就是人们在实践的基础上,对于丰富的感性材料通过去粗取精、去伪存真、由此及彼、由表及里的加工制作,形成概念、判断、推理等思维形式,以反映事物的本质和规律的方法。 -
三大特性
-
从认识论的角度考虑是先有对象,后有类的。对象,具体的事物。类,是抽象的是对对象的抽象(自我理解:具有教育能力的人,人在这里是对象,老师是一个抽象的概念,是一个类)。 -
从代码的角度考虑是先有类后有对象。类是对象的模板。(在代码的角度,是先有老师这个整体,然后再有他们各自的功能。) 回顾方法
方法定义:
- 修饰符
- 返回类型:void 、基本数据类型
- break:**跳出switch,结束循环和return的区别,return结束方法 **
- 方法名:首字母小写,驼峰命名规范
- 参数列表:参数类型+参数名-------形式参数和实参
- 异常抛出:略(未学习)
方法调用 :
test:
package javabase.oop;
public class Demo01 {
//静态方法的调用
public static void main(String[] args) {
add();
}
public static void add(){
}
}
test:
package javabase.oop;
public class Demo02 {
public static void main(String[] args) {
Demo02 demo02=new Demo02();
demo02.even();
}
public void even(){
}
}
- 形参-----占用符,实参----实际参数
- 值传递和引用传递
- this关键字的调用
值传递:
test:
package javabase.oop;
public class Demo03 {
//值传递
public static void main(String[] args) {
int a=1;
System.out.println(a);
add();
System.out.println(a);
}
public static void add(){
int a=10;
}
}
自我理解:
这个程序从main方法进入之后,调用了add();这个方法并没有返回值,只是单纯的跑了一遍这个方法,并没有将10这个值赋值给a。
test2:
package javabase.oop;
public class Demo03 {
//值传递
public static void main(String[] args) {
int a=1;
System.out.println(a);
a= add();
System.out.println(a);
}
public static int add(){
int a=10;
return a;
}
}
引用传递—本质上还是值传递
package javabase.oop;
public class Demo04 {
public static void main(String[] args) {
Person person=new Person();
System.out.println(person.name);
//1.执行下行方法,调用了person这个变量,也就是拥有了person类的属性
//2.方法中的person。name也就指向了Person类中name属性,并给它赋值
//3.然后在进行输出
Demo04.a(person);
System.out.println(person.name);
}
// 变量类型 变量名
public static void a(Person person){
person.name="laji";
}
}
class Person{
String name;
}
创建和初始化对象
类与对象的关系
创建和初始化
test:
Student类:
package javabase.oop;
public class Student {
String name;
int age;
}
Demo05:
package javabase.oop;
public class Demo05 {
static int age=0;
public static void main(String[] args) {
Student xiaoming=new Student();
Student xiaohong=new Student();
xiaoming.name="小明";
xiaoming.age=3;
System.out.println(xiaoming.age);
System.out.println(xiaoming.name);
xiaohong.name="小红";
xiaoming.age=3;
System.out.println(xiaoming.age);
System.out.println(xiaoming.name);
}
}
构造器(构造方法)详解-----掌握!
特点:
- 和类名相同
- 没有返回值和void
作用
- new 本质是在调用构造方法
- 初始化对象的值
注意点:
- 定义有参构造之后,如果想使用有参构造,必须在定义一个无参构造
反编译class文件:
(无参的)
Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//package javabase.oop;class Person { String name; Person() { }}
test:(有参的)
Person类:
package javabase.oop;class Person { String name; //无参构造 public Person(){}//有参构造 public Person(String name) { this.name = "name"; }}
Demo06类:
package javabase.oop;import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;public class Demo06 { public static void main(String[] args) { Person demo01=new Person(); System.out.println(demo01.name); Person dmeo02=new Person(demo01.name); System.out.println(dmeo02.name); }}
内存分析面对对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kRQHo2EP-1631964754381)(C:\Users\35122\Desktop\java学习\Java学习图片\面对对象\面对对象.png)]
先把类以及类的属性加载到堆的方法区,然后再在栈中生成引用变量名,最后在给堆中的属性赋值,以及执行方法。
补充
对象的引用:
- 引用类型;基本类型
- 对象是通过引用来操作的: 栈------》堆(地址)
面向对象2
封装
- 该露的露,该藏的藏
-
- 我们程序设计要追求“高内聚,低耦合”。高内聚:类的内部数据操作细节自己完成,不允许外部干涉;低耦合:暴露少量的方法给外部使用。
- 封装(数据的隐藏)关键字private
-
- 通常,应禁止直接访问一个对象中的数据的实际表示,而应通过操作接口来访问,这成为信息隐藏。
- 属性私有;get/set
-
- get:获得数据
- set:修改数据,通常加上判断,判断数据是否合理。
- 快捷键:a/t+inside
test:
Student:
package javabase.oop.demo02;
public class Student {
private int age;
private char set;
public char getSet() {
return set;
}
public void setSet(char set) {
this.set = set;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Demo02:程序入口
package javabase.oop.demo02;
public class Demo02 {
public static void main(String[] args) {
Student student = new Student();
System.out.println(student.getAge());
student.setAge(10);
System.out.println(student.getAge());
}
}
继承(核心)
- 继承本质是对某一批类的抽象,从而实现对现实世界更好的建模
- extends的意识是“拓展”。子类对父类的拓展。
- Java中没有多继承,只有单继承。
- 继承是类与类之间的某种联系。除此之外,类和类之间还有依赖,组合,聚合等
- 继承是两个类,一个是子类(派生类),一个是父类(基类),子类继承父类,用关键字extends。
- 子类继承完父类就会拥有父类的全部公开的属性和方法
- 子类和父类从某种意义上是“is a ”的关系
- 私有的东西无法被继承
- object类,所有的类都直接或者间接继承object类
- super
- 方法重写
test:
父类:
package demo01;
public class Person {
public int money=10_0000_0000;
public static void say(){
System.out.println("叫了一声");
}
}
子类:
package demo01;
public class Student extends Person{
}
主程序:
package demo01;
public class Application {
public static void main(String[] args) {
Student student = new Student();
System.out.println(student.money);
student.say();
}
}
super详解
注意点
- super调用父类的构造方法,必须在构造方法中的第一个
- super必须只能出现在子类的方法或者构造方法中
- super和this不能同时使用
- 私有的属性不能调用
跟this的不同点:
- 代表的对象不同
-
- this:本身带哦用这个对象
- 代表父类对象的应用
- 前提不同
-
- this:没有继承也可以使用
- super:只能在继承中使用
- 构造方法
-
- this:本类的构造
- super:父类的构造
测试1
父类
package demo02;
public class Person {
protected String name="person";
}
子类
package demo02;
public class Student extends Person{
private String name="student";
public void test(String name){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
}
程序入口
package demo02;
public class application {
public static void main(String[] args) {
Student student = new Student();
student.test("name");
}
}
测试2
子类
package demo02;
public class Student extends Person{
private String name="student";
public void print(){
System.out.println("student执行了");
}
public void test1(){
print();//student的print方法
this.print();//student的print方法
super.print();//person类的print方法
}
}
父类
package demo02;
public class Person {
protected String name="person";
public void print (){
System.out.println("person执行了");
}
}
程序入口
package demo02;
public class application {
public static void main(String[] args) {
Student student = new Student();
//student.test("name");
student.test1();
}
}
测试3
子类—子类中的构造函数里面隐藏了一行代码super();
如果要写出来,必须卸载构造函数的第一行
this与super不能一起用,否则报错
package demo02;
public class Student extends Person{
private String name="student";
public Student() {
System.out.println("student");
}
}
父类
package demo02;
public class Person {
protected String name="person";
public Person() {
System.out.println("person");
}
}
程序入口
package demo02;
public class application {
public static void main(String[] args) {
Student student = new Student();
}
}
重写
重写:需要有继承关系,子类重写父类。
特点:
- 方法名相同
- 参数列表相同
- 修饰符:范围可以扩大,但是不能缩小;public—》protected------》default------》private
- 抛出的异常:范围可以被缩小,但是不能被扩大:classoutFoundException====》Exception
重写:子类的方法和父类一致,但是方法体不同
重写的好处:
- 父类的功能,子类不一定需要或者不一定满足。
注意跟静态的区分开
测试
父类
package override;
public class A {
public void test(){
System.out.println("a--->b");
}
}
子类
package override;
public class B extends A{
@Override
public void test() {
System.out.println("b---->a");
}
}
程序入口
package override;
public class Application {
public static void main(String[] args) {
A a=new B();
a.test();
B b = new B();
b.test();
}
}
面向对象3
多态
- 即同一方法可以根据发送的对象不同采取多种不同的行为方式。
- 一个对象的实际类型是确定的,但是可以指向对象的引用的类型有很多(父子类,有关系的类)
- 多态的存在
-
- 有继承关系
- 有方法的重写
- 父类的引用指向的子类对象
- 子类重写父类的方法执行子类
- 注意:多态是方法的多态,属性没有多态
- instanceof类型转换 引用类型
一个对象的实际类型是可以确定的;
可以指向的引用类型就不确定了:父类的引用类型指向子类
子类重写了父类的方法,执行子类的方法
实例:
父类:
package demo03;
public class Person {
public void run(){
System.out.println("eat");
}
}
子类:
package demo03;
public class Student extends Person{
public void run(){
System.out.println("tea");
}
}
测试类:
package demo03;
import java.util.Scanner;
public class Appcation {
public static void main(String[] args) {
//Student student = new Student();
Person person=new Student();
person.run();
// student.run();
}
}
注意事项
- 多态是方法的多态
- 父类和子类,有联系,类型转换异常classcastexception
- 存在条件:继承,重写方法,父类类型指向子类
- 不存在状态:static 方法属于类,不属于实例,final 常量 ,private 方法;
instanceof和类型转换
instanceof
判断一个对象是什么类型
输出布尔类型
System.out.println(student instanceof Person);
类型转换
基本类型转换:
低转高:自动转换
高转低:强制转换64 double long 32 int float 16 short char 8 byte 1 boolean
引用类型转换:
父类转子类:自动转换
子类转换父类:强制转换
Person类:
package demo03;
public class Person {
public void run(){
System.out.println("eat");
}
}
Student:
package demo03;
public class Student extends Person{
public void run(){
System.out.println("tea");
}
public void a(){
System.out.println("a");
}
}
Application:
package demo03;
import java.util.Scanner;
public class Application {
public static void main(String[] args) {
Person person=new Person();
Student student=new Student();
Person person1= student;
person1.run();
Student s2= (Student) person;
s2.a();
}
}
static关键字总结
静态变量
非静态变量
静态方法
非静态方法
package demo04;
public class Person {
private static int age;
private double d;
public static void eat(){
}
public void drink(){
}
public static void main(String[] args) {
System.out.println(Person.age);
Person person = new Person();
System.out.println(person.d);
Person.eat();
person.drink();
}
}
静态代码块>匿名代码块>构造方法
静态代码块只执行一次
匿名代码块赋初始值用的
静态导入包:import static java.lang.Math.random;
抽象类
abstract 抽象类
abstract 抽象方法
注意事项
- 不能new这个抽象类,只能通过子类去实现它:约束的条件;
- 抽象类中可以写普通的方法
- 抽象方法必须在抽象类中
- 抽象类中有构造器
构造器作用:是定义在Java类中的一个用来初始化对象的方法,用new+构造方法去创建一个新的对象,并给对象实例进行赋值。
接口interface
作用:
- 约束
- 定义一些方法,让不同的人实现
- 所有的方法public abstract
- 常量public static final
- 接口不能被实例化,接口没有构造方法
- implements可以实现多个接口
- 必须要重写接口中的方法
定义接口:
package demo06;public interface UseService { public static final int AGE=100; public abstract void eat(); void drink();}
实现接口:
package demo06;public class Application implements UseService{ @Override public void eat() { } @Override public void drink() { }}
面向对象4
成员内部类
- 可以直接访问外部成员
- 重名会优先访问内部类的属性
- 并且生成字节码文件
- 成员内部类不能定义静态的属性和方法,但是可以包含静态常量
package classtest;
public class Outer {
private String name ="张三";
private int age=10;
class Inter{
private String name ="北京";
private int phone =110;
public void show(){
System.out.println(Outer.this.name);
System.out.println(age);
//重名会优先访问内部类的属性
System.out.println(name);
System.out.println(phone);
}
}
}
class OuterTest{
public static void main(String[] args) {
Outer.Inter inter=new Outer().new Inter();
inter.show();
}
}}
静态内部类
与外部类相似,拥有自己的属性和方法,类名前面加一个关键字static
- 不依赖外部类对象,可直接创建或者类名访问,可以声明静态成员。
- 只能通过new的形式访问外部类的静态成员
package classtest02;
public class Outer {
//外部类
private String name="zhangsan ";
private int age =10;
private String address="shanghai ";
static class Inter{
//静态内部类
private String name1="lisi ";
private int age1 =155;
private static String address1="beijing ";
public void show(){
//1. 创建对象2. 实例化
Outer outer = new Outer();
System.out.println(outer.name);
System.out.println(outer.age);
System.out.println(outer.address);
//inter
System.out.println(name1);
System.out.println(age1);
System.out.println(address1);
}
}
}
class TestOuter{
public static void main(String[] args) {
Outer.Inter inter = new Outer.Inter();
inter.show();
}
}
局部内部类
package classtest03;
public class Outer {
//外部类
private String name="刘德华";
private int age=10;
public void show(){
//默认常量
String name="刘**";
//局部内部类
class Inter{
private String address="北京";
private int count=1000;
public void show1(){
int phone =10000;
System.out.println(age);
System.out.println(Outer.this.name);
System.out.println(name);
System.out.println(address);
System.out.println(count);
System.out.println(phone);
}
}
Inter inter = new Inter();
inter.show1();
}
}
class TestOuter{
public static void main(String[] args) {
Outer outer = new Outer();
outer.show();
}
}
匿名内部类
没有类名的局部内部类(一切特征与局部内部类相同)
必须继承一个父类或者接口。
定义类、实现类、创建对象的语法合并,只能创建一个该类的对象。
package classtest04;
public interface Usb {
void service();
}
class Mouse{
public static void main(String[] args) {
Usb usb=new Usb(){
@Override
public void service() {
System.out.println("电脑链接成功,鼠标考试运行....");
}
};
usb.service();
}
}
方法1
- 概念:方法是语句的合集,他们在一起执行一个功能。
- 特点:1. 方法是解决一类问题的步骤的有序组合。
-
- 方法包含于类或者对象中
- 方法在程序中被创建在其他地方被引用
设计方法的原则
方法的本意是功能块,就是实现某个功能的语句块集合。我们设计方法的时候,请保持方法的原子性(原子性:就是一个方法只完成1个功能,这样有利于我们后续的拓展)。
方法的命名规范
首字母小写,遵守驼峰命名规范
方法的定义
Java的方法类似于其他语言程序的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法:
方法包含一个方法头和方法体:
test:
修饰符 返回值类型 方法名(参数类型 参数名){
方法体
return 返回值;
}
- 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
- 返回值类型:方法可能有返回值,return valuetype(意思是:返回值类型)是方法返回值的数据类型。有些方法执行所需的操作,但是没有返回值。在这种情况下,return value type的关键字是void
- 方法名:是方法的实际名称。方法名和参数共同构成方法签名。遵循驼峰命名规范
- 参数类型:参数是一个占用符(自我理解:可写可不写,就是一个替代品)。当方法被调用时,传递给参数。这个值被称为实参或者变量。参数列表是指方法参数类型、顺序和参数的个数。参数是可选的,方法中可以不包含参数。
- 形式参数:在被方法调用时用于接收外界输入的数据。
- 实参:调用方法时传递给方法数据
- 方法体:方法包含具体的语句,定义该方法的功能。
test:
比较大小,记得返回值
package javabase.method;
public class Demo01 {
public static void main(String[] args) {
int big=comparison(10,20);
System.out.println(big);
}
//比较大小,然后输出最大的那个数
//加上static
public static int comparison(int a,int b){
int big =0;
if (a==b){
System.out.println("==");
return big;
}
if (a>b){
big=a;
}else {
big=b;
}
return big;
}
}
方法调用
- 调用方法:对象名.方法名(实参列表)
- Java支持两种调用方式,根据方法返回值来选择
- 当方法返回一个值的时候,方法通常被当作一个值,如
int larger=max(30,40);
System.out.println("Hello,World");
return补充:终止方法的作用。
拓展:值传递(Java)和引用传递
自己上网查资料,小白一个,不懂!
方法的重载
- 重载就是在一个类中,有相同的函数名称,但形参不同的函数。
- 方法重载的规则:
- 方法名称必须相同。
- 参数列表不同(个数不同、类型不同、参数排列不同),只要有一个不同就可以实现方法的重载。
- 仅仅返回类型不同不足以构成方法的重载。
- 实现理论:方法名称相同时,编译器会根据用方法的参数个数、参数类型等去逐个匹配,已选择对应的方法,如果匹配失败,则编译器会报错。
test:
package javabase.method;
public class Demo01 {
public static void main(String[] args) {
int big=comparison(10,20);//对第一个方法的调用
System.out.println(big);
int big1=comparison(10,20,30);
System.out.println(big1);//对于第2个方法的调用
}
//比较大小,然后输出最大的那个数
//加上static
//1
public static int comparison(int a,int b){
int big =0;
if (a==b){
System.out.println("==");
return big;
}
if (a>b){
big=a;
}else {
big=b;
}
return big;
}
//比较大于两个数的大小
//2
public static int comparison(int a,int b,int c){
int big =0;
if (a==b){
if (b==c) {
System.out.println("==");
return big;
}
}
if (a>b){
if (a>c){
big=a;
}else{
big=c;
}
}else {
if (b>c){
big=b;
}else{
big=c;
}
}
return big;
}
}
方法2
命令行传参
有时候你希望运行一个程序的时候再给他传递参数。这要靠传递命令行参数给main()函数实现。
javac与java必须环境变量的配置正确
package javabase.method;
public class Demo02 {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println("args["+i+"]:"+args[i]);
}
}
}
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7CYLg04F-1631964754382)(C:\Users\35122\AppData\Roaming\Typora\typora-user-images\image-20210809102333456.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iTM4MVdQ-1631964754383)(C:\Users\35122\Desktop\java学习\Java学习图片\方法\方法2.png)]
可变参数(不定项参数)
-
jdk5开始,Java支持同类型的可变参数给一个方法 -
在方法声明中,在指定参数类型后面加一个省略号(…)。 -
一个方法中只能指定一个可变参数,他必须是方法的最后一个参数。任何普通的参数必须在它之前声明。 -
实质:把你传进去的参数封装成一个数组
public static void test(double ... i){
}
test :
package javabase.method;
public class Demo02 {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println("args["+i+"]:"+args[i]);
}
}
public static void test( double ...i){
}
}
递归
递归就是a方法调用a方法!就是自己调用自己
利用递归可以用简单的程序解决一些复杂的问题。通常吧大型复杂的问题层层转化为一个与原问题相似的规模较小的问题解决,递归策略只需少量的程序就可以描述出解题过程所需要的多次重复计算,大大减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合
递归的结构包括两个部分:
- 递归头:什么时候不调用方法。没有递归头,就会陷入死循环。
- 递归体:什么时候需要调用自身方法。
test:
package javabase.method;
public class Demo03 {
public static void main(String[] args) {
//阶乘5! 5*4*3*2*1
System.out.println(f(10000));
}
public static double f(double n){
if (n==1){
return 1;
}else {
return n*f(n-1);
}
}
}
异常
- 实际工作中,遇到的情况不可能是非常完美的。比如:你写的某个模块,用户输入不一定符合你的要求、你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等。我们程序在跑着,内存或硬盘可能满了。
- 软件工程过程中,非常可能遇到刚刚提到的异常问题,我们叫异常。
- 异常指程序运行中出现的不期而至的各种问状况,如:文件找不到、网络连接失败,非法参数。
- 异常发生在程序运行期间,他影响了正常的程序执行流程。
简单分类:检查行异常,运行时异常,错误。
异常体系结构
Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。
在Javaapi中已经定义了许多异常类,这些异常类分为两大类:错误Error和异常Exception。
Error错误
- error是有由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
- Java虚拟机运行错误,当jvm不在有继续执行所需的内存资源时,将出现OutOfMemoryEoor。这些异常发生时,Java虚拟机一般会选择线程终止。
- 还有执行在虚拟机试图运行应用时,如类定义错误,连接错误。这些错误时不可查的,因为他们在程序的控制和处理能力之外,而且绝大多数是程序执行时不允许出现的状况。
异常Exception
- 在Exception分支中有一个重要的子类RuntimeException(运行时异常)
-
- ArrayIdexOutOfException数组下标越界
- NullPointException空指针异常
- ArithmeticException算术异常
- ClassNotFoundException找不到类
- 这些异常是不检查异常,程序中可以选择捕获初六,也可以不处理
- 这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类错误的出现。
- Error和Exception的区别:error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机一般会选择终止线程;EXCEPTION通常情况下是可以被程序处理的,并在程序中应该尽可能的去处理这些异常。
捕获异常
关键字try 监控 catch 捕获 finally(最终都会执行的,善后处理工作:io流的关闭) throw(抛出) throws(方法中抛出异常)
- try (){}catch(){}监控异常,并抛出异常,然后在执行后面的程序
- throw和throws 只抛出异常,后面的程序不执行
test:
package exception;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
public class Test {
public static void main(String[] args) {
int a=10;
int b=0;
Test test = new Test();
test.add(10,0);
System.out.println("======================================");
try {
System.out.println(a/b);
} catch (Error error) {
System.out.println("Error");
}catch (Exception e){
System.out.println("Exception");
} finally {
System.out.println("Finally");
}
}
public void add(int a,int b)throws ArithmeticException{
System.out.println(a/b);
if (b==0) {
throw new ArithmeticException();
}
}
}
实际应用中的经验总结
- 处理运行时异常时,采用逻辑去合理规避同时辅助try—catch处理
- 在多重catch块后面,可以在加一个catch(Exception)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上以恶个try-catch处理潜在的异常
- 尽量去处理异常,切忌只是简单调用printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去坚决
- 尽量添加finally语句块去释放占用的资源
自定义异常
test:
package exception;
public class MyExcepion extends Exception {
private int age;
@Override
public String toString() {
return "MyExcepion{" + age + '}';
}
public MyExcepion(int a) {
this.age = a;
}
}
测试:
package exception;
public class Test {
static void test(int b) throws MyExcepion {
System.out.println("传递的参数是"+b);
if (b>10){
throw new MyExcepion(b);
}
System.out.println("OK");
}
public static void main(String[] args) {
try {
test(11);
} catch (MyExcepion e) {
System.out.println("MyException"+e);
}
}
}
Java常用类
Objeck类
- 超类,基类,所有的类的直接或间接父类,位于继承树的最顶层
- 任何类,如没有书写extends显示继承某个类,都默认继承Object类,否则为间接继承
- Object类中定义的所有方法,是所有对象都具备的方法。
- Object类型可以存储任何对象。
-
- 作为参数,可接受任何对象
- 作为返回值,可返回任何对象
getClass()方法
package objecttest;
public class Student {
private String name;
private int age;
// public String getName() {
// return name;
// }
//
// public void setName(String name) {
// this.name = name;
// }
//
// public int getAge() {
// return age;
// }
//
// public void setAge(int age) {
// this.age = age;
// }
public Student(String name,int age) {
this.name = name;
this.age=age;
}
}
class TestStudent{
public static void main(String[] args) {
Student student = new Student("zhangsan",100);
Class calss1=student.getClass();
Student lisi = new Student("lisi", 200);
Class class2=lisi.getClass();
if(calss1==class2){
System.out.println("他们是一种类型");
}else{
System.out.println("他们不是一种类型");
}
}
}
getHashCode()
内存分析
- 返回该对象的哈希码值
- 哈希码值根据对象的地址或者数字使用hash算法计算出来的int类型的数值
- 一般情况下,相同的对象返回相同的哈希码。
package objecttest;
public class Student {
private String name;
private int age;
// public String getName() {
// return name;
// }
//
// public void setName(String name) {
// this.name = name;
// }
//
// public int getAge() {
// return age;
// }
//
// public void setAge(int age) {
// this.age = age;
// }
public Student(String name,int age) {
this.name = name;
this.age=age;
}
}
class TestStudent{
public static void main(String[] args) {
Student student = new Student("zhangsan",100);
Student lisi = new Student("lisi", 200);
Class class2=lisi.getClass();
// if(calss1==class2){
// System.out.println("他们是一种类型");
// }else{
// System.out.println("他们不是一种类型");
// }
System.out.println(student.hashCode());
Student s3 =student;
System.out.println(lisi.hashCode());
System.out.println(s3.hashCode());
}
}
toString()
- 返回该对象的字符串表示(表现形式)。
- 可以根据程序需求覆盖该方法,如展示对象的各个属性值。
- 当不满足需求时,重写方法(返回值,参数列表相同)
equals()方法
- 默认实现(this=obj),比较两个对象的地址是否相同。
- 可进行覆盖,比较两个对象的内容是否相同。
- 覆盖步骤:
-
- 比较两个引用是否指向同一个对象
- 判断obj是否为null
- 判断两个引用指向的对象类型是否一致
- 强制类型转换
- 一次比较各个属性值是否相同
- 返回布尔类型
package objecttest;
import java.util.Objects;
public class Student {
private String name;
private int age;
// public String getName() {
// return name;
// }
//
// public void setName(String name) {
// this.name = name;
// }
//
// public int getAge() {
// return age;
// }
//
// public void setAge(int age) {
// this.age = age;
// }
public Student(String name,int age) {
this.name = name;
this.age=age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public boolean equals(Object obj){
//判断两个对象是否指向同一个引用
if(this==obj){
return false;
}
//判断obj是否是null
if (obj==null){
return false;
}
//强制类型转换
if (obj instanceof Student){
Student s=(Student) obj;
//比较各个属性值是否相同
if (this.name.equals(s.name)&&this.age==s.age){
return true;
}
}
return false;
}
}
class TestStudent{
public static void main(String[] args) {
Student student = new Student("zhangsan",100);
Student lisi = new Student("lisi", 200);
Student lisi1= new Student("lisi", 200);
Class class2=lisi.getClass();
// if(calss1==class2){
// System.out.println("他们是一种类型");
// }else{
// System.out.println("他们不是一种类型");
// }
// System.out.println(student.hashCode());
// Student s3 =student;
// System.out.println(lisi.hashCode());
// System.out.println(s3.hashCode());
//
//toString方法
System.out.println(student.toString());
System.out.println(lisi.toString());
System.out.println("----------------------------");
System.out.println(lisi.equals(lisi1));
}
}
finalize()方法
-
当对象被判定为垃圾对象时,有jvm自动调用此方法,用以标记垃圾对象。 -
垃圾对象:没有有效指向此对象时,为垃圾对象。 -
垃圾回收:由GC销毁垃圾对象,释放储存空间。 -
自动回收机制:jvm内存耗尽时,一次性回收所有垃圾对象。 -
手动回收垃圾:使用System.gc();通知jvm执行垃圾回收。 Student: package objecttest;
import java.util.Objects;
public class Student {
private String name;
private int age;
// public String getName() {
// return name;
// }
//
// public void setName(String name) {
// this.name = name;
// }
//
// public int getAge() {
// return age;
// }
//
// public void setAge(int age) {
// this.age = age;
// }
@Override
protected void finalize() throws Throwable {
System.out.println(this.name+"垃圾被回收了");
}
public Student(String name, int age) {
this.name = name;
this.age=age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public boolean equals(Object obj){
//判断两个对象是否指向同一个引用
if(this==obj){
return false;
}
//判断obj是否是null
if (obj==null){
return false;
}
//强制类型转换
if (obj instanceof Student){
Student s=(Student) obj;
//比较各个属性值是否相同
if (this.name.equals(s.name)&&this.age==s.age){
return true;
}
}
return false;
}
}
class TestStudent{
public static void main(String[] args) {
Student student = new Student("zhangsan",100);
Student lisi = new Student("lisi", 200);
Student lisi1= new Student("lisi", 200);
Class class2=lisi.getClass();
// if(calss1==class2){
// System.out.println("他们是一种类型");
// }else{
// System.out.println("他们不是一种类型");
// }
// System.out.println(student.hashCode());
// Student s3 =student;
// System.out.println(lisi.hashCode());
// System.out.println(s3.hashCode());
//
//toString方法
System.out.println(student.toString());
System.out.println(lisi.toString());
System.out.println("----------------------------");
System.out.println(lisi.equals(lisi1));
}
}
TestStudent:
package objecttest;
public class TestStudents01 {
public static void main(String[] args) {
new Student("aaa",10);
new Student("bbb",10);
new Student("ccc",10);
new Student("ddd",10);
new Student("eee",10);
System.out.println("垃圾回收了");
System.gc();
}
}
包装类
基本数据类型所对应的引用类型
一般地,当我们需要用到数字时,我们通常会使用内置数据类型如:byte、int、long、double等;
所有的包装类**(Integer、Long、Byte、Double、Float、Short)**都是抽象类 Number 的子类。
包装类 | 基本数据类型 |
---|
Boolean | boolean | Byte | byte | Short | short | Integer | int | Long | long | Long | char | Float | float | Double | double |
装箱和拆箱
装箱:基本数据类型转化成引用类型,反之为拆箱。
JDK1.5之后自动装箱和拆箱
package objecttest;
public class TestInteget {
public static void main(String[] args) {
//手动装箱和拆箱
int age=10;
Integer i1=new Integer(age);
int i2=i1.intValue();
System.out.println(i2);
Integer integer = new Integer(100);
int age2=integer.intValue();
System.out.println(age2);
//JDK1.5以后实现自动装箱和拆箱
System.out.println("---------------自动-----------------");
//自动
int count =100;
Integer integer1=count;
int age3=integer1;
System.out.println(integer1);
System.out.println(age3);
}
}
parse()方法
-
8中包装类提供不同类型间的转换方式 -
- Number父类中提供的6个共性方法
- parseXXX()静态方法
- valueOf()静态方法
-
注意:需保证类型兼容,否则抛出NumberFormatException异常。 -
package objecttest;
public class Demo01 {
public static void main(String[] args) {
//基本类型转换成字符串
int i1=1000;
String s1=i1+"";
Integer integer=Integer.valueOf(i1);
String s2=integer.toString(integer);
System.out.println(s2);
System.out.println(s1);
//字符串转换成基本数据类型
String s3="123";
int i2=Integer.parseInt(s3);
System.out.println(s3);
System.out.println(i2);
//boolean类型 "true"--->true 非"true"------>false
String s4="true";
String s5="ture";
boolean b=Boolean.parseBoolean(s4);
System.out.println(b);
boolean b1=Boolean.parseBoolean(s5);
System.out.println(b1);
}
}
整数缓冲区
- Java预先创建了256个常用的整数包装类型对象
- 在实际应用当中,对已创建的对象进行复用
package objecttest;
public class Demo02 {
public static void main(String[] args) {
Integer integer = new Integer(100);
Integer integer1 = new Integer(100);
System.out.println(integer==integer1);
Integer integer2=Integer.valueOf(100);
Integer integer3=Integer.valueOf(100);
System.out.println(integer2==integer3);
Integer integer4=Integer.valueOf(200);
Integer integer5=Integer.valueOf(200);
System.out.println(integer4==integer5);
}
}
String类
- 字符串是常量,创建之后不可改变。
- 字符串字面值存储在字符串常量池中,可以共享。
- String s=“hello”;产生一个对象,字符串常量池中存储。
- String s=new String(“World”);产生两个对象,堆、池个存储一个
常用方法
public int length();int返回字符串长度
public char charAt(int index);char根据下标获取字符
public boolean contains(String str);判断当前字符串是否包含str boolean
public char [] toCharArray();将字符串转化成数组。
public int indexOf(String str);查找str首次出现的下标,存在。则返回下标;不存在,则返回-1
public int lastindexOf(String str);查找str字符串最后一次出现的下标。
public String trim();去掉字符串前后的空格。
public String toUpperCase();将小写转化成大写
public boolean endWith(String str);判断字符串时候以str结尾
public String replace(Char oldChar , Char newChar);将旧的字符串替换成新的字符串
public String 【】 split(String str);根据str做拆分
compare比较大小 字典表的位置,长度不同比较长度
equals比较字符串
package classtest05;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Locale;
public class TestString {
public static void main(String[] args) {
String s = " java 是 世界 上 最好 的 语言 ";
//1
System.out.println(s.length());
//2
System.out.println(s.charAt(0));
//3
System.out.println(s.contains("java "));
//4
char[] chars = s.toCharArray();
System.out.println(chars);
//5
System.out.println(s.indexOf("java"));
//6
System.out.println(s.lastIndexOf("java"));
//7
System.out.println(s.trim());
//8
System.out.println(s.toUpperCase());
//9
System.out.println(s.endsWith("语言"));
//10
System.out.println(s.replace("java ", "php "));
//11
String [] arr=s.split(" ");
for (String s1:
arr) {
System.out.println(s1);
}
System.out.println("---------------------------------");
//12
System.out.println(s.compareTo("java "));
}}
Java StringBuffer
当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。
和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象
在使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,所以如果需要对字符串进行修改推荐使用 StringBuffer。
StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。
由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。
实例:
package demo06;
public class Demo07 {
public static void main(String[] args) {
StringBuilder sb=new StringBuilder(10);
sb.append("LIUYUEYANG");//添加
System.out.println(sb);
sb.delete(1,9);//从开始位置,删除到结束位置
System.out.println(sb);
sb.insert(2,"java");//从开始位置开始插入,字符串长度改变
System.out.println(sb);
}
}
主要方法:
序号 | 方法描述 |
---|
1 | public StringBuffer append(String s) 将指定的字符串追加到此字符序列。 | 2 | public StringBuffer reverse() 将此字符序列用其反转形式取代。 | 3 | public delete(int start, int end) 移除此序列的子字符串中的字符。 | 4 | public insert(int offset, int i) 将 int 参数的字符串表示形式插入此序列中。 | 5 | insert(int offset, String str) 将 str 参数的字符串插入此序列中。 | 6 | replace(int start, int end, String str) 使用给定 String 中的字符替换此序列的子字符串中的字符。 |
其他常用方法
序号 | 方法描述 |
---|
1 | int capacity() 返回当前容量。 | 2 | char charAt(int index) 返回此序列中指定索引处的 char 值。 | 3 | void ensureCapacity(int minimumCapacity) 确保容量至少等于指定的最小值。 | 4 | void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) 将字符从此序列复制到目标字符数组 dst 。 | 5 | int indexOf(String str) 返回第一次出现的指定子字符串在该字符串中的索引。 | 6 | int indexOf(String str, int fromIndex) 从指定的索引处开始,返回第一次出现的指定子字符串在该字符串中的索引。 | 7 | int lastIndexOf(String str) 返回最右边出现的指定子字符串在此字符串中的索引。 | 8 | int lastIndexOf(String str, int fromIndex) 返回 String 对象中子字符串最后出现的位置。 | 9 | int length() 返回长度(字符数)。 | 10 | void setCharAt(int index, char ch) 将给定索引处的字符设置为 ch 。 | 11 | void setLength(int newLength) 设置字符序列的长度。 | 12 | CharSequence subSequence(int start, int end) 返回一个新的字符序列,该字符序列是此序列的子序列。 | 13 | String substring(int start) 返回一个新的 String ,它包含此字符序列当前所包含的字符子序列。 | 14 | String substring(int start, int end) 返回一个新的 String ,它包含此序列当前所包含的字符子序列。 | 15 | String toString() 返回此序列中数据的字符串表示形式。 |
BigDecimal类
很多实际应用中需要精确运算,而double是近似值存储,不再符合要求,需要借助BigDicimal。
package classtest06;
import java.math.BigDecimal;
public class TestBigDecimal {
public static void main(String[] args) {
//0.9+1.0
BigDecimal bigDecimal = new BigDecimal("0.9");
BigDecimal bigDecimal1 = new BigDecimal("1.0");
BigDecimal bigDecimal2= bigDecimal.add(bigDecimal1);
System.out.println(bigDecimal2);
//subtract
BigDecimal bigDecimal3=bigDecimal.subtract(new BigDecimal("0.1"));
System.out.println(bigDecimal3);
//multiply
BigDecimal bigDecimal4= bigDecimal.multiply(new BigDecimal("0.8"));
System.out.println(bigDecimal4);
//divide
BigDecimal bigDecimal5 = bigDecimal.divide(new BigDecimal("0.3"));
System.out.println(bigDecimal5);
}
}
注意:在做除法运算时,要用divide的重载方法
- 除法:BigDecimal(Bigdecimal bd , int scal,RoundingMode mode)
- 参数scal:指定精确到小数点后几位
- 参数mode:
-
- 指定小数部分的取舍模式,通常采取四舍五入的模式
- 取值为BigDecimal.ROUND_HALF_UP。
JavaMath类
Java 的 Math 包含了用于执行基本数学运算的属性和方法,如初等指数、对数、平方根和三角函数。
Math 的方法都被定义为 static 形式,通过 Math 类可以在主函数中直接调用。
Math类中提供的方法很多,自己实践!
实例:
package demo06;
public class Demo02 {
public static void main(String[] args) {
System.out.println(Math.max(10,20));//最大值
System.out.println(Math.abs(-10));//绝对值
System.out.println(Math.cos(Math.PI/2));
}
}
区分:
-
round() 它表示四舍五入,算法为 Math.floor(x+0.5),即将原来的数字加上 0.5 后再向下取整,所以,Math.round(11.5) 的结果为12,Math.round(-11.5) 的结果为-11。 -
floor() 返回小于等于(<=)给定参数的最大整数 。 -
ceil() 返回大于等于( >= )给定参数的的最小整数,类型为双精度浮点型。
Java Character类
package demo06;
public class Demo03 {
public static void main(String[] args) {
Character c=new Character('a');
System.out.println(c);
}
}
在某些情况下,Java编译器会自动创建一个Character对象。
例如,将一个char类型的参数传递给需要一个Character类型参数的方法时,那么编译器会自动地将char类型参数转换为Character对象。 这种特征称为装箱,反过来称为拆箱。
转义序列 | 描述 |
---|
\t | 在文中该处插入一个tab键 | \b | 在文中该处插入一个后退键 | \n | 在文中该处换行 | \r | 在文中该处插入回车 | \f | 在文中该处插入换页符 | ’ | 在文中该处插入单引号 | " | 在文中该处插入双引号 | \ | 在文中该处插入反斜杠 |
注意:
\r: return 到当前行的最左边。
\n: newline 向下移动一行,并不移动左右。
Linux中**\n**表示:回车+换行;
Windows中**\r\n**表示:回车+换行。
Mac中**\r**表示:回车+换行。
Date
- date表示特定的瞬间,精确到毫秒。Date类的大部分都已经被Calender类中的方法所取代。
- 时间单位:
-
- 1s=100毫秒
- 1毫秒=1000微秒
- 1微秒=1000纳秒
package classtest06;
import java.util.Date;
public class TestDate {
public static void main(String[] args) {
Date date = new Date();
//今天
System.out.println(date.toLocaleString());
//昨天时间减去今天的时间的一个毫秒数
Date date1 = new Date(date.getTime() - (60 * 60 * 24 * 1000));
System.out.println(date1.toLocaleString());
//after
System.out.println(date.after(date1));
//before
System.out.println(date.before(date1));
//compareTo----->结果:正数,负数和0
int b= date.compareTo(date1);
System.out.println(b);
}
}
Calendarl类
- Calendar提供了获取和设置各种日历字段的方法
-
- 构造方法protected Calendar,由于修饰符是protected,所以无法直接创建该对象
- 其他方法jdk帮助文档
package classtest06;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import java.util.Calendar;
public class TestCalenar {
public static void main(String[] args) {
//获取
Calendar calendar=Calendar.getInstance();
System.out.println(calendar.getTime().toLocaleString());
//获取年月日等
int year=calendar.get(Calendar.YEAR);
int month=calendar.get(Calendar.MONTH);
int date=calendar.get(Calendar.DATE);
int hour=calendar.get(Calendar.HOUR_OF_DAY);
int minute=calendar.get(Calendar.MINUTE);
int second=calendar.get(Calendar.SECOND);
System.out.println(year+"-"+(month+1)+"-"+date+" "+hour+":"+minute+":"+second);
//修改
Calendar calendar1=Calendar.getInstance();
calendar1.set(Calendar.YEAR,2022);
System.out.println(calendar1.getTime().toLocaleString());
//添加时间或者减少时间
calendar1.add(Calendar.YEAR,-1);
System.out.println(calendar1.getTime().toLocaleString());
//获取最大值和最小值
int i=calendar1.getMaximum(Calendar.MONTH);
System.out.println(i);
}
}
SimpleDateFormat
- SimpleDateFormat是一个以语言环境有关的方式来格式化和解析日期的具体类
- 进行格式化(日期---->文本)、解析(文本---->日期)。
- 常用的时间模式字母
字母 | 日期或者时间 | 示例 |
---|
y | 年 | 2021 | M | 年中月份 | 08 | d | 月中天数 | 10 | H | 1天中小时数(0-23) | 22 | m | 分钟 | 16 | s | 秒 | 59 | S | 毫秒 | 367 |
package classtest06;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestSimpleDateFormat {
public static void main(String[] args) throws Exception{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
Date date = new Date();
String s= sdf.format(date);
System.out.println(s);
String s1="2021-9-15-19-13-01";
Date date1= sdf.parse(s1);
System.out.println(date1);
}
}
System类
package classtest06;
public class TestSystem {
public static void main(String[] args) {
//copyarray
int [] i ={10,10,10,10,10,10,10,10,10};
int [] i1=new int[99];
System.arraycopy(i,0,i1,2,i.length);
for (int s: i1) {
System.out.println(s);
}
//获取毫秒数
System.out.println(System.currentTimeMillis());
//垃圾回收
System.gc();
//退出jvm
System.exit(0);
System.out.println(0000);
}
}
Java集合框架
早在 Java 2 中之前,Java 就提供了特设类。比如:Dictionary, Vector, Stack, 和 Properties 这些类用来存储和操作对象组。
虽然这些类都非常有用,但是它们缺少一个核心的,统一的主题。由于这个原因,使用 Vector 类的方式和使用 Properties 类的方式有着很大不同。
集合框架被设计成要满足以下几个目标。
- 该框架必须是高性能的。基本集合(动态数组,链表,树,哈希表)的实现也必须是高效的。
- 该框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性。
- 对一个集合的扩展和适应必须是简单的。
集合框架是一个用来代表和操纵集合的统一架构。
所有的集合框架都包含如下内容:
-
**接口:**是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象 -
**实现(类):**是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。 -
**算法:**是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。
Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap 等等。
collection是存储一个元素集合
map是key—>value键值对映射(对映射就是a,b两个非空集合,a集合中的元素a,b集合中总有一个唯一与它)
集合接口
集合框架定义了一些接口。本节提供了每个接口的概述:
序号 | 接口描述 |
---|
1 | Collection 接口 Collection 是最基本的集合接口,一个 Collection 代表一组 Object,即 Collection 的元素, Java不提供直接继承自Collection的类,只提供继承于的子接口(如List和set)。Collection 接口存储一组不唯一,无序的对象。 | 2 | List 接口 List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。List 接口存储一组不唯一,有序(插入顺序)的对象。 | 3 | Set Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素。Set 接口存储一组唯一,无序的对象。 | 4 | SortedSet 继承于Set保存有序的集合。 | 5 | Map Map 接口存储一组键值对象,提供key(键)到value(值)的映射。 | 6 | Map.Entry 描述在一个Map中的一个元素(键/值对)。是一个 Map 的内部接口。 | 7 | SortedMap 继承于 Map,使 Key 保持在升序排列。 | 8 | Enumeration 这是一个传统的接口和定义的方法,通过它可以枚举(一次获得一个)对象集合中的元素。这个传统接口已被迭代器取代。 |
Set和List的区别
- \1. Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。
- \2. Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>。
- \3. List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变 <实现类有ArrayList,LinkedList,Vector> 。
集合算法
集合框架定义了几种算法,可用于集合和映射。这些算法被定义为集合类的静态方法。
在尝试比较不兼容的类型时,一些方法能够抛出 ClassCastException异常。当试图修改一个不可修改的集合时,抛出UnsupportedOperationException异常。
集合定义三个静态的变量:EMPTY_SET,EMPTY_LIST,EMPTY_MAP的。这些变量都不可改变。
Java ArrayList
ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。
ArrayList 继承了 AbstractList ,并实现了 List 接口。
ArrayList 类位于 java.util 包中,使用前需要引入它,语法格式如下:
import java.util.ArrayList; // 引入 ArrayList 类
ArrayList<E> objectName =new ArrayList<>(); // 初始化
- E: 泛型数据类型,用于设置 objectName 的数据类型,只能为引用数据类型。
- objectName: 对象名。
ArrayList 是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。
基本用法
package demo08;
import java.util.ArrayList;
public class Demo01 {
public static void main(String[] args) {
ArrayList<String> objects = new ArrayList<String>();
//添加元素
objects.add("Monday");
objects.add("Tuesday");
objects.add("Wednesday");
System.out.println(objects);
//访问元素
System.out.println(objects.get(0));
//修改元素
objects.set(0,"Friday");
System.out.println(objects);
//删除元素
objects.remove(2);
System.out.println(objects);
//计算大小
int i=objects.size();
System.out.println(i);
System.out.println("=============================================");
//迭代数组列表
//for循环
for(i=0;i<objects.size();i++){
System.out.println(objects.get(i));
}
System.out.println("===========================================");
//排序,按照字母顺序排
objects.add("zay");
Collections.sort(objects);
//for -each 迭代
for (String arrays:
objects) {
System.out.println(arrays);
}
}
}
其他引用类型
package demo08;
import java.util.ArrayList;
public class ArrayListDemo {
public static void main(String[] args) {
ArrayList<Integer> integers = new ArrayList<>();
integers.add(200);
integers.add(200);
integers.add(200);
integers.add(200);
integers.add(200);
integers.add(200);
integers.add(200);
integers.add(200);
integers.add(200);
integers.add(200);
integers.add(200);
integers.add(200);
System.out.println(integers);
ArrayList<Double> bytes = new ArrayList<Double>();
bytes.add(200000.0);
System.out.println(bytes);
}
}
Java ArrayList 方法
Java ArrayList 常用方法列表如下:
LinkedList
链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。
链表可分为单向链表和双向链表。
以下情况使用 ArrayList :
- 频繁访问列表中的某一个元素。
- 只需要在列表末尾进行添加和删除元素操作。
以下情况使用 LinkedList :
- 你需要通过循环迭代来访问列表中的某些元素。
- 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。
常用方法案例
package demo08;
import java.util.LinkedList;
public class LinkedListDemo {
public static void main(String[] args) {
//链表
LinkedList<String> sites = new LinkedList<String>();
//add方法
sites.add("Liu");
sites.add("Yue");
sites.add("Yang");
System.out.println(sites);
//addFirst从开头添加
sites.addFirst("NB");
System.out.println(sites);
//addLast方法从结尾添加
sites.addLast("NB");
System.out.println(sites);
//removeFirst方法 从开头移除元素
sites.removeFirst();
System.out.println(sites);
//removeLast方法 从末尾移除元素
sites.removeLast();
System.out.println(sites);
//getFirst获取开头的元素
String s= sites.getFirst();
System.out.println(s);
//getLast获取末尾的元素
String s1=sites.getLast();
System.out.println(s1);
System.out.println("==============================================");
//迭代元素for循环
for (int i = 0; i < sites.size(); i++) {
System.out.println(sites.get(i));
}
}
}
其他常用方法
方法 | 描述 |
---|
public boolean add(E e) | 链表末尾添加元素,返回是否成功,成功为 true,失败为 false。 | public void add(int index, E element) | 向指定位置插入元素。 | public boolean addAll(Collection c) | 将一个集合的所有元素添加到链表后面,返回是否成功,成功为 true,失败为 false。 | public boolean addAll(int index, Collection c) | 将一个集合的所有元素添加到链表的指定位置后面,返回是否成功,成功为 true,失败为 false。 | public void addFirst(E e) | 元素添加到头部。 | public void addLast(E e) | 元素添加到尾部。 | public boolean offer(E e) | 向链表末尾添加元素,返回是否成功,成功为 true,失败为 false。 | public boolean offerFirst(E e) | 头部插入元素,返回是否成功,成功为 true,失败为 false。 | public boolean offerLast(E e) | 尾部插入元素,返回是否成功,成功为 true,失败为 false。 | public void clear() | 清空链表。 | public E removeFirst() | 删除并返回第一个元素。 | public E removeLast() | 删除并返回最后一个元素。 | public boolean remove(Object o) | 删除某一元素,返回是否成功,成功为 true,失败为 false。 | public E remove(int index) | 删除指定位置的元素。 | public E poll() | 删除并返回第一个元素。 | public E remove() | 删除并返回第一个元素。 | public boolean contains(Object o) | 判断是否含有某一元素。 | public E get(int index) | 返回指定位置的元素。 | public E getFirst() | 返回第一个元素。 | public E getLast() | 返回最后一个元素。 | public int indexOf(Object o) | 查找指定元素从前往后第一次出现的索引。 | public int lastIndexOf(Object o) | 查找指定元素最后一次出现的索引。 | public E peek() | 返回第一个元素。 | public E element() | 返回第一个元素。 | public E peekFirst() | 返回头部元素。 | public E peekLast() | 返回尾部元素。 | public E set(int index, E element) | 设置指定位置的元素。 | public Object clone() | 克隆该列表。 | public Iterator descendingIterator() | 返回倒序迭代器。 | public int size() | 返回链表元素个数。 | public ListIterator listIterator(int index) | 返回从指定位置开始到末尾的迭代器。 | public Object[] toArray() | 返回一个由链表元素组成的数组。 | public T[] toArray(T[] a) | 返回一个由链表元素转换类型而成的数组。 |
HashSet
HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。
HashSet 允许有 null 值。
HashSet 是无序的,即不会记录插入的顺序。
HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的。 您必须在多线程访问时显式同步对 HashSet 的并发访问。
HashSet 实现了 Set 接口。
HashSet 中的元素实际上是对象,一些常见的基本类型可以使用它的包装类。
方法使用实例
package demo08;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
public class HashSetDemo {
public static void main(String[] args) {
HashSet<String> sites = new HashSet<>();
//add 添加元素会查重,元素的index会改变
sites.add("Liu");
sites.add("Yue");
sites.add("Yang");
sites.add("Liu");
System.out.println(sites);
//contains 判断元素是否在集合中
boolean n= sites.contains("Liu");
System.out.println(n);
//remove
sites.remove("Liu");
System.out.println(sites);
//clear清楚所有元素
sites.clear();
System.out.println(sites);
System.out.println("=====================================");
new Liu().demo();
}
}
class Liu{
public void demo(){
HashSet<String> sites = new HashSet<>();
sites.add("Liu");
sites.add("Yue");
sites.add("Yang");
sites.add("NB");
sites.add("Plus");
sites.add("Liu");
System.out.println(sites);
ArrayList<Object> sites1 = new ArrayList<>(sites);
for (int i = 0; i <sites1.size() ; i++) {
System.out.println(sites1.get(i));
}
}
}
Java HashMap
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。
HashMap 是无序的,即不会记录插入的顺序。
HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。
HashMap 的 key 与 value 类型可以相同也可以不同,可以是字符串(String)类型的 key 和 value,也可以是整型(Integer)的 key 和字符串(String)类型的 value。
方法实例
package demo08;
import java.util.HashMap;
public class HashMapDemo {
public static void main(String[] args) {
HashMap<String, Integer> sites = new HashMap<String, Integer>();
//put 添加key-value
sites.put("taobao",22);
sites.put("tianmao",223);
sites.put("meituan",224);
sites.put("jingdong",225);
System.out.println(sites);
//size
System.out.println(sites.size());
//remove 移除key -value 可以只写一个参数key
sites.remove("taobao",22);
System.out.println(sites);
//clear
// sites.clear();
//System.out.println(sites);
//get
int i=sites.get("tianmao");
System.out.println(i);
//迭代key
for (String s: sites.keySet()) {
System.out.println(s);
}
//迭代value
for (int v:sites.values()) {
System.out.println(v);
}
}
}
Java Iterator
Java Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法,可用于迭代 ArrayList 和 HashSet 等集合。
package demo08;
import java.util.ArrayList;
import java.util.Iterator;
public class IteratorDemo {
public static void main(String[] args) {
//Iterator迭代器的使用
ArrayList<String> sites = new ArrayList<String>();
sites.add("Liu");
sites.add("Yue");
sites.add("Yang");
sites.add("N");
sites.add("B");
System.out.println(sites);
Iterator<String> iterable= sites.iterator();
while (iterable.hasNext()){
System.out.println(iterable.next());
}
//removetest
new IteratorDemo01().removeTest();
}
}
class IteratorDemo01{
public void removeTest(){
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);
numbers.add(7);
numbers.add(8);
numbers.add(6);
numbers.add(15);
Iterator iterator=numbers.iterator();
while(iterator.hasNext()){
Integer i=(Integer) iterator.next();
if(i<10){
iterator.remove();
System.out.println("del"+"\t"+i);
}
}
System.out.println(numbers);
}
}
Object
Java Object 类是所有类的父类,也就是说 Java 的所有类都继承了 Object,子类可以使用 Object 的所有方法。
Object 类位于 java.lang 包中,编译时会自动导入,我们创建一个类时,如果没有明确继承一个父类,那么它就会自动继承 Object,成为 Object 的子类。
Object 类可以显示继承,也可以隐式继承,以下两种方式时一样的:
显示继承:
public class Runoob extends Object{
}
隐式继承:
public class Runoob {}
类的方法
Java泛型
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
泛型方法
你可以写一个泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。
下面是定义泛型方法的规则:
- 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(在下面例子中的)。
- 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
- 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
- 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像int,double,char的等)。
public class GenericMethodTest{
有界的类型参数:
可能有时候,你会想限制那些被允许传递到一个类型参数的类型种类范围。例如,一个操作数字的方法可能只希望接受Number或者Number子类的实例。这就是有界类型参数的目的。
要声明一个有界的类型参数,首先列出类型参数的名称,后跟extends关键字,最后紧跟它的上界。
下面的例子演示了"extends"如何使用在一般意义上的意思"extends"(类)或者"implements"(接口)。该例子中的泛型方法返回三个可比较对象的最大值。
public class MaximumTest{
泛型类
泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分。
和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。因为他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。
public class Box<T> { private T t; public void add(T t) { this.t = t; } public T get() { return t; } public static void main(String[] args) { Box<Integer> integerBox = new Box<Integer>(); Box<String> stringBox = new Box<String>(); integerBox.add(new Integer(10)); stringBox.add(new String("菜鸟教程")); System.out.printf("整型值为 :%d\n\n", integerBox.get()); System.out.printf("字符串为 :%s\n", stringBox.get()); }}
类型通配符
1、类型通配符一般是使用?代替具体的类型参数。例如 List<?> 在逻辑上是List,List 等所有List<具体类型实参>的父类。
import java.util.*; public class GenericTest { public static void main(String[] args) { List<String> name = new ArrayList<String>(); List<Integer> age = new ArrayList<Integer>(); List<Number> number = new ArrayList<Number>(); name.add("icon"); age.add(18); number.add(314); getData(name); getData(age); getData(number); } public static void getData(List<?> data) { System.out.println("data :" + data.get(0)); }}
Java序列化
[https://www.runoob.com/java/java-serialization.html]:
Java枚举
Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。
Java 枚举类使用 enum 关键字来定义,各个常量使用逗号 , 来分割。
例如定义一个颜色的枚举类。
实例:
package demo06;
public class Demo08 {
//颜色
enum Color{
RED,BLUE,GREEN;
}
public static void main(String[] args) {
{
Color c1 = Color.RED;
System.out.println(c1);
}
Color c2=Color.BLUE;
System.out.println(c2);
}
}
package demo06;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
public class Demo09 {
enum Year{
MONDAY,TUESDAY;
}
public static void main(String[] args) {
Year year=Year.MONDAY;
System.out.println(year);
}
}
每个枚举都是通过 Class 在内部实现的,且所有的枚举值都是 public static final 的。
以上的枚举类 Color 转化在内部类实现
迭代枚举元素
for循环
package demo06;
public class Demo08 {
enum Color{
RED,BLUE,GREEN;
}
public static void main(String[] args) {
for (Color myVar:
Color.values()) {
System.out.println(myVar);
}
}
}
switch迭代
package demo06;
public class Demo08 {
enum Color{
RED,BLUE,GREEN;
}
public static void main(String[] args) {
Color color=Color.BLUE;
switch (color){
case RED:
System.out.println("RED");
break;
case BLUE:
System.out.println("BLUE");
break;
case GREEN:
System.out.println("Green");
break;
}
}
}
value() ,ordinal()和valueOf()方法
enum 定义的枚举类默认继承了 java.lang.Enum 类,并实现了 java.lang.Seriablizable 和 java.lang.Comparable 两个接口。
values(), ordinal() 和 valueOf() 方法位于 java.lang.Enum 类中:
- values() 返回枚举类中所有的值。
- ordinal()方法可以找到每个枚举常量的索引,就像数组索引一样。
- valueOf()方法返回指定字符串值的枚举常量。
实例:
package demo06;
public class Demo08 {
enum Color{
RED,BLUE,GREEN;
}
public static void main(String[] args) {
//value方法
Color [] color=Color.values();
//迭代
for (Color myVar:
color) {
//查看索引
System.out.println(myVar+" "+"at index"+" "+myVar.ordinal());
}
//输出常量值
System.out.println(Color.valueOf("RED"));
}
}
枚举类成员
package demo06;
public class Demo08 {
enum Color{
RED,BLUE,GREEN;
//构造函数
private Color(){
System.out.println("color"+" "+this.toString());
}
//结束之后打印所有的颜色
private void edd( ){
System.out.println("Universal Color");
}
}
public static void main(String[] args) {
Color color1=Color.BLUE;
System.out.println(color1);
color1.edd();
}
}
小结
其实枚举的东西就是一个类
枚举中的方法关键字必须用private
enum Color{
RED{
public String getColor(){//枚举对象实现抽象方法
return "红色";
}
},
GREEN{
public String getColor(){//枚举对象实现抽象方法
return "绿色";
}
},
BLUE{
public String getColor(){//枚举对象实现抽象方法
return "蓝色";
}
};
public abstract String getColor();//定义抽象方法
}
public class Test{
public static void main(String[] args) {
for (Color c:Color.values()){
System.out.print(c.getColor() + "、");
}
}
}
|