自用JavaSE学习笔记
Java是强类型语言*
要求变量的使用要严格符合规定,所有变量都必须先定义后才能使用
基本数据类型
==整数类型==
- byte占1个字符范围:-128-127
- short占2个字符范围:-32768-32767
- int占4个字符范围:-2147483648-2147483647
- long占8个字符范围:-9223372036854775808-9223372036854775807
- ⚠️long类型要在数字后面加个L
==浮点类型==
- float占4个字节
- double占8个字节
- ⚠️float类型要在数字后面加个F
==字符类型==
- char占2个字节
==布尔类型==
- boolean占1位,只有true和false
数据类型扩展
==整数扩展:==
整数扩展: 进制 二进制0b 十进制 八进制0 十六进制0x
public static void main(String[] args) {
//整数扩展: 进制 二进制0b 十进制 八进制0 十六进制0x
int i = 10;
int i2 = 010; //八进制0
int i3 = 0x10; //十六进制0x
System.out.println(i); //输出10
System.out.println(i2); //输出8
System.out.println(i3); //输出16
}
==浮点数扩展:==
浮点数拓展? 银行业务怎么表示?钱
public static void main(String[] args) {
//浮点数拓展? 银行业务怎么表示?钱
//BigDecimal 数学工具类
//float 有限 离散 舍入误差 大约数 接近但不等于
//double
//最好完全《避免》使用浮点数进行比较
//最好完全《避免》使用浮点数进行比较
//最好完全《避免》使用浮点数进行比较
float f=0.1f;
double d = 1.0/10;
System.out.println(f); //输出0.1
System.out.println(d); //输出0.1
System.out.println(f==d); //输出结果false
float d1 = 111111111111F;
float d2 = d1 + 1F;
System.out.println(d1); //输出1.1111111E11
System.out.println(d2); //输出1.1111111E11
System.out.println(d1==d2); //输出结果true
}
==字符扩展:==
public static void main(String[] args) {
char c1 = 'A';
char c2 = '中';
System.out.println(c1);
System.out.println((int)c1); //强制转换 输出65
System.out.println(c2);
System.out.println((int)c2); //强制转换 输出20013
//所有的字符本质还是数字
//编码 Unicode 2字节 0-65536
//U0000 UFFFF char c3 = '\u0061'; //16进制Unicode编码
System.out.println(c3); //输出A
//字符串
String S1 = "hello world";
System.out.println(S1); //输出hello world
}
==转义字符==
Java语言支持一些特殊的转义字符序列
\n 换行 (0x0a)
\r 回车 (0x0d)
\f 换页符(0x0c)
\b 退格 (0x08)
\0 空字符 (0x0)
\s 空格 (0x20)
\t 制表符
\" 双引号
\' 单引号
\\ 反斜杠
\ddd 八进制字符 (ddd)
\uxxxx 16进制Unicode字符 (xxxx)
==布尔值扩展==
public static void main(String[] args) {
boolean b1 = true;
if (b1==true){}
if (b1){} //默认==true
}
什么是字节
==位(bit)==:是计算机内部数据存储的最小单位,110001100是一个八位二进制数。
==**字节(byte)**==:是计算机数据处理的基本单位,习惯上用大写B来表示,
1B(byte,字节)=8bit(位)
==**字符**==:是指计算机中使用的字母、数字、字和符号
- 1bit表示一位
- 1Byte表示一个字节 1B=8b
- 1024KB=1M
- 1024M=1G
由于Java是强类型语言,所以要进行有些运算的时候,需要用到类型转换。
运算中,不同类型的数据先转化成为同一类型,然后进行运算。
强制类型转换
自动类型转换
public static void main(String[] args) {
int i = 128;
byte b = (byte) i; //内存溢出 强制转换 (类型)变量名 高--低
double d = i; //自动转换 高--低
System.out.println(i); //128
System.out.println(b); //-128
System.out.println(d); //128.0
char c = 'a';
int d = c+1;
System.out.println(d); //98
System.out.println((char) d); //b
System.out.println((int) 23.7); //23
System.out.println((int)-45.89F); //-45 精度丢失
}
⚠️注意
- 不能对布尔值进行转换
- 不能把对象类型转换为不相干的类型
- 在把高容量量转换到低容量的时候,强制类型转换
- 转换的时候可能存在内存溢出,或者精度问题
public static void main(String[] args) {
//操作比较大的数字的时候,注意一出问题
//JDK7新特性,数字之间可以用下划线分割
int money =10_0000_0000;
int years =20;
int total =money*years; //,计算的时候溢出了
long total2 =money*years; //默认是int ,转换之前已经存在问题了?
long total3 =money*((long)years); //正确写法
System.out.println(total); //-1474836480
System.out.println(total2); //-1474836480
System.out.println(total3); //20000000000
}
变量
变量是什么:就是可以变化的量
Java是一种强类型语言,每个变量都必须声明其类型。
Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。
⚠️注意事项:
- 每个变量都有类型,类型是基本类型,也可以是引用类型。
- 变量名必须是合法的标识符。
- 变量声明是一条完整的语句,因此每一个声明都必须以分号结束
变量作用域
局部变量
public class Main {
public static void main(String[] args) {
int i = 0; //局部变量
System.out.println(i);
}
}
实例变量
public class Main {
//实例变量:从属于对象
String name = "nannanwu";
public static void main(String[] args) {
//变量类型 变量名字 = new 方法名
Main main = new Main();
System.out.printf(main.name); //输出nannanwu
}
}
类变量
public class Main {
//类变量 static static String name = "nannanwu";
public static void main(String[] args) {
System.out.printf(name); //输出nannanwu
}
}
常量
常量(constant):初始化(initialize)后不能改变的值!不会变动的值
所谓常量可以理解为一种特殊的变量,他的值被设定后,在程序运行过程中不允许被改变。
⚠️常量一般使用大写字符。
public class Main {
static final double PI = 3.14;
//修饰符,不存在先后顺序
//final static double PI = 3.14;
public static void main(String[] args) {
System.out.println(PI); //3.14
}
}
命名规范
- 所以变量、方法、类名:见名知意
- 类成员变量:首字母小写和驼峰原则:monthSalary
- 局部变量:首字母小写和和驼峰原则
- 常量:首字母大写和驼峰原则:MAX_VALUE
- 方法名:首字母小写和驼峰原则:run()
Java基本运算符
++与--
public class Main {
public static void main(String[] args) {
int a = 10;
int c = a++; //a++表示c=a a=a+1 先把a赋值给b 然后a再加1
System.out.println(a); //11
System.out.println(c); //10
a = 10;
int b = ++a; //++a表示b=a+1 先把a再加1 然后a赋值给b
System.out.println(a); //11
System.out.println(b); //11
}
}
逻辑运算
public class Main {
public static void main(String[] args) {
//逻辑运算
//与(and),或(or),非(取反)
boolean a = true;
boolean b= false;
System.out.println((a&&b)); //与运算、false 两个结果都为真,结果才为真
System.out.println((a||b)); //或运算、true 两个结果有一个为真,结果为真
System.out.println(!(a)); //非运算、false 如果是真,则为假,如果是假,则为真,
//短路运算
int c = 5;
boolean d = (c<4)&&(c++<4); //(c<4)已经为假,不执行后续运算 (c++<4)不会计算
System.out.println(d); //false
System.out.println(c); //5
}
}
位运算
public class Main {
public static void main(String[] args) {
/*
A = 0011 1100
B = 0000 1101
----------------------
A&B = 0000 1100 与运算
A|B = 0011 1101 或
A^B = 0011 0001 异或运算
~B = 1111 0010 取反
2*8 = 16 2*2*2*2*2*2*2*2
//效率高
<< *2
>> /2
*/
System.out.println(2<<3); //16
}
}
扩展赋值运算符
public class Main {
public static void main(String[] args) {
int a = 20;
int b = 30;
a+=b; //a=a+b
System.out.println(a); //50
a-=b; //a=a-b
System.out.println(a); //20
//字符串连接符 +,第一个为字符型String,后面的默认执行字符串+
System.out.println(a+b); //50
System.out.println(""+a+b); //2030
System.out.println(a+b+"6"); //506
}
}
三元运算
public class Main {
public static void main(String[] args) {
//三元运算
//x ? y : z
//如果x==true 结果为y 否则为z
int score = 80;
String type = score <60 ?"不及格":"及格";
System.out.println(type); //及格
}
}
Java包机制
- 为了更好的组织类,java提供了包机制来了,用于区别类的命名空间。
- 一般用公司域名倒置作为包名
- 包语言得格式为:
package pkg1[.pkg2[.pkg3…]];
- 为了使用某一个包的成员,我们需要在java程序中明确导入该包。使用“import”语句可以完成此功能
import package1[.package2…].(classname|*);
Java用户交互Scanner
以hasNext的方法接收
package com.nannanwu.www;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("以next的方法接收:");
//判断用户有没有输入字符串
if (scanner.hasNext()){
String str = scanner.next();
System.out.println("输入的内容为:"+str);
}
//关闭scanner
scanner.close();
}
}
以hasNextLine的方法接收
package com.nannanwu.www;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
if (scanner.hasNextLine()){
String str = scanner.nextLine();
System.out.println("输入的数据为" + str);
}
scanner.close();
}
}
求多个数平均值
package com.nannanwu.www;
import java.util.Scanner;
public class scanner_pj {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double sum = 0;
int m = 0;
System.out.println("请输入第1个数字");
while (scanner.hasNextDouble()){
System.out.println("请输入第" + (m+2) +"个数字");
double x =scanner.nextDouble();
m = m + 1;
sum =sum + x;
}
System.out.println(m + "个数和为" + sum);
System.out.println(m + "个数平均值为" + (sum / m));
scanner.close();
}
}
Java if 选择结构
if单选结构
我们很多时候需要判断一个东西是否可行,然后我们才去执行,这样一个过程我们用if语句来表示
输入Hello正确后返回"输入正确"
package com.nannanwu.www;
import java.util.Scanner;
public class if_demo_0 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入Hello");
String s = scanner.nextLine();
//equals:判断字符串是否相等
if (s.equals("Hello")){
System.out.println("输入正确");
}
scanner.close();
}
}
if 双选结构
现在有这样一个需求,输入正确鼓励你,输入失败安慰你
package com.nannanwu.www;
import java.util.Scanner;
public class if_demo {
public static void main(String[] args) {
System.out.println("请输入Hello");
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
//equals:判断字符串是否相等
if (s.equals("Hello")){
System.out.println("你是最棒的╰(*°▽°*)╯");
}else{
System.out.println("加油,下次你会成功的(●'◡'●)");
}
scanner.close();
}
}
if 多选结构
生活中,我们很多时候的选择也不仅仅只有两个,我们需要更多
一个给分数评级的程序
package com.nannanwu.www;
import java.util.Scanner;
public class if_demo2 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入成绩:");
int score = scanner.nextInt();
if (score == 100){
System.out.println("恭喜满分");
} else if (score < 100 && score >= 90) {
System.out.println("A级");
} else if (score < 90 && score >= 80) {
System.out.println("B级");
} else if (score < 80 && score >= 70) {
System.out.println("C级");
} else if (score < 70 && score >= 60) {
System.out.println("D级");
} else if (score < 60 && score >= 0) {
System.out.println("成绩不合格");
} else {
System.out.println("成绩不合法");
}
scanner.close();
}
}
嵌套的if结构
java switch多选结构
所选结构还有一个实现方式就是switch case 语句。
switch case 语句判断一个变量与一系列值中某个值是否相等,每个值为一个分支。
- switch 语句中的变量类型可以是:
- byte、short、int、char
- 从Java SE7开始 switch支持字符串String类型了
- 同时 casa 标签必须为字符串常量或字变量。
package com.nannanwu.www;
public class Switch_demo02 {
public static void main(String[] args) {
String name = "我是傻逼";
switch (name){
case "我是傻逼":
System.out.println("我是傻逼");
break;
case "我是大聪明":
System.out.println("我是大聪明");
break;
case "我是什么":
System.out.println("我是什么");
break;
default:
System.out.println("你是个什么狗屎");
}
}
}
while 循环
-
while循环是最基本的循环,他的结构为:
-
只要表达式为true ,循环就会一直循环下去。
-
我们大多数情况会让循环停下来的,我们需要一个表方式失效的方式来结束循环。
-
少部分情况需要循环一直执行,比如服务器的请求相应监听等。
-
循环条件为true会造成无限循环【死循环】,我们的正常业务编程中应该尽量避免死循环,会影响程序性能,或者造成程序卡死崩溃
输出1-100
package com.nannanwu.www;
public class While_demo01 {
public static void main(String[] args) {
//输出1-100
int i = 0;
while (i < 100){
i++;
System.out.println(i);
}
}
}
计算1+2+3...+100=?
package com.nannanwu.www;
public class While_demo02 {
public static void main(String[] args) {
int i = 0;
int z = 0;
while (i < 100){
i++;
z=z+i;
}
System.out.println(z);
}
}
do whlie循环
- 对于whlie语句而言,如果不满足条件,则不能进入循环。但是我们需要即使不满足调条件,也至少进行一次。
- do ... while 循环和while循环相似,不同的是,do ... while循环至少会循环一次。
- whlie和do...while的区别
- while先判断后执行。do...while先执行后判断!
- do...whlie总是保证循环体会被至少执行一次!这是他们的主要区别。
do whlie计算1+2+3...+100=?
package com.nannanwu.www;
public class Do_while_demo01 {
public static void main(String[] args) {
int i = 0;
int z = 0;
do{
i++;
z=z+i;
}while (i < 100);
System.out.println(z);
}
}
for循环
- for循环使一些循环结构更加简单。
- for循环是支持迭代的一种通用结构,是最有效、最灵活的循环结构
- for循环执行的次数是在执行前就确定的
for循环和while循环输出1-100
package com.nannanwu.www;
public class For_demo01 {
public static void main(String[] args) {
int a = 1; //初始化条件
while (a <= 100){//条件判断
System.out.println(a);//输出
a++;//迭代
}
System.out.println("while循环结束!");
for (int i = 1;i <= 100;i++){
System.out.println(i);
}
System.out.println("for循环结束");
for ( ; ;){
System.out.println("持续输出死循环");
}
}
}
计算0-100之间奇数和偶数的和
package com.nannanwu.www;
public class For_demo02 {
public static void main(String[] args) {
int oddNumber = 0;
int evenNumber = 0;
for (int i = 0; i < 100; i++) {
if (i % 2 != 0){ //%取余运算
oddNumber += i;
}
if (i % 2 == 0){ ////%取余运算
evenNumber += i;
}
}
System.out.println("奇数的和:" + oddNumber);
System.out.println("偶数的和:" + evenNumber);
}
}
输出1-1000能被5整除的数,并且每行输出3个
package com.nannanwu.www;
public class For_demo03 {
public static void main(String[] args) {
int b = 0;
int b1 = 0;
int b2 = 0;
int b3 = 0;
for (int i = 0; i <= 1000; i++) {
if (i % 5 ==0) {
if (b == 2) {
b3 = i;
b++;
}
if (b == 1) {
b2 = i;
b++;
}
if (b == 0) {
b1 = i;
b++;
}
if (b == 3) {
System.out.println(""+ b1 +" " + b2 + " " + b3);
b = 0;
}
}
}
}
}
package com.nannanwu.www;
public class For_demo04 {
public static void main(String[] args) {
int b = 0;
for (int i = 0; i <= 1000; i++) {
if (i % 5 == 0){
System.out.print(i+"\t");
b++;
}
if (b == 3){
System.out.println();
b = 0;
}
}
}
}
打印九九乘法表
package com.nannanwu.www;
public class For_demo05 {
public static void main(String[] args) {
for (int i = 1; i <= 9; i++) {
for (int o = 1; o <= i; o++){
System.out.print(i + "x" + o + "=" + (i*o) + "\t");
}
System.out.println();
}
}
}
增强for循环
- java5引入了一种主要用于数组或集合的增强for循环
- 声明语句:声明新的环境变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等
- 表达式:表达式是要访问的数组名,或者是返回值为数组的方法
输出数组
package com.nannanwu.www;
public class For_demo06 {
public static void main(String[] args) {
int [] num = {10,20,30,40,50};
for (int i = 0; i < 5; i++) {
System.out.println(num [i]);
}
System.out.println("==================");
//遍历数组元素
for (int x:num){
System.out.println(x);
}
}
}
终止
- break在任何循环语句的主要部分,均可以用break控制循环的流程强制退出循环不在执行循环中剩余的语句。(break在switch中也可使用)
break
输出到30强制停止
package com.nannanwu.www;
public class Break_demo01 {
public static void main(String[] args) {
int a = 0;
while (a < 100){
a++;
System.out.println(a);
if (a == 30){
break;
}
}
}
}
continue
- contiune在循环语句中,用于终止某次循环过程,即跳过循环中为执行的语句,接着进行下一次是否执行循环的判定
输出1-100,不输出10的倍数并且换行
package com.nannanwu.www;
public class Continue_deom01 {
public static void main(String[] args) {
int a = 0 ;
while (a < 100){
a++;
if (a % 10 ==0){
System.out.println();
continue;
}
System.out.print(a+" ");
}
}
}
goto关键字
- goto关键字很早就在程序设计语言中出现。尽管goto仍是Java的一个保留字,但并未在语言中得到正式使用;Java没有goto。然而,在break和continue这两个关键字的身上,我们仍然能看出一些goto的影子---带标签的break和continue,
- “标签”是指后面跟一个冒号的标识符,例如: label:
- 对Java来说唯一用到标签的地方是在循环语句之前。而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方。
输出100到150的质数
package com.nannanwu.www;
public class Label_demo01 {
public static void main(String[] args) {
outer:for (int i = 100; i < 150; i++) {
for (int j = 2; j < i; j++){
if (i % j ==0){
continue outer; //跳转到outer标签的位置,不建议使用
}
}
System.out.println(i + "");
}
}
}
for打印三角形
package com.nannanwu.www;
public class Test_demo01 {
public static void main(String[] args) {
//打印三角形 5行
for (int i = 1; i <= 5; i++) {
for (int i1 = 5; i1 >= i; i1--) {
System.out.print(" ");
}
for (int i1 = 1; i1 <= i; i1++) {
System.out.print("6");
}
for (int j = 1; j < i; j++) {
System.out.print(6);
}
System.out.println();
}
}
}
Java方法
- java方法是语句的集合,他们在一起执行一个功能
- 方法是解决一类问题的步骤的有序组合
- 方法包含于类或对象中
- 方法在程序中创建,在其他地方被引用
- 设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成一个功能,这样利于我们后期扩展。
方法的定义
Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法:
- 方法包含一个方法头和一个方法体。下面是一个方法的所有部分:
- 修饰符: 这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
- 返回值类型: 方法可能会返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值,在这种情况下returnValueType是关键字void。
- 方法名: 是方法的实际名称。方法名和参数表共同构成方法签名。
- **参数类型:**参数像是一个占位符,当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
- 形式参数: 在方法调用时用于接收外界输入的数据。
- 实参:调用方法时实际传给方法的数据
- 方法体: 方法体包含具体的语句,定义该方法的功能。
方法调用
- 调用方法:对项名、方法名(实例列表)
- Java支持两种调用方法的方式,根据方法是否返回值来选择
- 当方法返回一个值的时候,方法调用通常被当作一个值。例如:
int larger = max(30, 40);
- 如果方法返回值是void,方法调用一定是一条语句。
System.out.println("Hello");
调用简易加法模块
package method;
public class Demo01 {
//main方法
public static void main(String[] args) {
int sum = add(1, 2);
System.out.println(sum);
}
//加法
public static int add(int a, int b){
return a+b;
}
}
vido调用
package com.nannanwu.www;
public class Do_while_demo01 {
public static void main(String[] args) {
test();
}
public static void test(){
int i = 0;
int z = 0;
do{
i++;
z=z+i;
}while (i < 100);
System.out.println(z);
}
}
调用大小比较输出大的数
package method;
public class Demo02 {
public static void main(String[] args) {
System.out.println(max(6,6));
}
//比大小,输出大的值
public static int max(int a, int b){
int c = 0;
if (a > b){
c = a;
}
if (a < b){
c = b;
}
if (a == b){
c = a;
}
return c;
}
}
方法的重载
-
重载就是在一个类中,有相同的函数名称,但形参不同的函数
-
方法的重载规则
- 方法名名称必须相同。
- 参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)。
- 方法的返回类型可以相同也可以不同。
- 仅仅返回类型不同,不足以成为方法的重载
-
实践理论
- 方法名相同时,编译器会根据调用 方法的参数个数 ,参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,编译器报错
比较小数调用max double
package method;
public class Demo03 {
public static void main(String[] args) {
System.out.println(max(30,6.1));
}
//比大小,输出大的值int
public static int max(int a, int b){
int c = 0;
if (a > b){
c = a;
}
if (a < b){
c = b;
}
if (a == b){
c = a;
}
return c;
}
//比大小,输出大的值double
public static double max(double a, double b){
double c = 0;
if (a > b){
c = a;
}
if (a < b){
c = b;
}
if (a == b){
c = a;
}
return c;
}
}
java命令行穿参
有时候你希望运行一个程序的时候,再传递给他消息。这就要靠传递命令行参数给main()函数实现。
package method;
public class Demo04 {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println("args["+ i + "]:" + args[i]);
}
}
}
进入根目录
cmd java method.Demo04 hhh hhh hhh hhh
输出:
可变参数
- JDK 1.5开始,java支持传递同类型的可变参数给一个方法。
- 在方法声明中,在指定参数类型后面加一个省略号(...)。
- 一个方法中只能指定一个可变参数,他必须是方法的最后一个参数,任何一个普通的参数必须在他之前声明
package method;
public class Demo05 {
public static void main(String[] args) {
Demo05 demo05 = new Demo05();
demo05.test(1);
}
public void test (int... i){
System.out.println(i[0]);
}
}
package com.nannanwu.www;
public class Demo06 {
public static void main(String[] args) {
printMax(54,54,54,54,666,5555,333);
printMax(new double[]{1,2,3,4,5});
}
public static void printMax(double... numbers){
if (numbers.length == 0){
System.out.println("没有参数");
}
double result = numbers[0];
for (int i = 1; i < numbers.length ; i++) {
if (numbers[i] > result){
result = numbers[i];
}
}
System.out.println("最大值:" + result);
}
}
递归 (能不用就不用)
-
A方法调用B方法,我们很容易理解!
-
递归就是A方法调用A方法!就是自己调用自己
-
递归可以用简单的程序解决一些复杂的问题。他通常把一个大型复杂的问题层次转化为一个于原问题相似的规模较小的问题来求解,递归策略只需要少量的程序就可以描述出解体过程所需要的多次重复运算,大大的减少了程序的代码量,递归的能力在于用有限的语句来定义对象的无限集合。
-
递归结构包括两个部分:
- 递归头:什么时候不调用自身方法。如果没有头,则进入死循环。
- 递归体:什么时候需要调用自身方法
递归运算
package method;
public class Demo08 {
public static void main(String[] args) {
System.out.println(f(3));
}
public static int f(int n){
if (n == 1){
return 1;
}else {
return n*f(n-1);
}
}
}
数组的定义
- 数组是相同类型数据的有序集合
- 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
- 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问他们
数组声明于创建
- 首选必须声明是数组变量,才能在程序中使用数组。下面是声明数组变量的方法:
变量类型[] 变量名字 //首选方法
变量类型 变量名字[] //效果相同但不是首选方法
Java语言使用new来创建数组,方法如下:
数组名 = new 类型[数组大小]
声明和创建写在一起
类型[] 数组名 = new 类型[数组大小]
数组的元素是通过索引访问的,数组访问从0开始。
获取数组的长度 arrays.length
数组的基本特点
- 其长度是固定的。数组一旦被创建,他的大小就是不可改变的。
- 其元素必须是相同类型,不允许出现混合类型。
- 数组中的元素可以是任何数据类型,包括基本类型和应用类型
- 数组的变量属引用类型,数组也可以看成是对象,数组中每一个元素相当于该对象的成员变量
- 数组本身就是变量,Java中对象是在堆栈中的,因此数组无论是保存原始类型还是其他对象类型
- 数组本身是在堆栈中的
数组三种初始化
//静态初始化,创建+赋值
int[] a = {1,2,3,4,5,6,7,8};
//动态初始化:包含默认初始化
int[] b = new int[10];
b[0] = 10;
数值的默认初始化
数组是引用类型,他的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐藏初始化
数组的四个基本特点
- 其长度是固定的。数组一旦被创建,他的大小就是不可以改变的
- 其元素必须是相同的类型,不允许出现混合类型。
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型。
- 数组变量属引用类型,数组可以看成是对象,数组中的每个元素相当于该对象的成员变量。
- 数组本身就是对象,Java中对象存在堆栈中,因此数组无论保存原始值还是其他对象类型,数组本身是在堆中的
数组边界
- 下标的合法区间:[0,length-1],如果越界就会报错;
public class Array {
public static void main(String[] args) {
int[] a = new int[2];
System.out.println(a[2]);
}
}
ArrayIndexOutOfBoundsException 数组下标越界
小结:
- 数组是相同数据类型(数据类型可以为任意类型)的有序集合
- 数组也是对象。数组元素相当于对象的成员变量
- 数组长度的确定,不可变的。如果越界,则报错:ArrayIndexOutOfBoundsException
数组的使用
打印全部元素
数组之和
数组最大元素
package com.nannanwu.www;
public class ArrayDemo03 {
public static void main(String[] args) {
int[] arrays = {1,2,3,4,5,5,3,4,7,2,9,100,4,3,2};
// 打印数值全部元素
for (int i = 0; i < arrays.length; i++) {
System.out.println(arrays[i]);
}
System.out.println("==================");
// 全部数组的和
int sun = 0;
for (int i = 0; i < arrays.length; i++) {
sun += arrays[i];
}
System.out.println(sun);
System.out.println("===================");
// 查找最大元素
int max = 0;
for (int i = 0; i < arrays.length; i++) {
if (arrays[i] > max){
max = arrays[i];
}
}
System.out.println(max);
}
}
输出反转后的数组
package com.nannanwu.www;
public class ArrayDemo04 {
public static void main(String[] args) {
int[] array = {1,4,23,2,5,46,6};
Array_printing(Array_inversion(array));
}
//数组反转 Array_inversion
public static int[] Array_inversion(int[] a){
int[] d = new int[a.length];
for (int b = 0,c = a.length - 1; b < a.length; b++,c--) {
d[b] = a[c];
}
return d;
}
//数组打印 Array_printing
public static void Array_printing(int[] a){
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
}
}
多维数组
- 可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组
- 二维数组
int[][] array = new int[3][3];
public class ArrayDemo05 {
public static void main(String[] args) {
int[][] array = {{1,2,3},{4,4,3},{3,3,5},{5,4,4}};
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
System.out.print(array[i][j] + "\s");
}
System.out.print("\n");
}
}
}
数组排序
冒泡排序
package com.nannanwu.www;
import java.util.Arrays;
public class Array_Demo06 {
public static void main(String[] args) {
int[] array = {3, 2, 5, 6, 7, 8, 1};
int[] sort = sort(array);
System.out.println(Arrays.toString(sort));
}
public static int[] sort(int[] array){
int temp;
for (int i = 0; i < array.length - 1; i++) {
for (int j = 0; j < array.length - 1 - i; j++) {
if (array[j+1] < array[j]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
return array;
}
}
稀疏数组
- 当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
- 稀疏数组的处理方式是:
- 记录数组有几行几列
- 把具有不同值的元素和行列及值记录在一个小规模数组时,从而缩小程序的规模
原始数组稀疏数组转换
package com.nannanwu.www;
public class Array_demo08 {
public static void main(String[] args) {
// 创建原始数组11x11
int[][] array1 = new int[16][11];
array1[0][0] = 5;
array1[1][2] = 1;
array1[1][3] = 2;
array1[1][4] = 3;
array1[2][4] = 3;
array1[3][4] = 3;
array1[4][4] = 3;
// 输出原始数组
System.out.println("=======================输出数组:");
for (int[] ints : array1) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
// 输出稀疏数组
int[][] sz = array_sparse(array1);
System.out.println("=======================稀疏数组:");
for (int[] ints : sz) {
for (int i : ints) {
System.out.print(i+" ");
}
System.out.println();
}
// 输出原始数组
System.out.println("稀疏数组转原始数组=============");
for (int[] ints : array_Not_sparse(sz)) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
}
// 二维数组转换为稀疏二维数组
public static int[][] array_sparse(int[][] a){
int c = 0;
// 获取有几个有效值
for (int[] ints : a) {
for (int anInt : ints) {
if (anInt != 0) {
c++;
}
}
}
int[][] b = new int[c+1][3];
b[0][0] = a.length;
b[0][1] = a[0].length;
b[0][2] = c;
int d = 1;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
if (a[i][j] !=0){
b[d][0] = i;
b[d][1] = j;
b[d][2] = a[i][j];
d++;
}
}
}
return b;
}
// 稀疏数组转二维数组
public static int[][] array_Not_sparse(int[][] a){
int[][] b = new int[a[0][0]][a[0][1]];
for (int i = 0; i < a[0][2]; i++) {
b[a[i+1][0]][a[i+1][1]] = a[i+1][2];
}
return b;
}
}
面向对象
Java的核心思想就是oop
面向过程&面向对象
面向过程思想
- 步骤清晰简单,第一步做什么、第二部做什么......
- 面对过程适合处理一些简单的问题
面向对象思想
- 物以类聚,分类的思想模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对分类下的细节进行面向过程的思索。
- 面对对象适合处理复杂的问题,适合处理需要多人协作的问题!
对于描述复杂的事物,为例从宏观上把握,从整体上合理分析,我们需要使用面向对象的的思路来分析整个系统。但是具体到微观,仍然需要面向过程的思路去处理!
什么是面向对象编程
- 面向对象编程(Object-Oriented Programming,OOP)
- 面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据。
- 抽象
- 三大特征:
- 封装
- 继承
- 多态
- 从认识论的角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
- 从代码运行的角度考虑是先有类后有对象。类是对象的模板。
类与对象的关系
- 类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。
- 动物、植物、手机、电脑......
- Person类、Pet类、Car类等,这些类都是用来描述/定义某一类具体事物应该具备的特点和行为
- 对象是抽象概念的具体实例
- 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。
- 能够体现出特点,展现出功能的具体的实例,二不是一个抽象的概念。
创建与初始化对象
- 使用new关键字创建对象
- 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构建器的调用。
- 类的构建器也称为构建方法,是在进行创建对象的时候必须要调用的。并且构建器有以下两个特点:
- 必须和类的名字相同
- 必须没有返回类型,也不能写void
- 构建器必须要掌握
package com.oop.Demo02;
//学生类
public class Student {
// 属性:字段
String name;
int age;
// 方法
public void study(){
System.out.println(this.name + "在学习");
}
}
/*
//一个项目只应该存在一个main方法
public class Application {
public static void main(String[] args) {
// 类:抽象化,实例化
// 类实例化后会返会一个自己的对象;
// student对象就是一个Student类的具体实例!
Student xiaoming = new Student();
Student xiaohong = new Student();
xiaoming.name = "小明";
xiaoming.age = 3;
xiaohong.name = "小红";
xiaohong.age = 6;
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
System.out.println(xiaohong.name);
System.out.println(xiaohong.age);
}
}
*/
构造器
package com.oop.demo02;
//java --->class
public class Person {
//一个类即使什么都不屑,它也会存在一个方法
//显示的定义构造器
String name;
//实例化初始值
//1,使用new关键字,本质是在调用构建器
//2,用来初始化值
public Person(){
this.name = "nannanwu";
}
//有参构造:一旦定义了有参构造,无参亏必须显示定义
public Person(String name){
this.name = name;
}
/*
public static void main(String[] args) {
// new实例化了一个对象
Person person = new Person();
System.out.println(person.name);
}
构造器:
1.和类名相同
2.没有返回值
作用:
1.new本质在调用构建方法
2.初始化对象的值
注意点:
1.定义了有参后,如果想使用无参构造,显示的定义一个无参构造
Alt + Insert
*/
}
小结
1.类与对象
- 类是一个模板:抽象,对象是一个具体的实例
2.方法
- 定义、调用!
3.对应的引用
- 引用类型:基本类型(8)
- 对象是通过引用来操作的:栈--> 堆
4.属性:字段Field成员变量
- 默认化初始值:-
- 数学:0 0.0
- char: u0000
- boolean: false
- 引用: null
修饰符 属性类型 属性名 = 属性值!
5.对象的创建和使用
- 必须使用new 关键字创建对象,构造器 Person nannanwu = new Person();
- 对象的属性 nannanwu.name
- 对象的方法 nannanwu.sleep()
6.类:
- 静态的属性 属性
- 动态的行为 方法
封装、继承、多态
封装
- 该露的露,该藏的藏
- 我们程序设计要追求"高内聚,低耦合"。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量方法给外部使用。
- 封装(数据的隐藏)
- 通常,我们应该禁止直接访问一个对象中数据的实际表示,而通过操作接口来访问,这称为信息隐藏。
- 记住这句话就够了:属性私有,get/set
package com.oop.demo04;
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("nannanwu");
s1.setAge(130);
System.out.println(s1.getName());
System.out.println(s1.getAge());
}
}
package com.oop.demo04;
public class Student {
/*
1.提高程序的安全性,保护数据
2.隐藏代码实现细节
3.同一接口
4.系统可维护
*/
private String name; //名字
private int id; //学号
private char sex; //性别
private int age; //年龄
public int getAge() {
return age;
}
public void setAge(int age) {
if (age < 120 && age > 0){
this.age = age;
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
}
继承
- 继承的本质是对一批类的抽象,从而实现对现实世间更好的建模
- extands的意思是"扩展"。子类是父类的扩展。
- JAVA中只有单继承,没有多继承!
- 继承是类和类的一种关系。除此之外,类和类的关系还有依赖、组合、聚合等。
- 继承关系有两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
- 子类和父类之间,从意义上来讲应该具有”is a“的关系。
- objec类
- super this
- 方法重写
super注意点
- super 调用父类的构造方法,必须在构造方法的第一个
- super 必须只能出现在子类的方法或者构造方法中
- super和this不能同时调用方法构造!
VS this:
代表的对象不同
- this:本身调用者这个对象
- super:代表父类对象应用
前提
- this:没有继承也能使用
- super:只能在继承条件才可以使用
构造方法
- this();本类构造
- super(); 父类构造!
方法重写
重写:需要有继承关系,子类重写父类的方法!
- 方法名必须相同
- 参数列表必须相同
- 参数符:范围可以扩大但不能缩小:public>Protected>Default>private
- 抛出的异常:范围,可以被缩小,但不能扩大:ClassNotFoundException -->Exception(大)
重写,子类的方法和父类必要一致;方法体不同!
为什么需要重写:
1.父类的功能,子类不一定需要,或者不一定被满足!
多态
-
动态编译:类型:可扩展
-
即同一方法可以根据发送对象的不同而采用多种不同的行为方式。
-
一个对象的实际类型是确定的,但可以指向对象的引用类型有很多
-
多态存在的条件
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
-
注意:多态是方法的多态,属性没有多态。
-
instanceof(类型转换)引用类型,判断一个对象是是什么类型
多态注意事项:
- 多态是方法的多态,属性没有多态
- 父类和子类,有联系 类型转换异常! ClassCastException!
- 存在条件:继承关系,方法需要重写,父类引用指向子类对象!Father f1 = new Son( );
无法多态的
- static 方法,属于类,它不属于实例
- final 常量;
- private 方法;
抽象类
- abstract修饰符刻意用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象的方法;如果修饰符,那么就是抽象类。
- 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
- 抽象类,不能使用new关键字来创建对象,它是用来让子类继承的
- 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的
- 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类
package com.oop.domo09;
//abstract 抽象类:类 extends:单继承~ (接口可多集成)
public abstract class Action {
//约束~有人帮我们实现~
//abstract,抽象方法,只有方法名字,没有方法实现!
public abstract void doSmething();
//1.不能new这个抽象类,只能靠子类去实现它;约束!
//2。抽象类中可以写普通的方法~
//3.抽象方法必须在抽象类中
//抽象的抽象:约束~
}
package com.oop.domo09;
public class A extends Action {
@Override
public void doSmething() {
}
}
接口
- 普通类:只有具体实现
- 抽象类:具体实现和规范(抽象方法)
- 接口:只有规范!自己无法些方法~专业的约束!约束和实现分离:面向接口编程
- 接口就是规范,定义的是一组规则,体现了现实世界中”如果你是...则必须能...“的思想。如果你是天使则必需能飞。如果你是汽车,则必须能跑。如果你是好人,则必须干掉坏人;如果你是坏人,则必须欺负好人。
- 接口的本质就是契约,就像我们人间的法律一样。制定好大家都遵守。
- oo的精髓,是对对象的抽象,最能体现这一点的就是接口。为什吗我们讨论设计 模式都只针对具备了抽象能力的语言(比如c++ java c#等) 就是因为设计模式所研究的,实际上就是如何合理的去抽象
声明类的关键字是class,声明接口的关键字是interface
作用:
- 约束
- 定义一些方法,让不同的人实现~ 10 ---> 1
- public static final
- public abstract
- 接口不能被实例化~,接口中没有构造方法~
- implements可以实现多个接口
- 必须要重写接口中的方法~
异常机制
- 实际工作中,遇到的情况不可能是非常完美的。比如:你写的某个模块,用户输入不一定符合你的要求,你的程序打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据库可能是空的。我们的程序再跑着,内存或硬盘可能满了。等等
- 软件程序在运行中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是:Excption,意识是例外。这些例外情况狂,或者叫异常,怎么让我们写的程序合理处理,而不至于崩溃。
- 异常指针程序运行中出现的不期而至的各种状况,如:找不到文件、网络连接失败、非法参数等。
- 异常发生在程序运行期间,它影响了正常程序执行流程。
简单分类
- 要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:
- 检查性异常:最具代表性的检查性异常是用户错误或问题引起的异常,这是程序无法遇见的。例如打开一个不存在的文件时,一个异常就发生了,这些异常不能被简单的忽略。
- 运行时异常Exception:运行时异常是肯能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
- 错误ERROR:错位u不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略,当栈溢出时,一个错误就发生了,他们在编译时也检查不到的。
异常体系结构
- Java把异常当作对象来处理,并定义一个基于java.lang.Throwable作为所有异常的超类。
- 在Java API中已经定义了许多异常类,这些异常分为两大类,错误Error和异常Exception。
Error
- Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
- Java虚拟机运行错误(Virtual MachineError),当JVM不在有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止;
- 还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、连接错误(LinkageError)。这些错误是不检查的,因为他们在应用程序的控制和处理能力之外,而且绝大数是程序运行时不允许出现的情况。
Exception
- 在Exception分支中有一个重要的子类RuntimeException(运行时异常)
- ArrayIndexOutOfBoundsException(数组下标越界)
- NullPointerException(空指针异常)
- ArithmeticException (算数异常)
- MissingResourceException (丢失资源)
- ClassNotFoundException (找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
这些错误异常一般是有程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;
Error和Exception的区别:Error通常是灾难性的致命错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。
抛出异常和捕获异常
- 异常处理五个关键字
- try、catch、finally、throw、throws
public static void main(String[] args) {
int a = 1;
int b = 0;
if (b == 0){
//throw 主动抛出异常
throw new ArithmeticException();
}
try {
System.out.println(a/b);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
}
}
自定义异常
- 使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需继承Exception类即可。
- 在程序中使用自定义异常类,大体可以分为以下几个步骤:
- 创建自定义异常类
- 在方法中通过throw关键字抛出异常对象。
- 如果在当前抛出方法中处理异常,可以使用try-cath语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
- 在出现异常方法的调用者中捕获并处理异常。