Java
Java基础
注释、标识符、关键字
注释
-
平时我们编写代码,在代码量比较少的时候,我们还可以看懂自己写的,但是当项目结构一旦复杂起来,我们就需要用到注释了。
-
注释并不会被执行,是给我们写代码的人看的
-
书写注释是一个非常好的习惯
-
平时写代码一定要注意规范。
-
Java中的注释有三种:
- 单行注释 //
- 多行注释 /* */
- 文档注释 /** */
// _ooOoo_ // o8888888o // 88" . "88 // (| -_- |) // O\ = /O // ____/`---'\____ // . ' \\| |// `. // / \\||| : |||// \ // / _||||| -:- |||||- \ // | | \\\ - /// | | // | \_| ''\---/'' | | // \ .-\__ `-` ___/-. / // ___`. .' /--.--\ `. . __ // ."" '< `.___\_<|>_/___.' >'"". // | | : `- \`.;`\ _ /`;.`/ - ` : | | // \ \ `-. \_ __\ /__ _/ .-` / / // ======`-.____`-.___\_____/___.-`____.-'====== // `=---=' // // ............................................. // 佛祖保佑 永无BUG
标识符
Java 所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。
-
所有的标识符都应该以字母(A-Z或者a-z),美元符($)、或者下划线(_)开始
-
首字符之后可以是字母(A-Z 或者 a-z),美元符($)、下划线(_)或数字的任何字符组合
-
不能使用关键字作为变量名或方法名。
-
标识符是大小写敏感的
-
合法标识符举例:age、$salary、_value、__1_value
-
非法标识符举例: 123abc、-salary、#abc
public static void main(String[] args){ String Hello = "hello"; System.out.println(Hello); }
可以使用中文命名,但是一般不建议这样去使用,也不建议使用拼音,很Low
关键字
Java关键字类别 | Java关键字 | 关键字含义 |
---|---|---|
访问控制 | private | 一种访问控制方式:私用模式,访问控制修饰符,可以应用于类、方法或字段(在类中声明的变量) |
访问控制 | protected | 一种访问控制方式:保护模式,可以应用于类、方法或字段(在类中声明的变量)的访问控制修饰符 |
访问控制 | public | 一种访问控制方式:共用模式,可以应用于类、方法或字段(在类中声明的变量)的访问控制修饰符。 |
类、方法和变量修饰符 | abstract | 表明类或者成员方法具有抽象属性,用于修改类或方法 |
类、方法和变量修饰符 | class | 声明一个类,用来声明新的Java类 |
类、方法和变量修饰符 | extends | 表明一个类型是另一个类型的子类型。对于类,可以是另一个类或者抽象类;对于接口,可以是另一个接口 |
类、方法和变量修饰符 | final | 用来说明最终属性,表明一个类不能派生出子类,或者成员方法不能被覆盖,或者成员域的值不能被改变,用来定义常量 |
类、方法和变量修饰符 | implements | 表明一个类实现了给定的接口 |
类、方法和变量修饰符 | interface | 接口 |
类、方法和变量修饰符 | native | 用来声明一个方法是由与计算机相关的语言(如C/C++/FORTRAN语言)实现的 |
类、方法和变量修饰符 | new | 用来创建新实例对象 |
类、方法和变量修饰符 | static | 表明具有静态属性 |
类、方法和变量修饰符 | strictfp | 用来声明FP_strict(单精度或双精度浮点数)表达式遵循IEEE 754算术规范 |
类、方法和变量修饰符 | synchronized | 表明一段代码需要同步执行 |
类、方法和变量修饰符 | transient | 声明不用序列化的成员域 |
类、方法和变量修饰符 | volatile | 表明两个或者多个变量必须同步地发生变化 |
程序控制 | break | 提前跳出一个块 |
程序控制 | continue | 回到一个块的开始处 |
程序控制 | return | 从成员方法中返回数据 |
程序控制 | do | 用在do-while循环结构中 |
程序控制 | while | 用在循环结构中 |
程序控制 | if | 条件语句的引导词 |
程序控制 | else | 用在条件语句中,表明当条件不成立时的分支 |
程序控制 | for | 一种循环结构的引导词 |
程序控制 | instanceof | 用来测试一个对象是否是指定类型的实例对象 |
程序控制 | switch | 分支语句结构的引导词 |
程序控制 | case | 用在switch语句之中,表示其中的一个分支 |
程序控制 | default | 默认,例如:用在switch语句中,表明一个默认的分支。Java8 中也作用于声明接口函数的默认实现 |
错误处理 | try | 尝试一个可能抛出异常的程序块 |
错误处理 | catch | 用在异常处理中,用来捕捉异常 |
错误处理 | throw | 抛出一个异常 |
错误处理 | throws | 声明在当前定义的成员方法中所有需要抛出的异常 |
包相关 | import | 表明要访问指定的类或包 |
包相关 | package | 包 |
基本类型 | boolean | 基本数据类型之一,声明布尔类型的关键字 |
基本类型 | byte | 基本数据类型之一,字节类型 |
基本类型 | char | 基本数据类型之一,字符类型 |
基本类型 | double | 基本数据类型之一,双精度浮点数类型 |
基本类型 | float | 基本数据类型之一,单精度浮点数类型 |
基本类型 | int | 基本数据类型之一,整数类型 |
基本类型 | long | 基本数据类型之一,长整数类型 |
基本类型 | short | 基本数据类型之一,短整数类型 |
基本类型 | null | 空,表示无值,不能将null赋给原始类型(byte、short、int、long、char、float、double、boolean)变量 |
基本类型 | true | 真,boolean变量的两个合法值中的一个 |
基本类型 | false | 假,boolean变量的两个合法值之一 |
变量引用 | super | 表明当前对象的父类型的引用或者父类型的构造方法 |
变量引用 | this | 指向当前实例对象的引用,用于引用当前实例 |
变量引用 | void | 声明当前成员方法没有返回值,void可以用作方法的返回类型,以指示该方法不返回值 |
保留字 | goto | 保留关键字,没有具体含义 |
保留字 | const | 保留关键字,没有具体含义,是一个类型修饰符,使用const声明的对象不能更新 |
数据类型
-
强类型语言
- 要求变量的使用要严格符合规定,所有变量都必须先定义后才能使用
-
弱类型语言
-
Java的数据类型分为两大类
- 基本类型(primitive type)
- 引用类型(reference type)
-
八大基本数据类型
- byte,short,int,long,float,char,boolean
public class HelloWorld {
public static void main(String[] args) {
//单行注释
//输出一个HelloWorld!
System.out.println("HelloWorld!");
/*多行注释
多行注释*/
//JavaDoc:文档注释
/**
*
*
*/
String Ahello = "helo";
String hello = "hello";
String $hello = "hello";
String _hello = "hello";
String _1 = "hello";
//String class = "hello";
// string 1heLLo = "hello";
// string #heLLo = "hello";
// string *heLLo = "hello";
//大小写十分敏感
String Man = "man";
//String Man = "man";
String man = "man";
//String man = "man";
//八大基本数据类型
// 整数
int num1 = 10;
// 最常用
byte num2 = 20;
short num3 = 30;
long num4 = 30L;//Long类型要在数字后面加入L
//小数:浮点数
float num5 = 50.1F;//LfLoat类型要在数字后面加个F
double num6 = 3.141592653589793238462643;
//字符
char name = '国';
//字符串,String不是关键字,类
//string nameq = "秦疆";
//布尔值:是非
boolean flag = true;
//booLean fLag = faLse;
//整数拓展:进制 二进制0b 十进制 八进制0 十六进制0x
int i = 10;
int i2 = 010;//八进制的 10 逢8进一
int i3 = 0x10; //十六进制 的 10 逢16进1 0 ~9 A ~F 16
System.out.println("========================");
System.out.println(i);
System.out.println(i2);
System.out.println(i3);
System.out.println("========================");
//浮点数拓展
//fLoat 有限 离散 舍入误差 大约 接近但不等于
//double
//最好完全使用浮点数进行比较
//最好完全使用浮点数进行比较
//最好完全使用浮点数进行比较
float f = 0.1f; //0.1
double d = 1.0/10;//0.1
System.out.println(f==d); //faLse
float d1 = 231312312312313f;
float d2 = d1 + 1;
System.out.println(d1==d2);//true
//字符拓展
//====================
System.out.println("=============================");
char c1 = 'A';
char c2 = '中';
System.out.println(c1);
System.out.println((int)c1);//强制换行
System.out.println(c2);
System.out.println((int)c2);//强制换行
//所有的字符本质还是数字
//编码 Unicode 表:97=a 2字节 0 - 65536 Excel 2 16 = 65536
//U0000 UFFFF
char c3 = '\u0061';
System.out.println(c3);//a
//转义字符
// \t 制表符
// \n 换行
// .....
System.out.println("Hello\nWorld");
String sa = new String( "hello world");
String sb = new String( "hello world");
System.out.println(sa==sb);
String sc = "hello world";
String sd = "hello world";
System.out.println(sc==sd);
//对象 从内存分析
//布尔值扩展
boolean flag1 = true;
if (flag1==true){} //新手
if (flag1){} //老手
//Less is More! 代码要精简易读
}
}
字节
- 位 (bit): 是计算机 内部数据 储存的最小单位, 11001100是一个八位二进制数。
- 字节(byte):是计算中 数据处理的基本单位,习惯上用大写 B 来表示,
- 1B (byte,字节) = 8bit(位)
- 字符: 是指计算机中使用的字母、数字、字和符号
- 1bit表示1位
- 1Byte表示一个字节 1B=8b
- 1024B=1KB
- 1024KB=1M
- 1024M=1G
类型转换(cast)
-
由于Java是强类型语言 所以要进行有些运算的时候的,需要用到类型转换。
低----------------------------------------------------------->高
byte->short->char-> int -> long-> float -> double -
运算中,不同类型的数据先转化为同一类型,然后进行运算。
-
强制类型转换
-
自动类型转换
public class HelloWorld {
public static void main(String[] args) {
int i = 128;
//强制转换(类型)变量名 高--低
byte b = (byte) i;//内存溢出
//自动转换 低--高
double c = i;
System.out.println(i);
System.out.println(b);
System.out.println(c);
/*
注意点:
1.不能对布尔值进行转换
2.不能把对象类型转换为不相干的类型
3.在把高容量转换到低容量的时候,强制转换
4.转换的时候可能存在内存溢出,或者精度问题!
*/
System.out.println("======================");
System.out.println((int) 23.7);
System.out.println((int) -45.89f);
System.out.println("======================");
char d = 'a';
int e = d + 1;
System.out.println(e);
System.out.println((char) e);
//操作比较大的数的时候,注意溢出问题
//JDK7新特性,数字之间可以用下划线分割
System.out.println("======================");
int money = 10_0000_0000;
int years = 20;
int total = money*years ; //-1474836480 ,计算的时候溢出了
long total2 = money*years;//默认是int,转换之前已经存在问题了
long total3 = money*((long)years);//先把一个数转换为Long
System.out.println(total);
System.out.println(total2);
System.out.println(total3);
}
}
变量、常量
-
变量是什么: 就是可以变化的量!
-
Java是一种强类型语言,每个变量都必须声明其类型。
-
Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。
type varName [=value] [{,varName[=value]}] ; //数据类型 变量名 =值;可以使用逗号隔开来声明多个同类型变量。
-
注意事项:
-
每个变量都有类型,类型可以是基本类型,也可以是引用类型。
-
变量名必须是合法的标识符。
-
变量声明是一条完整的语句,因此每一个声明都必须以分号结束
-
变量作用域
-
类变量
-
实例变量
-
局部变量
public class HelloWorld { static int allClicks = 0;//类变量 String str = "hello world";//实例变量 public static void main(String[] args) { } public void method() { int i = 0; // 局部变量 } }
public class HelloWorld {
//类变量 static
static double salary = 2500;
//属性:变量
//实例变量:从属于对象;如果不自行初始化,这个类型的默认值0 0.0
//布尔值:默认是faLse
//除了基本类型,其余的默认值都是nuLL;
String name;
int age;
//main方法
public static void main(String[] args) {
//局部变量;必须声明和初始化值
int i = 10;
System.out.println(i);
//变量类型 变量名字 = new HelloWorld();
HelloWorld hello = new HelloWorld();
System.out.println(hello.age);
System.out.println(hello.name);
//类变量 static
System.out.println(salary);
}
//其他方法
public void add() {
}
}
-
常量
-
常量(Constant):初始化(initialize)后不能再改变值!不会变动的值。
-
所谓常量可以理解成一种特殊的变量,它的值被设定后,在程序运行过程中不允许被改变。
final 常量名=值;
final double PI=3.14; -
常量名一般使用大写字符。
-
//修饰符,不存在先后顺序
static final double PI = 3.14;
public static void main(String[] args) {
System.out.println(PI);
}
变量的命名规范
- 所有变量、方法、类名:见名知意
- 类成员变量: 首字小写和驼峰原则:monthSalary,除了第一个单词以外,后面的单词首字母大写 lastname lastName
- 局部变量:首字母小写和驼峰原则
- 常量:大写字母和下划线:MAX_VALUE
- 类名:首字母大写和驼峰原则: Man, GoodMan
- 方法名: 首字母小写和驼峰原则: run(),runRun()
运算符
- Java 语言支持如下运算符:
- 算术运算符: +,-, *, / %,++,–
- 赋值运算符: =
- 关系运算符: >,<,<=, ==, != instanceof
- 逻辑运算符: &&,ll,!
- 位运算符: &,| ^,~, >>,<<,>>>(了解!!!)
- 条件运算符: ?:
- 扩展赋值运算符: +=, -=, *=, /=
// 与(and) 或(or) 非(取反)
boolean a = true;
boolean b = false;
System.out.println("a && b: " + (b && a));//逻辑与运算:两个变量都为真,结果才为true
System.out.println("a ll b:" + (a||b));//逻辑或运算:两个变量有一个为真,则结果才为true
System.out.println("! (a && b):" + !(a && b));//如果是真,则变为假,如果是假则变为真
//短路运算
int c = 5;
boolean d = (c < 4) && (c++ < 4);
System.out.println(d);
System.out.println(c);
-------------------------------------------
/*
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
0000 0000 0
0000 0001 1
0000 0010 2
0000 0011 3
0000 0100 4
0000 1000 8
0001 0000 16
*/
System.out.println(2 << 3);
---------------------------------------------
int a = 10;
int b = 20;
a += b; //a = a+b
a -= b; //a = a-b
System.out.println(a);
//字符串连接符 + , string
System.out.println("" + a + b);
System.out.println(a + b + "");
-------------------------------------------
//三元运算符
// x ? y : z
//如果x==true,则结果为y,否则结果为z
int score = 50;
String type = score <60 ?"不及格":"及格";//必须掌握
// if
System.out.println(type);
包机制、JavaDoc
-
为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。
-
包语句的语法格式为:
package pkg1[ . pkg2[. pkg3…]];
-
一般利用公司域名倒置作为包名; www.baidu.com com.baidu.www
-
为了能够使用某一个包的成员,我们需要在 Java 程序中明确导入该包。使用“import" 语句可
完成此功能import package1[ .package2…].(classname|*);
-
javadoc命令是用来生成自己API文档的
-
参数信息
- @author 作者名
- @version 版本号
- @since 指明需要最早使用的jdk版本
- @param 参数名
- @return 返回值情况
- @throws 异常抛出情况
[jdk帮助文档](在线文档-jdk-zh (oschina.net))
/**
*@author xzzs0507
*@version 1.0
*@since 1.8
*
*/
public class Doc {
String name;
/**
*@author xzzs0507
*@param name
*@return
*@throws Exception
*/
public String test(String name) throws Exception {
return name;
}
//我是通过命令行 javadoc 参数 Java文件
//作业:学会查找使用IDEA生产 JavaDoc文档! 面向百度编程!
}
Java流程控制
Scanner对象
-
之前我们学的基本语法中我们并没有实现程序和人的交互,但是Java给我们提供了这样一个工具类,我们可以获取用户的输入java.util.Scanner是Java5 的新特征,我们可以通过Scanner 类来获取用户的输入。
-
基本语法:
Scanner s = new Scanner(System.in);
-
通过Scanner类的next()与 nextLine() 方法获取输入的字符串,在读取前我们一般需要使用hasNext()与hasNextLine()判断是否还有输入的数据。
next():
- 一定要读取到有效字符后才可以结束输入。
- 对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。
- 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
- next()不能得到带有空格的字符串。
nextLine():
- 以Enter为结束符,也就是说 nextLine() 法返回的是输入回车之前的所有字符。
- 可以获得空白。
public static void main(String[] args) {
// //Hello World!
// //创建一个扫描器对象,用于接收键盘数据
// Scanner scanner = new Scanner(System.in);
// System.out.println("使用next方式接收:");
// //判断用户有没有输入字符串
// if (scanner.hasNext()) {
// //使用next方式接收
// String str = scanner.next();
// System.out.println("输出的内容为:" + str);
// }
// //凡是短于IO流的类如果不关闭会一直占用资源.要养成好习惯用完就关掉
// scanner.close();
//Hello World!
//从键盘接收数据
Scanner scanner2 = new Scanner(System.in);
System.out.println("使用nextLine方式接收:");
// 判断是否还有输入
if (scanner2.hasNextLine()) {
String str = scanner2.nextLine();
System.out.println("输出的内容为:" + str);
}
scanner2.close();
}
//我们可以输入多个数字,并求其总和与平均数,每输入一个数字用回车确认,通过输入非数字来结束输入并输出执行结果:
Scanner scanner = new Scanner(System.in);
//和
double sum = 0;
//计算输入了多少个数字
int m = 0;
//通过新环判断是否还有输入,并在里面对每一次进行求和和统计
while (scanner.hasNextDouble()) {
double x = scanner.nextDouble();
m = m + 1; //m++
sum = sum + x;
System.out.println("你输入了第"+m+"个数据,然后当前结果sum="+sum);
}
System.out.println(m + "个数的和为" + sum);
System.out.println(m + "个数的平均值是" + (sum / m));
scanner.close();
顺序结构
- JAVA的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行。
- 顺序结构是最简单的算法结构。
- 语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法结构。
选择结构
if单选择结构
-
我们很多时候需要去判断一个东西是否可行,然后我们才去执行,这样一个过程在程序中用if语句来表示
语法: if(布尔表达式){ //如果布尔表达式为true将执行的语句 }
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入内容:");
String s = scanner.nextLine();
//equats:判断字符申是否相等
if (s.equals("Hello")) {
System.out.println(s);
}
System.out.println("End");
scanner.close();
}
if双选择结构
那现在有个需求,公司要收购一个软件,成功了,给人支付100万元,失败了,自己找人开发。这样的需求用一个if就搞不定了,我们需要有两个判断,需要一个双选择结构,所以就有了if-else结构。
语法:
if(布尔表达式){
//如果布尔表达式的值为true
}else{
//如果布尔表达式的值为false
}
if多选择结构
我们发现刚才的代码不符合实际情况,真实的情况还可能存在ABCD,存在区间多级判断。比如90-100就是A,80-90就是B.等等,在生活中我们很多时候的选择也不仅只有两个,所以我们需要一个多选择结构来处理这类问题!
语法:
if(布尔表达式 1){
//如果布尔表达式 1的值为true执行代码
}else if(布尔表达式2){
//如果布尔表达式 2的值为true执行代码
}else if(布尔表达式3){
//如果布尔表达式3的值为true执行代码
}else {
//如果以上布尔表达式都不为true执行代码
}
public static void main(String[] args) {
//考试分数大于60就是及格,小于60分就不及格。
Scanner scanner = new Scanner(System.in);
/*
if 语句至多有 1 个 else 语句,else 语句在所有的 else if 语句之后。
if 语句可以有若干个 else if 语句:它们必须在 else 语句之前。
一旦其中一个 else if 语句检测为 true,其他的 else if 以及 else 语句都将跳过执行。
*/
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结构
使用嵌套的 if…else 语句是合法的。也就是说你可以在另一个if或者else if语句中使用if或者 else if 语句。你可以像if 语句一样嵌套 else if…else。
语法:
if(布尔表达式 1){
如果布尔表达式 1的值为true执行代码
if(布尔表达式 2){
如果布尔表达式 2的值为true执行代码
}
}
switch多选择结构
-
多选择结构还有一个实现方式就是switch case 语句。
-
switch case 语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支。
-
switch 语句中的变量类型可以是:
- byte、short、int或者 char。
- 从Java SE7 开始,switch支持字符串String类型了
- 同时case标签必须为字符串常量或字面量。
switch(expression){
case value :
//语句
break;//可选
case value :
//语句
break;//可选
//你可以有任意数量的case语句
default : //可选
//语句
}
public static void main(String[] args) {
//case穿透 //switch 匹配一个具体的值
char grade = 'C';
switch (grade) {
case 'A':
System.out.println("优秀");
break;//可选
case 'B':
System.out.println("良好");
break;//可选
case 'C':
System.out.println("及格");
break;//可选
case 'D':
System.out.println("再接再厉");
break;//可选
case 'E':
System.out.println("挂科");
break;//可选
default:
System.out.println("未知等级");
}
}
循环结构
while循环
-
while是最基本的循环,它的结构为:
while( 布尔表达式 ) { //循环内容 }
-
只要布尔表达式为 true,循环就会一直执行下去。
-
我们大多数情况是会让循环停止下来的,我们需要一个让表达式失效的方式来结束循环。
-
少部分情况需要循环一直执行,比如服务器的请求响应监听等。
-
循环条件一直为true就会造成无限循环【死循环】,我们正常的业务编程中应该尽量避免死循环。会影响程序性能或者造成程序卡死奔溃!
-
思考:计算1+2+3+…+100=?
public static void main(String[] args) {
//输出1~100
int i = 0;
while (i < 100) {
i++;
System.out.println(i);
}
}
public static void main(String[] args){
//计算1+2+3+-+100=?
int i = 0;
int sum = 0;
while (i<=100){
sum = sum + i;
i++;
}
System.out.println("最终结果是:"+ sum);
}
do.…while循环
-
对于while 语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即便不满足条件也至少执行一次。
-
do.…while 循环和 while 循环相似,不同的是,do…while 循环至少会执行一次。
do { //代码语句 }while(布尔表达式);
-
While和do-While的区别:
- while先判断后执行。dowhile是先执行后判断!
- Do…while总是保证循环体会被至少执行一次!这是他们的主要差别。
public static void main(String[] args) {
int i = 0;
int sum = 0;
do {
sum = sum + i;
i++;
}while (i<=100);
System.out.println(sum);
}
public static void main(String[] args) {
int a = 0;
while (a < 0) {
System.out.println(a);
a++;
}
System.out.println("===================");
do {
System.out.println(a);
a++;
} while (a < 0);
}
for循环
- 虽然所有循环结构都可以用while或者 do…while表示,但Java 提供了另一种语句 ___ for循环,使一些循环结构变得更加简单。
- for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构。
- for循环执行的次数是在执行前就确定的。语法格式如下:
for(初始化;布尔表达式;更新){
//代码语句
}
public static void main(String[] args) {
int a = 1; //初始化条件
while (a <= 100) {//条件判断
System.out.println(a); //循环体
a += 2;//迭代
}
System.out.println("while循环结束!");
//初始化//条件判断 //迭代
for (int i = 1; i <= 100; i++) {
System.out.println(i);
}
System.out.println("for循环结束!");
/*关于 for 循环有以下几点说明:
最先执行初始化步骤,可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。
然后,检测布尔表达式的值。如果为 true,循环体被执行。如果为faLse,循环终止,开始执行循环体后面的语句。
执行一次循环后,更新循环控制变量(迭代因子控制循环变量的增减)。
再次检测布尔表达式。循环执行上面的过程。*/
for (; ;) {
}
}
- 练习1:计算0到100之间的奇数和偶数的和
public static void main(String[] args) {
//练习1:计算0到100之间的奇数和偶数的和
int oddSum = 0;
int evenSum = 0;
for (int i = 0; i <= 100; i++) {
if (i % 2 != 0) { //奇数
oddSum += i;//oddSun = oddSum + i;
} else {//偶数
evenSum += i;
}
}
System.out.println("奇数的和:" + oddSum);
System.out.println("偶数的和:" + evenSum);
}
- 练习2: 用while或for循环输出1-1000之间能被5整除的数,并且每行输出3个
public static void main(String[] args) {
//练习2: 用while或for循环输出1-1000之间能被5整除的数,并且每行输出3个
for (int i = 1; i <= 1000; i++) {
if(i%5 == 0){
System.out.print(i+"\t");
}
if(i%(5*3)==0){//每行
System.out.println();
//System.out.print("\n");
}
}
//println 输出完会换行
//print 输出完不会换行
}
- 练习3: 打印九九乘法表
public static void main(String[] args) {
//练习3: 打印九九乘法表
//1.我们先打印第一列,这个大家应该都会
//2.我们把固定的1再川一个新环包起来
//3.去掉重复项,i <= j
//4.调整样式
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(j + "*" + i + "=" + (i * j)+"\t");
}
System.out.print("\n");
}
}
增强型for循环。
-
这里我们先只是见一面,做个了解,之后数组我们重点使用
-
Java5 引入了一种主要用于数组或集合的增强型for 循环。
-
Java 增强 for 循环语法格式如下:
for(声明语句 :表达式) { //代码句子 }
-
声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等。
-
表达式:表达式是要访问的数组名,或者是返回值为数组的方法。
public static void main(String[] args) {
int[] numbers = {10,20,30,40,50};//定义了一个数组
for (int i = 0; i < 5; i++) {
System.out.println(numbers[i]);
}
System.out.println("===============");
//遍历数组的元素
for (int x:numbers){
System.out.println(x);
}
}
break continue
- break在任何循环语语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)
- continue 语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。
- 关于goto关键字
- goto关键字很早就在程序设计语言中出现。尽管goto仍是Java的一个保留字,但并未在语言中得到正式使用;Java没有goto。然而,在break和continue这两个关键字的身上,我们仍然能看出一些goto的影子—带标签的break和continue。
- “标签”是指后面跟一个冒号的标识符,例如: label:
- 对Java来说唯一用到标签的地方是在循环语句之前。而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方。
public static void main(String[] args) {
int i = 0;
while (i < 100) {
i++;
if (i % 10 == 0) {
System.out.println();
continue;
}
System.out.print(i);
}
//break在任何新环语句的主体部分,均可用break控制新环的流程。
//break月于强行退出新环,不执行新环中剩余的语句。(break语句也在switch语句中使用)
//continue 勾片任游坏合勾体中,月十来次游坏之程, 40%之的环体中尚不句,我行 卜一次行债坏
}
public static void main(String[] args) {
//打印101-150,之间所有的质数
//质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。
int count = 0;
//不建议使用
outer:
for (int i = 101; i < 150; i++) {
for (int j = 2; j < i / 2; j++) {
if (i % j == 0) {
continue outer;
}
}
System.out.print(i + " ");
}
}
Java方法
何谓方法?
-
System.out.println(),那么它是什么呢?
-
Java方法是语句的集合,它们在一起执行一个功能。
- 方法是解决一类问题的步骤的有序组合
- 方法包含于类或对象中
- 方法在程序中被创建,在其他地方被引用
-
设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成1个功能,这样利于我们后期的扩展。
-
回顾:方法的命名规则?—小驼峰
方法的定义
- Java的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法:
- 方法包含一个方法头和一个方法体。下面是一个方法的所有部分:
- 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
- 返回值类型:方法可能会返回值。returnValueTvpe是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType是关键字void。
- **方法名:**是方法的实际名称。方法名和参数表共同构成方法签名。
- 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数、这个值被称为实参或变量、参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
- 形式参数:在方法被调用时用于接收外界输入的数据。
- 实参:调用方法时实际传给方法的数据。
- 方法体:方法体包含具体的语句,定义该方法的功能。
修饰符 返回值类型 方法名(参数类型 参数名){
...
方法体
...
return 返回值;
}
public class HelloWorld {
//main方法
public static void main(String[] args) {
int max = max(10, 10);
System.out.println(max);
}
//比大小
public static int max(int num1, int num2) {
int result = 0;
if (num1 == num2) {
System.out.println("num1==num2");
return 0;//终止方法
}
if (num1 > num2) {
result = num1;
} else {
result = num2;
}
return result;
}
}
方法的重载
- 重载就是在一个类中,有相同的函数名称,但形参不同的函数。
- 方法的重载的规则:
- 方法名称必须相同。
- 参数列表必须不同(个数不同、或类型不同,参数排列顺序不同等)。
- 方法的返回类型可以相同也可以不相同。
- 仅仅返回类型不同不足以成为方法的重载。
- 实现理论:
- 方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。
public class HelloWorld {
//main方法
public static void main(String[] args) {
int max = max(10, 20);
System.out.println(max);
}
//比大小
public static double max(double num1, double num2) {
double result = 0;
if (num1 == num2) {
System.out.println("num1==num2");
return 0;//终止方法
}
if (num1 > num2) {
result = num1;
} else {
result = num2;
}
return result;
}
//比大小
public static int max(int num1, int num2) {
int result = 0;
if (num1 == num2) {
System.out.println("num1==num2");
return 0;//终止方法
}
if (num1 > num2) {
result = num1;
} else {
result = num2;
}
return result;
}
}
命令行传参
-
有时候你希望运行一个程序时候再传递给它消息。这要靠传递命令行参数给main(函数实现。
public static void main(String args[]) { for (int i = 0; i < args.length; i++) { System.out.println("args[" + i + "]:" + args[i]); } }
可变参数
-
JDK 1.5 开始,Java支持传递同类型的可变参数给一个方法。
-
在方法声明中,在指定参数类型后加一个省略号(…)。
-
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
public static void printMax(double... numbers) { if (numbers.length == 0) { System.out.println("No argument passed"); return; } double result = numbers[0]; //排序! for (int i = 1; i < numbers.length; i++) { if (numbers[i] > result) { result = numbers[i]; } } System.out.println("The max value is " + result); }
public static void main(String args[]) {
// 调用可变参数的方法
printMax(34, 3, 3, 2, 56.5);
printMax(new double[]{1, 2, 3});
}
public static void printMax(double... numbers) {
if (numbers.length == 0) {
System.out.println("No argument passed");
return;
}
double result = numbers[0];
//排序!
for (int i = 1; i < numbers.length; i++) {
if (numbers[i] > result) {
result = numbers[i];
}
}
System.out.println("The max value is " + result);
}
递归
-
A方法调用B方法,我们很容易理解!
-
递归就是:A方法调用A方法!就是自己调用自己
-
利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
-
递归结构包括两个部分:
- 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
- 递归体:什么时候需要调用自身方法。
边界条件:边界
前阶段
返回阶段 n*(n-1)
栈
public static void main(String[] args) {
System.out.println(f(5));
}
//1! 1
//2! 2*1
//5! 5*4*3*2*1
//2 2 * f(1)
//3 3*f(2)
public static int f(int n) {
if (n == 1) {
return 1;
} else {
return n * f(n - 1);
}
}
栈溢出报错
public class HelloWorld {
public static void main(String[] args) {
HelloWorld test = new HelloWorld();
test.test();
}
public void test(){
test();
}
}
Java数组
数组的定义
- 数组是相同类型数据的有序集合.
- 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。
- 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们.
数组声明创建
-
首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法:
dataType[] arrayRefVar;//首选的方法 或 dataType arrayRefVar[]; // 效果相同,但不是首选方法
-
Java语言使用new操作符来创建数组,语法如下:
dataType[] arrayRefVar = new dataType[arraySize];
-
数组的元素是通过索引访问的,数组索引从始。
-
获取数组长度:
arrays.length
//变量的类型 变量的名字 = 变量的值;
//数组类型
public static void main(String[] args) {
int[] nums; //1.声明一个数组
nums = new int[10];//2.创建一个数组
//3.给数组元素中赋值
nums[0]= 1;
nums[1]= 2;
nums[2]= 3;
nums[3]= 4;
nums[4]= 5;
nums[5]= 6;
nums[6]= 7;
nums[7]= 8;
nums[8]= 9;
nums[9]= 10;
//计算所有元素的和
int sum = 0 ;
//获取数组长度,arrays.length
for (int i = 0; i < nums.length; i++) {
sum = sum + nums[i];
}
System.out.println(sum);
}
内存分析
-
堆
-
存放new的对象和数组
-
可以被所有的线程共享,不会存放别的对象引用
-
-
栈
- 存放基本变量类型(会包含这个基本类型的具体数值)
- 引用对象的变量(会存放这个引用在堆里面的具体地址)
-
方法区
- 可以被所有的线程共享
- 包含了所有的class和static变量
写代码画图分析内存!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TviQr424-1659070441865)(C:\Users\Wz\Desktop\博客\数组内存分析.png)]
三种初始化
静态初始化
int[] a = {1,2,3};
Man[] mans = {new Man(1,1),new Man(2,2)};
动态初始化
int[] a = new int[2];
a[0]=1;
a[1]=2;
数组的默认初始化
- 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
public static void main(String[] args) {
//静态初始化:创建 + 赋值
int[] a = {1,2,3,4,5,6,7,8};
System.out.println(a[0]);
//动态初始化
int[] b = new int[10];
b[0] = 10;
System.out.println(b[0]);
b[1] = 20;
//默认初始化
System.out.println(b[1]);
System.out.println(b[2]);
System.out.println(b[3]);
}
数组的四个基本特点
- 其长度是确定的。数组一旦被创建,它的大小就是不可以改变的。
- 其元素必须是相同类型,不允许出现混合类型。
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型。
- 数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。
数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
数组边界
-
下标的合法区间:[0, length-1],如果越界就会报错;
public static void main(String[ ] args) { int[] a=new int[2]; System.out.println(a[2]); }
-
ArrayIndexOutOfBoundsException :数组下标越界异常!
//下标越界案例
public static void main(String[] args) {
//静态初始化:创建 + 赋值
int[] a = {1, 2, 3, 4, 5, 6, 7, 8};
System.out.println(a[0]);
for (int i = 0; i <= a.length; i++) {
System.out.println(a[i]);
}
}
- 小结:
- 数组是相同数据类型(数据类型可以为任意类型)的有序集合
- 数组也是对象。数组元素相当于对象的成员变量
- 数组长度的确定的,不可变的。如果越界,则报:ArraylndexOutofBounds
数组使用
public static void main(String[] args) {
int[] arrays = {1, 2, 3, 4, 5};
//打印全部的数组元素
for (int i = 0; i < arrays.length; i++) {
System.out.println(arrays[i]);
}
System.out.println("=================");
//计算所有元素的和
int sum = 0;
for (int i = 0; i < arrays.length; i++) {
sum += arrays[i];
}
System.out.println("sum=" + sum);
System.out.println("=================");
//查找最大元素
int max = arrays[0];
for (int i = 1; i < arrays.length; i++) {
if (arrays[i] > max) {
max = arrays[i];
}
}
System.out.println("max=" + max);
}
- For-Each 循 环
- 数组作方法入参
- 数组作返回值
public static void main(String[] args) {
int[] arrays = {1, 2, 3, 4, 5};
//JDK1.5,没有下标
// for (int array : arrays) {
// System.out.println(array);
// }
// printArray(arrays);
int[]reverse = reverse(arrays);
printArray(reverse);
}
//反转数组
public static int[] reverse(int[] arrays) {
int[] reslt = new int[arrays.length];
//反转的操作
for (int i = 0, j = reslt.length - 1; i < arrays.length; i++, j--) {
reslt[j] = arrays[i];
}
return reslt;
}
//打印数组元素
public static void printArray(int[] arrays) {
for (int i = 0; i < arrays.length; i++) {
System.out.print(arrays[i] + " ");
}
}
多维数组
-
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。
-
二维数组
int a[][] = new int[2][5];
-
解析: 以上二维数组 a 可以看成一个两行五列的数组。
-
思考:多维数组的使用?
num[1][0];
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YNMUPoty-1659070441867)(C:\Users\Wz\Desktop\博客\多维数组.png)]
public static void main(String[] args) {
//[4][2]
/*
1,2 array[0]
2,3 arrqy[1]
3,4 array[2]
4,5 array[3]
*/
int[][] array = {{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}};
System.out.println(array[0]);
System.out.println("=============");
printArray(array[0]);
System.out.println("=============");
System.out.println(array[2][0]);
System.out.println(array[2][1]);
System.out.println("=============");
System.out.println(array.length);
System.out.println(array[0].length);
System.out.println("=============");
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
System.out.println(array[i][j]);
}
}
}
//打印数组元素
public static void printArray(int[] arrays) {
for (int i = 0; i < arrays.length; i++) {
System.out.println(arrays[i] + "");
}
}
Arrays类
-
数组的工具类java.util.Arrays
-
由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。
-
查看JDK帮助文档
-
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而"不用"使用对象来调用(注意:是“不用”而不是“不能”)
-
具有以下常用功能:
- 给数组赋值:通过fill 方法。
- 对数组排序:通过 sort 方法,按升序。
- 比较数组:通过equals 方法比较数组中元素值是否相等。
- 查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作。
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 9090, 31231, 543, 21, 3, 23};
System.out.println(a); // [I@4554617c
//打印数组元素Arrays.tostring
System.out.println(Arrays.toString(a));
System.out.println("==========================");
printArray(a);
}
public static void printArray(int[] a) {
for (int i = 0; i < a.length; i++) {
if (i == 0) {
System.out.print("[");
}
if (i == a.length - 1) {
System.out.print(a[i] + "]");
} else {
System.out.print(a[i] + ", ");
}
}
}
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 9090, 31231, 543, 21, 3, 23};
//System.out.printLn(a); // [I@4554617c
//打印数组元素Arrqys.tostring
//System.out.printLn(Arroys.tostring(a));
Arrays.sort(a);//数组进行播序 :升序
System.out.println(Arrays.toString(a));
Arrays.fill(a,2,4,0);//数组填充---->下标从2到4填充为0,[2,4),取不到4
System.out.println(Arrays.toString(a));
}
排序
冒泡排序
- 冒泡的代码还是相当简单的,两层循环,外层冒泡轮数,里层依次比较,江湖中人人尽皆知。
- 我们看到嵌套循环,应该立马就可以得出这个算法的时间复杂度为:O(n2)。
public static void main(String[] args) {
int[] a = {1, 4, 5, 6, 72, 2, 2, 3, 7, 25, 87};
int[] sort = sort(a);//调用完我们自己写的排序方法以后,返回一个
System.out.println(Arrays.toString(sort));
}
//冒泡排序
//1.比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们就交换他们的位置
//2. 每一次比较,都会产生出一个人大,或者最小的数字:
//3.下一轮则可以少一次排序!
//4.依次新环,直到结束!
public static int[] sort(int[] array) {
//临时变量
int temp = 0;
//外层新环,制断我们这个要走多少次;
for (int i = 0; i < array.length - 1; i++) {
boolean flag = false;//通过flag标识位减少没有意义的比较
//内层循环,比价判断两个数,如果第一个数比第二个数大,则交换位置
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;
}
}
if (flag==false){
break;
}
}
return array;
}
稀疏数组
- 当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
- 稀疏数组的处理方式是:
- 记录数组一共有几行几列,有多少个不同值
- 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模
下图为6行7列8个有效数字的稀疏数组(将有效的值定位出来,节省空间)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-47WkfAeA-1659070441867)(C:\Users\Wz\Desktop\博客\稀疏数组.png)]
public static void main(String[] args) {
//1.创建一个二维数组 11*11 0:没有棋子 1:黑棋 2:白棋
int[][] array1 = new int[11][11];
array1[1][2] = 1;
array1[2][3] = 2;
//输出原始的数组
System.out.println("输出原始的数组");
for (int[] ints : array1) {
for (int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.println();
}
//转换为稀疏数组保存
//获取有效值的个数
int sum = 0;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (array1[i][j] != 0) {
sum++;
}
}
}
System.out.println("====================================");
System.out.println("有效值的个数:" + sum);
//2.创建一个稀疏数组的数组
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 < array1.length; i++) {
for (int j = 0; j < array1[i].length; j++) {
if (array1[i][j] != 0) {
count++;
array2[count][0] = i;
array2[count][1] = j;
array2[count][2] = array1[i][j];
}
}
}
//输出稀疏数组
System.out.println("稀疏数组");
for (int i = 0; i < array2.length; i++) {
System.out.println(array2[i][0] + "\t"
+ array2[i][1] + "\t"
+ array2[i][2] + "\t");
}
System.out.println("====================================");
System.out.println("还原");
//1.读取稀疏数组的值
int[][] array3 = new int[array2[0][0]][array2[0][1]];
//2.给其中的元素还原他的值
for (int i = 1; i < array2.length; i++) {
array3[array2[i][0]][array2[i][1]] = array2[i][2];
}
//3.打印
System.out.println("输出还原后的数值");
for (int[] ints : array3) {
for (int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.println();
}
}
Java面向对象
面向过程 & 面向对象
- 面向过程思想(具体实施)
- 步骤清晰简单,第一步做什么,第二步做什么……
- 面对过程适合处理一些较为简单的问题
- 面向对象思想(分析框架)
- 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
- 对于描述复杂的事物,为了从宏观上把握、 从整体上合理分析,我们需要使用面向对象的忠路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。
什么是面向对象
-
面向对象编程(Object-Oriented Programming, OOP)
-
面向对象编程的本质就是: 以类的方式组织代码,以对象的组织(封装)数据。
-
抽象:编程思想!持续的学习才有机会茅塞顿开!多实践多测试大脑中的想法!
-
三大特性:
-
封装
行李箱上锁
-
继承
继承父亲的产业,自己也可以有很多产业
-
多态
小明,小红,小强,小刚 … 都是 人
-
-
从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
-
从代码运行角度考虑是先有类后有对象。类是对象的模板。
回顾方法及加深
-
方法的定义
- 修饰符
- 返回类型
- break:跳出switch,结束循环 和 return 的区别
- 方法名 : 注意规范 (见名知意)
- 参数列表 :(参数类型,参数名)。。。
- 异常抛出 :
-
方法的调用
- 静态方法
- 非静态方法
- 形参和实参
public static void main(String[] args) { //实际参数和形式参数的类型要对应! int add = Demo03.add(1, 2); System.out.println(add); } public static int add(int a ,int b){ return a+b; }
- 值传递和引用传递
//值传递 public static void main(String[] args) { int a = 1; System.out.println(a); Demo04.change(a);//1 } //返回值为空 public static void change(int a){ a = 10; }
public class Demo05 { //引用传递 public static void main(String[] args) { Person person = new Person(); System.out.println(person.name);//null Demo05.change(person); System.out.println(person.name);//小白 } public static void change(Person person) { //person是一个对象:指向的--->Person person = new Person(); person.name = "小白"; } } //定义一个Person类,有一个属性:name class Person { String name;//null }
- this关键字
创建与初始化对象
- 使用new关键字创建对象
- 使用new关键字创建的时候,除了分配内存空间之外,还会给 创建好的对象 进行默认的初始化以及对类中构造器的调用。
- 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下俩
个特点:- 必须和类的名字相同
- 必须没有返回类型,也不能写void
- 构造器必须要掌握
类与对象的关系
- 类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物.
- 动物、植物、手机、电脑…
- Person类、Pet类、Car类等,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为
- 对象是抽象概念的具体实例
- 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。
- 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念.
-
类与对象
类是一个模板:抽象,对象是一个具体的实例 -
方法
定义、调用! -
对应的引用
引用类型:基本类型(8)对象是通过引用来操作的:栈—>堆
-
属性:字段Field 成员变量
默认初始化:
数字:0 0.0
char : u0000
Boolean: false
引用: null
修饰符 属性类型 属性名 = 属性值 !
-
对象的创建和使用
-
必须使用new 关键字创造对象,构造器 Person person = new Person();
-
对象的属性 person.name
-
对象的方法 person.sleep()
-
-
类:
- 静态的属性 属性
- 动态的行为 方法
-
封装、继承、多态
代码实现
public class Person {
//一个类即使什么都不写,它也会存在一个方法
//显示的定义构造器
String name;
int age;
//att+ insert
//1. 使用new关键字,本质是在调用构造器
//2.用来初始化值
public Person() {
}
//有参构造:一旦定义了有参构选,无参就必须显示定义
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
/*
构造器:
1.和类名相同
2.没有返回值
作用:
1.new 本质在调用构造方法
2.初始化对象的值
注意点:
1.定义有参构造之后,如果想使用无参构造,显示的定义一个无参的构造
Alt + Insert
this. =
*/
}
//一个项目应该只存一个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 = 5;
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
System.out.println("===================");
System.out.println(xiaohong.name);
System.out.println(xiaohong.age);
System.out.println("===================");
Person person = new Person("小白", 23);
System.out.println(person.name + "\t" + person.age);
}
}
封装
- 该露的露,该藏的藏
- 我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
- 封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
- 记住这句话就够了:属性私有, get/set
/*
1.提高程序的安全性,保护数据
2.隐藏代码的实现细节
3.统一接口
4.系统可维护增加了
*/
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("小白");
//方法名 参数列表
System.out.println(s1.getName());
s1.setAge(999);//不合法的
System.out.println(s1.getAge());
}
}
public class Student {
private String name;//名字
private int id;//学号
private char sex;//性别
private int age;//年龄
//提供一些可以操作这个属性的方法!
// 提供一些public 的get、set方法
//get 获得这个数据
public String getName() {
return this.name;
}
//set 给这个数据设置值
public void setName(String name) {
this.name = name;
}
//alt + insert
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;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age > 120 || age < 0) {//不合法
this.age = -1;
} else {
this.age = age;
}
}
//学习()
public void Stady() {
}
//睡觉()
public void sleep() {
}
}
继承
- 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
- extends的意思是“扩展”。子类是父类的扩展。
- JAVA中类只有单继承,没有多继承!
- 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
- 继承关系的俩个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
- 子类和父类之间,从意义上讲应该具有"is a"的关系.
- object类
- super
- 方法重写 : 重点(多态)
super:
-
super调用父类的构造方法,必须在构造方法的第一个
-
super 必须只能出现在子类的方法或者构造方法中!
-
super和 this 不能同时调用构造方法!
this:
- 代表的对象不同:
- this:本身调用者的这个对象
- super:代表父类对象的应用
- 前提
- this:没有继承也可以使用
- super:只能在继承条件才可以使用
- 构造方法
- this(): 本类的构造
- super():父类的构造!
重写
重写:需要有继承关系,子类重写父类的方法!
-
方法名必须相同
-
参数列表列表必须相同
-
修饰符:范围可以扩大但不能缩小:
public>Protected>Default>private -
抛出的异常:范围,可以被缩小,但不能扩大;ClassNotFoundException --> Exception(大)
重写,子类的方法和父类必要一致;方法体不同!
为什么需要重写:
1.父类的功能,子类不一定需要,或者不一定满足!
Alt + Insert : override;
多态
-
动态编译:类型:可扩展性
-
即同一方法可以根据发送对象的不同而采用多种不同的行为方式。
-
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
-
多态存在的条件
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
-
注意: 多态是方法的多态,属性没有多态性。
-
instanceof (类型转换) 引用类型~
多态注意事项:
- 多态是方法的多态,属性没有多态
- 父类和子类,有联系 类型转换异常!CLassCastException !
- 存在条件:继承关系,方法需要重写,父类引用指向子类对象!Father f1 = new Son();
- static 方法,属于类,它不属于实例
- final 常量;
- private方法;
- 父类引用指向子类的对象
- 把子类转换为父类,向上转型;
- 把父类转换为子类,向下转型:强制转换
- 方便方法的调用,减少重复的代码!简介
封装、继承、多态! 抽象类,接口
抽象类
- abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
- 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
- 抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
- 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
- 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
//abstract 抽象类:类extends: 单继承~ (接口可以多继承)
public abstract class Action {
//约束~有人帮我们实现~
//abstract ,抽象方法,只有方法名字,没有方法的实现!
public abstract void dosomething();
//1.不能new这个抽象类,只能靠子类去实现它;约束!
//2. 抽象类中可以写普通的方法。
//3.抽象方法必须在抽象类中~
// 抽象的抽象:约束~
//思考题? new ,存在构造器么?
//存在的意义 抽象出来~提高开发效率
}
接口
- 普通类:只有具体实现
- 抽象类:具体实现和规范(抽象方法) 都有!
- 接口: 只有规范! 自己无法写方法~专业的约束! 约束和实现分离:面向接口编程~
- 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你好人,则必须干掉坏人;如果你是坏人,则必须欺负好人。
- 接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。
- OO的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计 模式都只针对具备了抽象能力的语言(比如C++、java、c#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。
声明类的关键字是class,声明接口的关键字是interface
作用:
- 约束
- 定义一些方法,让不同的人实现~ 10 —> 1
- public abstract
- public static final
- 接口不能被实例化~,接口中没有构造方法~
- implements可以实现多个接口
- 必须要重写接口中的方法~
内部类
- 内部类就是在一个类的内部在定义一个类,比如, A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。
-
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
-
Java异常
什么是异常
- 实际工作中,遇到的情况不可能是非常完美的。比如: 你写的某个模块,用户输入不一定符合你的要求、你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等。我们的程序再跑着,内存或硬盘可能满了。等等。
- 软件程序在运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是:Exception,意思是例外。这些,例外情况,或者叫异常,怎么让我们写的程序做出合理的处理。而不至于程序崩溃。
- 异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。
- 异常发生在程序运行期间,它影响了正常的程序执行流程。
简单分类
- 要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:
- 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
- 运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
- 错误(ERRPR): 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
Error
- Error类对象由 Java 虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
- Java虚拟机运行错误(Virtual MachineError),当JVM不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机 (JVM) 一般会选择线程终止;
- 还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError) 、链接错误(LinkageError) 。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。
Exception
- 在Exception分支中有一个重要的子类RuntimeException (运行时异常)
- ArraylndexOutOfBoundsException (数组下标越界)
- NullPointerException (空指针异常)
- ArithmeticException (算术异常)
- MissingResourceException(丢失资源)
- ClassNotFoundException (找不到类) 等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
- 这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;
- Error和Exception的区别:Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机 (JVM) 一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。
异常处理机制
-
抛出异常
-
捕获异常
-
异常处理五个关键字
- try、catch、finally. throw、throws
public class Test {
public static void main(String[] args) {
//Ctrl + Alt + T
try {
new Test().test(1, 0);
} catch (Exception e) {
e.printStackTrace();
}
}
//假设这方法中,处理不了这个异常,方法上抛出异常
public void test(int a, int b) {
if (b == 0) {//throw throws
throw new ArithmeticException();//主动抛出异常,一般在方法中使用
}
}
}
/*
//假设要捕获多个异常,从小到大~
try {//try监控区域
if (b == 0) {//throw throws
throw new ArithmeticException();//主动抛出异常
}
System.out.println(a / b);
} catch (Error e) {//catch 想要捕获的异常类型
System.out.println("Exception");
} catch (Exception e) {
System.out.println("Error");
} catch (Throwable t) {
System.out.println("Throwable");
} finally {//处理善后工作
System.out.println("finally");
}
//finally 可以不要 ,假设IO,资源,关闭!
*/
自定义异常
- 使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需继承Exception类即可。
- 在程序中使用自定义异常类,大体可分为以下几个步骤:
- 创建自定义异常类。
- 在方法中通过throw关键字抛出异常对象。
- 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
- 在出现异常方法的调用者中捕获并处理异常。
//自定义的异常类
public class MyException extends Exception{
//传递数字>10;
private int detail;
public MyException(int a ){
this .detail = a;
}
//toString :异常的打印信息
@Override
public String toString() {
return "MyException{" + detail + '}';
}
}
public class Test {
//可能会存在异常的方法
static void test(int a) throws MyException {
System.out.println("传递的参数为:" + a);
if (a > 10) {
throw new MyException(a);//抛出
}
System.out.println("OK");
}
public static void main(String[] args) {
try {
test(11);
} catch (Exception e) {
System.out.println("MyException=>" + e);
}
}
}
实际应用中的经验总结
- 处理运行时异常时,采用逻辑去合理规避同时辅助 try-catch 处理
- 在多重catch块后面,可以加一个catch (Exception) 来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上 try-catch , 处理潜在的异常
- 尽量去处理异常,切忌只是简单地调用printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句块去释放占用的资源