Java学习
Java零基础学习视频通俗易懂(狂神说Java)
狂神说B站视频:https://www.bilibili.com/video/BV12J41137hu
Java官网:https://www.java.com/
一、Java入门
1.Java的诞生
1972年C语言建立。
问题:
- 指针
- 内存管理
1982年C++诞生。
问题:
- 复杂
1995年建立Java。
(C++—-)
为每台电脑安装JVM(Java虚拟机)。
分类:
-
JavaSE
-
JavaME
-
JavaEE
三高:高可用,高性能,高并发。
Java帝国的稳固:
2006:Hadoop(大数据端)
2008:Android(手机端)
2.Java的特性和优势
- 简单性
- 面向对象
- 可移植性
- 高性能
- 分布式
- 动态性
- 多线程
- 安全性
- 健壮性
3.Java三大版本
最大优点:跨平台语言;技术:JVM。
Write once , run anywhere!
- JavaSE 标准版
开发桌面程序,控制台开发
- JavaME 嵌入式开发
手机程序开发
- JavaEE 企业级开发
Web端,服务器开发
4.JDK JRE JVM
- JDK : Java Development Kit
- JRE: Java Runtime Environment
- JVM : JAVA Virtual Machine
5.Java开发环境搭建
1.卸载JDK
- 删除java安装目录
- 删除JAVA_HOME
- 删除Path下的JAVA目录
- java -version
2.安装JDK
- 百度搜索JDK8,下载电脑对应版本
- 双击安装JDK,设置安装路径
- 配置环境变量:JAVA_HOME
- 配置path变量
java -version
查看安装成功
3.JDK目录
bin:存放可执行程序
include:引入c头文件
jre:java运行环境
lib:java库,工具
src:资源文件,类
4.hello world!
- 编辑java文件
public class hello{
public static void main(String[] args){
System.out.print("Hello,World!");
}
}
- 编译java文件
javac hello.java
结果会在当前目录生成一个hello.class文件
- 运行class文件
java hello
5.可能出现的问题
- java大小写敏感
- 尽量使用英文,防止乱码
- 文件名与类名必须要保持一致
- 要使用英文符号
6.Java程序运行机制
编译型(complie):c c++ 操作系统
解释型:网页 javasprit python
Java既是编译型语言又是解释型语言
7.IDEA安装
1.什么是IDE?
集成开发环境
2.IDEA介绍
jetbrains公司,公司总部位于捷克。
3.IDEA下载
官网下载地址:https://download.jetbrains.com/idea/ideaIU-2020.3.2.exe
二、Java基本语法
1.注释 标识符 关键字
注释
java中的注释有三种:
1.单行注释
只能注释一行文字
public class hello {
public static void main(String[] args) {
//单行注释
//输出 hello world
System.out.println("hello world");
}
}
2.多行注释
可以注释多行文字
public class hello {
public static void main(String[] args) {
/*
多行注释
可跨行
*/
System.out.println("hello world");
}
}
3.文档注释
/**
* @description hello_world
* @Author baixf
*
*/
4.有趣的代码注释
/***
* .::::.
* .::::::::.
* :::::::::::
* ..:::::::::::'
* '::::::::::::'
* .::::::::::
* '::::::::::::::..
* ..::::::::::::.
* ``::::::::::::::::
* ::::``:::::::::' .:::.
* ::::' ':::::' .::::::::.
* .::::' :::: .:::::::'::::.
* .:::' ::::: .:::::::::' ':::::.
* .::' :::::.:::::::::' ':::::.
* .::' ::::::::::::::' ``::::.
* ...::: ::::::::::::' ``::.
* ```` ':. ':::::::::' ::::..
* '.:::::' ':'````..
*/
标识符
标识符注意点:
- 所有的标识符都应该以字母(A-Z或者a-z),美元符($)、或者下划线(_)开始
- 首字符之后可以是字母(A-Z或者a-z),美元符($)、下划线(_)或数字的任何字符组合不能使用关键字作为变量名或方法名。
- 标识符是大小写敏感的
public class hello {
public static void main(String[] args) {
String man="banananana";
String Man="orangegege";
}
}
- 合法标识符举例: age、$salary._value、_1_value
- 非标识符举例:123abc、-salary、#abc
关键字
2.数据类型
强类型语言:要求变量的使用严格规定,所有变量必须定义后才能使用。安全性高;速度慢。
弱类型语言:要求变量的使用要符合规定,所有变量都必须先定义后才能使用。
基本数据类型(primitive type)
byte:1个字节;
short:2个字节;
int:4个字节;
long:8个字节;
float:4个字节;
double:8个字节;
char:2个字节;
boolean:1位。
1.数值类型
- 整数类型
int其实是一个类,Integer;byte同理Byte。
//整数
int num1 = 10; //最常用byte num2 = 20;
short num3 = 30;
long num4 = 30L; //Long类型要在数字后面加个L
//进制问题
int i = 10;
int i2 = 010; //八进制0
int i3 = 0x10; //十六进制0x 0~9 A~F
system.out.print1n(i);
system.out.print1n(i2);
System.out.println(i3);
- 浮点类型
//浮点数
float num5 = 50.1F;
double num6 = 3.141592653589793238462643;
//浮点数的舍入误差问题
//fLoat 有限 离散 舍入误差 大约 接近但不等于
f1oat f = 0.1f; //0.1
double d = 1.0/10; //0.1
system.out.println(f==d); //false
system.out.println(f);
system.out.println(d);
f1oat d1 = 23131312312312313f;
f1oat d2 = d1 + 1;
system.out.print1n(d1==d2);//true
- 字符类型
//字符
char name = 'A' ;
//字符串,string不是关键字,类
//string namea ="白小飞"
//强制类型转换,所有的字符本质还是数字
char c1 = 'a';
char c2 = '中;
system.out.println(c1);
system.out.println((int)c1); //强制换行
system.out.println(c2);
system.out.println((int)c2); //强制换行
char c3 = '\u0061';
System.out.println(c3); //a
//所有的字符本质还是数字
//编码 unicode 表:(97 = a 65 =A) 2字节 0 - 65536 Excel 2 16 = 65536
//转义字符
// \t制表符 \n换行
system.out.println("He1lo\twor1d");
system.out.println("He1lo\nwor1d");
string sa = new String( original: "he11o world");
string sb = new String( original: "he1lo world");
system.out.print1n(sa==sb);
// false
String sc = "he1lo wor1d";
string sd = "he1lo wor1d" ;
system.out.println(sc==sd);/对象从内存分析
//true
2.bollean类型
/布尔值:是非
boolean f1ag = true;//booLean flag = false;
//布尔值扩展
boolean flag = true;
if (flag==true){}
if(flag){}
//less is more!
引用类型(reference type)
1.类
2.接口
3.数组
3.类型转换
由于Java是强类型语言,所以要进行有些运算的时候的,需要用到类型转换。
低-----------------》》》》》》-----------------------高
byte,short,char > int > long > float > double
int i = 128;
byte b = (byte)i; //内存溢出
double c = i;
//强制转换 (类型)变量名 高->地
//自动转换 地->高
system.out.println(i);
System.out.println(b);
System.out.println(c);
注意点
- 不能对布尔值进行转换
- 不能把对象类型转换为不相干的类型
- 在把高容量转换到低容量的时候,强制转换
- 转换的时候可能存在内存溢出,或者精度问题!
system.out.println((int)23.7);
system.out.println((int)-45.89f);
char c = 'a';
int d = c+1;
system.out.println(d);
System.out.println((char)d);
/操作比较大的数的时候,注意溢出问题
//JDK7新特性,数字之间可以用下划线分割
int money = 10_0000_0000;
int years = 20;
int total = money * years; //-1474836480 ,计算的时候溢出了
long total2 = money * years;//默认是int,转换之前已经存在问题了?
long total3 = money * ((long)yeans);//先把一个数转换为Long
system.out.println(total3);
4.变量常量
变量
变量是什么:就是可以变化的量!
Java是一种强类型语言,每个变量都必须声明其类型。
Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。
type varName [=value] [{,varName[=value]}];
//数据类型 变量值 = 值; 可以用逗号隔开来声明多个同类型变量。
注意事项:
每个变量都有类型,类型可以是基本类型,也可以是引用类型。
变量名必须是合法的标识符。
变量声明是一条完整的语句,因此每一个声明都必须以分号结束
int a=1,b=2,c=3; //程序可读性
string name = "baixf";
char x = 'x' ;
double pi = 3.14;
变量的作用域
public class Variable {
static int allClicks=0; //类变量
String str="hello world"; //实例变量
public void method(){
int i=0; //局部变量
}
}
1.类变量
2.实例变量
3.局部变量
public class demo01 {
//属性:变量;
//类变量
static double salary = 2500;
//实例变量:从属于对象-这个类;如果不自行初始化,这个类型的默认值 0;
//布尔值:默认为 false;
//除了基本类型,其余的都是null;
String name;
int age;
//main方法;
public static void main(String[] args) {
//局部变量;必须声明和初始化值
int i=10; //有效范围仅在其main方法中
System.out.println(i);
//变量类型 变量名字 = new demo01();
demo01 demo01=new demo01();
System.out.println(demo01.age);
System.out.println(demo01.name);
//类变量
System.out.println(salary);
}
//System.out.println(i); i超出适用范围
}
常量
常量(Constant):初始化(initialize)后不能再改变值!不会变动的值。
所谓常量可以理解成一种特殊的变量,它的值被设定后,在程序运行过程中不允许被改变。
常量名一般使用大写字符。
final 常量名=值;
final double PI=3.14;
public class demo02 {
//关键词:final
//修饰符,不存在先后顺序
//静态常量,例如游戏中对界面的设定
static final double pi = 3.14; //常量尽量全部大写,或者大写加下划线
final static double PI = 3.14;
public static void main(String[] args) {
System.out.println(pi);
System.out.println(PI);
}
}
变量的命名规范
所有变量、方法、类名:见名知意
类成员变量:首字母小写和驼峰原则: monthSalary,lastWeek
局部变量:首字母小写和驼峰原则
常量:大写字母和下划线:MAX_VALUE
类名:首字母大写和驼峰原则: Man, GoodMan
方法名:首字母小写和驼峰原则: run(), runRun()
5.运算符
Java语言支持如下运算符:
- 算术运算符: +,-,,l,%,++,--。
- 赋值运算符: =*
- 关系运算符:>,<,>=,<=,==, !=, instanceof
- 逻辑运算符: &&,|,!
- 位运算符: &,|,^,~,>>,<<,>>>(了解! ! ! )
- 条件运算符: ?∶
- 扩展赋值运算符:+=,-=,*=,/=
example
package operator;
public class demo01 {
public static void main(String[] args) {
//二元运算符
int a =10;
int b =20;
int c =30;
int d =40;
System.out.println(a+b);
System.out.println(a-b);
System.out.println(a*b);
System.out.println(a/b);
System.out.println(a/(double)b);
}
}
package operator;
public class Demo02 {
public static void main(String[] args) {
long a = 12345566l;
int b = 32411230;
short c = 50;
byte d = 8;
//多个数操作时,存在最高级则最终为最高级的数据类型
System.out.println(a+b+c+d); //long
System.out.println(b+c+d); //int
System.out.println(c+d); //int
}
}
package operator;
public class Demo03 {
public static void main(String[] args) {
//关系运算符返回的结果:true false 布尔值
//常与 if 使用
int a = 20;
int b = 60;
int c = 11;
System.out.println(a==b);
System.out.println(a!=b);
System.out.println(a>=b);
System.out.println(a<=b);
System.out.println(a%c);
}
}
package operator;
public class Demo04 {
public static void main(String[] args) {
//++ -- 自增 自减
int a = 3;
System.out.println(a);
System.out.println(a++);
System.out.println(a);
System.out.println(++a);
System.out.println(a);
}
}
3
3
4
5
5
package operator;
public class Demo05 {
public static void main(String[] args) {
//幂运算 3^2=9
double pow = Math.pow(3,2);
System.out.println(pow);
}
}
package operator;
public class Demo05 {
public static void main(String[] args) {
//幂运算 3^2=9
//Math类提供很多数学方法
double pow = Math.pow(3,2);
System.out.println(pow);
}
}
package operator;
//逻辑运算符
public class Demo06 {
public static void main(String[] args) {
//与或非
boolean a = true;
boolean b = false;
System.out.println(a && b); //两个全为真才为真
System.out.println(a || b); //有一真则为真
System.out.println(!(a && b)); //真变假,假变真
//短路运算
int c = 5;
System.out.println(b && (c++>4)); //当前面第一个为 false 时,后面的不会执行
System.out.println(c); //输出c仍为 5 ,说明 c++并未执行
}
}
package operator;
//位运算
public class Demo07 {
public static void main(String[] args) {
/*
A = 1001 1100
B = 1010 1110
A&B 1000 1100
A|B 1011 1110
A^B 0011 0010 //异或:相同则为0,不同为1
~B 0101 0011
*/
int a = 0b1001_1100;
int b = 0b1010_1110;
System.out.println(Integer.toBinaryString(a&b));
System.out.println(Integer.toBinaryString(a|b));
System.out.println(Integer.toBinaryString(a^b));
System.out.println(Integer.toBinaryString(~b));
/*
2*8最快运算
底层:二进制,所以效率极其高
<<
>>
0000 0000 0
0000 0001 1
0000 0010 2
0000 0100 3
0000 1000 4
*/
System.out.println(2<<3);
}
}
package operator;
public class Demo08 {
public static void main(String[] args) {
int a = 10;
int b = 20;
int c = 10;
a+=b; //a = a + b
c-=b; //c = c - b
//字符串连接符 +
//细节问题
System.out.println(""+a+b); //先做前面的,即将其整体转换为string
System.out.println(a+b+""); //先做整数相加,再转换为字符串
System.out.println(a);
System.out.println(c);
}
}
3020
50
30
-10
package operator;
//三元运算符
public class Demo09 {
public static void main(String[] args) {
// x : y ? z
// 如果 x 为 true,则为 y, 否则为 z
int a = 5;
int b = 6;
int c = 10;
//if 但是这样会更简洁
System.out.println((a>70?b:c));
}
}
运算符的优先级
6.包机制
- 为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。
- 包语句的语法格式为:
package pkg1[. pkg2[. pkg3...]];
- 一般利用公司域名倒置作为包名;
tk.baixf.www
tk.baixf.blog
- 为了能够使用某一个包的成员,我们需要在Java程序中明确导入该包。使用"import"语句可完成此功能
import package1[.package2……].(classname|*)
7.JavaDoc
- javadoc命令是用来生成自己API文档的
- 参数信息
* @author作者名
* @version版本
* @since指明需要最早使用的jdk版本
* @param参数名
* @return返回值情况
* @throws 异常抛出情况
javadoc -encoding UTF-8 -charset UTF-8 Doc.java
IDEA生成JavaDOC
三、Java流程控制
1.用户交互Scanner
Scanner对象
-
之前我们学的基本语法中我们并没有实现程序和人的交互,但是Java给我们提供了这样一个工具类,我们可以获取用户的输入。java.util.Scanner是Java5的新特征,我们可以通过Scanner类来获取用户的输入。
-
基本语法:
Scanner s = new Scanner(System.in);
-
通过Scanner类的next()与nextLine()方法获取输入的字符串,在读取前我们一般需要使用hasNext()与hasNextLine()判断是否还有输入的数据。
package tk.scanner;
import java.util.Scanner;
public class Demo03 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你想输入的字符串:");
String str = scanner.nextLine();
System.out.println("刚刚输入的为:"+str);
scanner.close();
}
}
Scanner对象
1.next():
- 一定要读取到有效字符后才可以结束输入。
- 对输入有效字符之前遇到的空白,next()方法会自动将其去掉。
- 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
- next()不能得到带有空格的字符串。
2.nextLine():
- 以Enter为结束符,也就是说nextLine()方法返回的是输入回车之前的所有字符。
- 可以获得空白。
package tk.scanner;
import java.util.Scanner;
public class Demo01 {
public static void main(String[] args) {
//创建一个扫描器对象,用于接收键盘数据
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();
}
}
package tk.scanner;
import java.util.Scanner;
public class Demo02 {
public static void main(String[] args) {
//从键盘接收数据
Scanner scanner = new Scanner(System.in);
System.out.println("使用nextLine方式接受:");
//判断是否还有输入
if(scanner.hasNextLine()){
String str = scanner.nextLine();
System.out.println("输出的内容为"+str);
}
scanner.close();
}
}
对浮点数的支持
package tk.scanner;
import java.util.Scanner;
public class Demo04 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int a = 0;
float b = 0.00f;
//从键盘接收数据
System.out.println("请输入整数:");
if(scanner.hasNextInt()){
a = scanner.nextInt();
System.out.println("输入的整数为:"+a);
}else{
System.out.println("您输入的不是整数!");
}
System.out.println("请输入一个小澍:");
if(scanner.hasNextFloat()){
b = scanner.nextFloat();
System.out.println("您输入的浮点数为"+b);
}else{
System.out.println("您输入的不是浮点数!!");
}
scanner.close();
}
}
此处出现了问题:由于第一次输入的不是整数,这个数也当作了第二次的输入值。
查看Scanner类
ctrl+鼠标点击代码中的Scanner
练习
输入多个数字,求其总和与平均数,每输入一个数字用回车确认,通过输入非数字来结束并输出结果。
package tk.scanner;
import com.sun.org.apache.xerces.internal.util.SynchronizedSymbolTable;
import java.util.Scanner;
public class Demo05 {
public static void main(String[] args) {
//输入多个数字,求其总和与平均数,每输入一个数字用回车确认,通过输入非数字来结束并输出结果
Scanner scanner = new Scanner(System.in);
//计算和
double sum = 0.0;
int count = 0;
System.out.println("请输入一个值:");
while (scanner.hasNextDouble()) {
System.out.println("请输入一个值:");
double x = scanner.nextDouble();
count+=1;
sum+=x;
System.out.println("你已经输入了"+count+"个值,当前的sum为"+sum);
}
System.out.println("和为:"+sum);
System.out.println("平均值为:"+sum/count);
scanner.close();
}
}
2.顺序结构
- JAVA的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行。
- 顺序结构是最简单的算法结构。
- 语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法结构。
package tk.struct.sequence;
public class Demo01 {
public static void main(String[] args) {
System.out.println("hello");
System.out.println("world");
System.out.println("i");
System.out.println("am");
System.out.println("roger");
}
}
3.选择结构
if单选择结构
我们很多时候需要去判断一个东西是否可行,然后我们才去执行,这样一个过程在程序中用if语句来表示。
语法:
if(布尔表达式){
//如果布尔表达式为true将执行的语句
}
example
package tk.struct.selection;
import java.util.Scanner;
public class ifDemo01 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入内容:");
String s = scanner.nextLine();
if(s.equals("hello")){
System.out.println(s);
}else{
System.out.println("End");
}
scanner.close();
}
}
if双选择结构
那现在有个需求,公司要收购一个软件,成功了,给人支付100万元,失败了,自己找人开发。这样的需求用一个if就搞不定了,我们需要有两个判断,需要一个双选择结构,所以就有了if-else结构。
语法:
if(布尔表达式){
//如果布尔表达式的值为true
}else{
//如果布尔表达式的值为false
}
package tk.struct.selection;
import java.util.Scanner;
public class ifDome02 {
public static void main(String[] args) {
//考试分数大于60就是及格,小于60就是不及格。
Scanner scanner = new Scanner(System.in);
System.out.println("请输入学生成绩:");
double score = scanner.nextDouble();
if(score>=60){
System.out.println("及格");
}else{
System.out.println("不及格");
}
scanner.close();
}
}
请输入学生成绩:
99
及格
Process finished with exit code 0
if多选择结果
我们发现刚才的代码不符合实际情况,真实的情况还可能存在ABCD,存在区间多级判断。比如90-100就是A,80-90 就是B..等等,在生活中我们很多时候的选择也不仅仅只有两个,所以我们需要一个多选择结构来处理这类问题!
语法:
if(布尔表达式 1){
//如果布尔表达式1的值为true执行代码
}else if(布尔表达式 2){
//如果布尔表达式2的值为true执行代码
}else if(布尔表达式 3){
//如果布尔表达式3的值为true执行代码
}else (布尔表达式 4){
//如果布尔表达式4的值为true执行代码
}
package tk.struct.selection;
import java.util.Scanner;
public class ifDemo03 {
public static void main(String[] args) {
//if多选择
//if语句至多有 1 个else 语句,else 语句在所有的else if语句之后。if语句可以有若干个else if语句,它们必须在else语句之前。
//一旦其中一个 else if 语句检测为true,其他的else if 以及else 语句都将跳过执行。
Scanner scanner = new Scanner(System.in);
System.out.println("请输入学生成绩:");
double score = scanner.nextDouble();
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执行代码
}
}
package tk.struct.selection;
import java.util.Scanner;
//二分查找
public class ifDemo04 {
public static void main(String[] args) {
//如何最快寻找输入的1-100之内的数位于那个区间[0,50]或[51,100]
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你想输入的数字:");
double value = scanner.nextDouble();
if(value>=0 && value<=100){
if(value>=0 && value<=50){
System.out.println("你所判断的值在0-50区间");
}else{
System.out.println("你所判断的值在51-100区间");
}
}else{
System.out.println("您输入的值不在合法的区间内!");
}
scanner.close();
}
}
switch多选择结果
- 多选择结构还有一个实现方式就是switch case语句。
- switch case语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支。
- switch语句中的变量类型可以是:
- byte、short、int或者char
- 从Java SE 7开始switch支持字符串String类型了
- 同时case标签必须为字符串常量或字面量。
switch(expression){
case value :
//语句
break; //可选
case value :
//语句
break; //可选
//你可以有任意数量的case语句
default :
//语句 //可选
}
package tk.struct.selection;
import java.util.Scanner;
public class switchDemo01 {
public static void main(String[] args) {
char grade = 'C';
//case 穿透
//switch 匹配一个值
//break 跳出循环
switch (grade){
case 'A':
System.out.println("优秀");
break;
case 'B':
System.out.println("良好");
case 'C':
System.out.println("再接再厉");
case 'D':
System.out.println("挂科");
break;
default:
System.out.println("输入的内容非法!");
}
}
}
package tk.struct.selection;
public class switchDemo02 {
public static void main(String[] args) {
//从Java SE 7开始switch支持字符串String类型了
String name = "杨洪利";
switch (name){
case "白小飞":
System.out.println("只是昵称");
break;
case "杨洪利":
System.out.println("正是在下!");
break;
default:
System.out.println("找错了吧");
//反编译:查找.class编译后文件
//file--project structure
}
}
}
//编译后switchDemo.class文件
//看源码!好思想!
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package tk.struct.selection;
public class switchDemo02 {
public switchDemo02() {
}
public static void main(String[] args) {
String name = "杨洪利";
byte var3 = -1;
switch(name.hashCode()) {
case 26326951:
if (name.equals("杨洪利")) {
var3 = 1;
}
break;
case 29919724:
if (name.equals("白小飞")) {
var3 = 0;
}
}
switch(var3) {
case 0:
System.out.println("只是昵称");
break;
case 1:
System.out.println("正是在下!");
break;
default:
System.out.println("找错了吧");
}
}
}
4.循环结构
在Java5中引入了一种主要用于数组的增强型for循环。
while循环
- while是最基本的循环,它的结构为:
while(布尔表达式){
//循环内容
}
- 只要布尔表达式为true,循环就会一直执行下去。
- 我们大多数情况是会让循环停止下来的,我们需要一个让表达式失效的方式来结束循环。
- 少部分情况需要循环一直执行,比如服务器的请求响应监听等。
package tk.struct.selection;
public class whileDemo02 {
public static void main(String[] args) {
while (true){
//监听消息
//......
}
}
}
- 循环条件一直为true就会造成无限循环【死循环】,我们正常的业务编程中应该尽量避免死循环。会影响程序性能或者造成程序卡死奔溃!
package tk.struct.selection;
public class whileDemo01 {
public static void main(String[] args) {
//输出1-100
int a=1;
while(a<=100){
System.out.println(a);
a++;
}
}
}
package tk.struct.selection;
public class whileDemo03 {
public static void main(String[] args) {
//计算1+2+...+100
//高斯的故事
int a=1;
int sum=0;
while(a<=100){
sum+=a;
a++;
}
System.out.println(sum);
}
}
do while循环
-
对于while语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少执行一次。
-
do...while循环和while循环相似,不同的是,do...while循环至少会执行一次。
do{
//代码语句
}while(布尔表达式);
package tk.struct.selection;
public class doWhileDemo01 {
public static void main(String[] args) {
//计算1+2+...+100
//高斯的故事
int a = 1;
int sum = 0;
do {
sum += a;
a++;
}while (a <= 100);
System.out.println(sum);
}
}
-
While和do-While的区别:
- while先判断后执行。dowhile是先执行后判断!
- Do...while总是保证循环体会被至少执行一次!这是他们的主要差别。
package tk.struct.selection;
//while与do while比较
public class doWhileDemo02 {
public static void main(String[] args) {
int a =0 ;
while(a>0){
System.out.println(a);
}
System.out.println("===========");
do {
System.out.println(a);
}while (a>0);
}
}
for循环
- 虽然所有循环结构都可以用while或者do...while表示,但Java提供了另一种语句——for循环,使一些循环结构变得更加简单。
- for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构。
- for循环执行的次数是在执行前就确定的。语法格式如下:
for(初始化;布尔表达式;更新){
//代码语句
}
package tk.struct.selection;
public class forDemo01 {
public static void main(String[] args) {
int a=1;
while (a<=100){
System.out.println(a);
a++;
}
System.out.println("while循环结束!");
for (int i = 0; i < 100; i++) {
System.out.println(i);
}
System.out.println("for循环结束!");
/*
关于for循环有以下几点说明:
最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。
然后,检测布尔表达式的值。如果为true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句。执行一次循环后,更新循环控制变量(迭代因子控制循环变量的增减)。
再次检测布尔表达式。循环执行上面的过程。
*/
//死循环的一种
for(;;){
}
}
}
练习1:分别计算0-100的奇数和和偶数和
package tk.struct;
public class praDemo01 {
public static void main(String[] args) {
int oddSum=0;
int evenSum=0;
for (int i = 0; i <= 100; i++) {
if(i%2==0){
evenSum+=i;
}else{
oddSum+=i;
}
}
System.out.println("偶数和为:"+evenSum);
System.out.println("奇数和为:"+oddSum);
}
}
练习2:用while和for循环输出1-1000之间能被5整除的数,并每行输出三个
//while循环
//用while循环输出1-1000之间能被5整除的数,并每行输出三个
package tk.struct.selection;
public class praDemo02 {
public static void main(String[] args) {
int i=1;
int count=0;
String str=" ";
while (i<=1000){
if(i%5==0){
str=str+i;
//System.out.println(i);
count++;
}
if (count==3){
System.out.println(str);
count=0;
str=" ";
}
i++;
}
}
}
package tk.struct.selection;
//改进版:用while循环输出1-1000之间能被5整除的数,并每行输出三个
public class praDemo02 {
public static void main(String[] args) {
int i=1;
int count=0;
String str=" ";
while (i<=1000){
if(i%5==0){
str=str+"\t"+i;
//System.out.println(i);
count++;
}
if (count==3){
System.out.println(str);
count=0;
str=" ";
}
i++;
}
}
}
//for循环
//用for循环输出1-1000之间能被5整除的数,并每行输出三个
package tk.struct.selection;
public class praDemo03 {
public static void main(String[] args) {
int count=0;
String str=" ";
for (int i = 1; i <= 1000; i++) {
if (i%5==0) {
//System.out.println(i);
count++;
str=i+str;
}
if (count==3){
count=0;
System.out.println(str);
str="";
}
}
}
}
//改进版:用for循环输出1-1000之间能被5整除的数,并每行输出三个
package tk.struct.selection;
public class praDemo03 {
public static void main(String[] args) {
int count=0;
String str=" ";
for (int i = 1; i <= 1000; i++) {
if (i%5==0) {
//System.out.println(i);
count++;
str=i+"\t"+str;
}
if (count==3){
count=0;
System.out.println(str);
str="";
}
}
}
}
练习3:打印九九乘法表
//打印九九乘法表
package tk.struct.selection;
public class praDemo04 {
public static void main(String[] args) {
String str = "";
for (int i = 1; i < 10; i++) {
for(int j = 1;j <= i; j++){
str=str+j+"*"+i+"="+j*i;
}
System.out.println(str);
str="";
}
}
}
//改进版:打印九九乘法表
package tk.struct.selection;
public class praDemo04 {
public static void main(String[] args) {
String str = "";
for (int i = 1; i < 10; i++) {
for(int j = 1;j <= i; j++){
str=str+j+"*"+i+"="+j*i+"\t";
}
System.out.println(str);
str="";
}
}
}
print与println
package tk.struct.selection;
public class praDemo05 {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.print(i);
}
System.out.println("==================");
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
}
}
增强for循环
- 这里我们先只是见一面,做个了解,之后数组我们重点使用。
- Java5引入了一种主要用于数组或集合的增强型for循环。
- Java增强for 循环语法格式如下:
for(声明语句:表达式)
{
//代码句子
}
- 声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等。
- 表达式:表达式是要访问的数组名,或者是返回值为数组的方法。
package tk.struct.selection;
public class forDemo02 {
public static void main(String[] args) {
int[] numbers={10,20,30,55,66}; //定义了一个数组
//本质理解
for (int i=0;i<5;i++){
System.out.println(numbers[i]);
}
System.out.println("==============");
//for与数组结合的应用
for (int x:numbers){
System.out.println(x);
}
}
}
5.break && continue
break
- break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)
package tk.struct.selection;
public class breakDemo01 {
public static void main(String[] args) {
for (int i = 1; i < 100; i++) {
System.out.println(i);
if(i%10==0){
break;
}
}
System.out.println("白小飞牛呀!");
}
}
continue
- continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。
package tk.struct.selection;
public class continueDemo01 {
public static void main(String[] args) {
for (int i = 1; i < 12; i++) {
System.out.println(i);
if(i%10==0){
continue;
}
}
System.out.println("白小飞牛呀!");
}
}
goto
- goto关键字很早就在程序设计语言中出现。尽管goto仍是Java的一个保留字,但并未在语言中得到正式使用;Java没有goto。然而,在break和continue这两个关键字的身上,我们仍然能看出一些goto的影子——带标签的break和continue。
- “标签”是指后面跟一个冒号的标识符,例如: label
- 对Java来说唯一用到标签的地方是在循环语句之前。而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方。
package tk.struct.selection;
public class labelDemo01 {
public static void main(String[] args) {
//打印101-150之间所有的质数
//质数:除了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.println(i+" ");
}
}
}
6.练习
打印一个三角形
package tk.struct.selection;
public class praDemo06 {
public static void main(String[] args) {
for (int i = 1; i < 6; i++) {
for (int j = 5; j > i; j--) {
System.out.print(" ");
}
for (int k = 1; k <= i; k++) {
System.out.print("*");
}
for (int l = 1; l < i; l++) {
System.out.print("*");
}
System.out.println();
}
}
}
Debug
run--debug
四、Java方法
1.何谓方法
- System.out.println(),是类.对象.方法。
- Java方法是语句的集合,它们在一起执行一个功能。
- 方法是解决一类问题的步骤的有序组合
- 方法包含于类或对象中
- 方法在程序中被创建,在其他地方被引用
package tk.method;
//main函数
public class Demo01 {
public static void main(String[] args) {
int sum = add(1, 3);
System.out.println(sum);
System.out.println("============");
printModel();
}
//定义一个add方法
public static int add(int a,int b){
return a+b;
}
//定义一个printModel方法
public static void printModel(){
for (int i = 1; i < 6; i++) {
for (int j = 5; j > i; j--) {
System.out.print("1");
}
for (int k = 1; k <= i; k++) {
System.out.print("*");
}
for (int l = 1; l < i; l++) {
System.out.print("*");
}
System.out.println();
}
}
}
- 设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成1个功能,这样利于我们后期的扩展。
方法的命名规则?首字母小写和驼峰原则
2.方法的定义及调用
方法定义
- Java的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法:
- 方法包含一个方法头和一个方法体。下面是一个方法的所有部分:
- 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
- 返回值类型∶方法可能会返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType是关键字void。
- 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
- 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
- 形式参数:在方法被调用时用于接收外界输入的数据。
- 实参:调用方法时实际传给方法的数据。
- 方法体:方法体包含具体的语句,定义该方法的功能。
语法:
修饰符 返回值类型 方法名(参数类型 参数名){
...
方法体
...
return 返回值;
}
package tk.method;
public class Demo02 {
//main方法
public static void main(String[] args) {
int a = compare(10, 20);
System.out.println("最大值是:"+a);
System.out.println("===============");
int b = compare(10, 10);
System.out.println(b);
}
//比较大小
public static int compare(int num1,int num2){
int result = -1;
if(num1==num2){
System.out.println("两个值相等!");
return 0; //中止方法
}
if (num1>num2){
result = num1;
}else {
result = num2;
}
return result;
}
}
方法调用
-
调用方法:对象名.方法名(实参列表)
-
Java支持两种调用方法的方式,根据方法是否返回值来选择。
-
当方法返回一个值的时候,方法调用通常被当做一个值。例如:
int larger = max(30,40);
- 如果方法返回值是void,方法调用一定是一条语句。
system.out. print1n("Hello");
- 课后拓展了解:值传递和引用传递
3.方法重载
-
重载就是在一个类中,有相同的函数名称,但形参不同的函数。
-
方法的重载的规则:
- 方法名称必须相同。
- 参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)。
- 方法的返回类型可以相同也可以不相同。
- 仅仅返回类型不同不足以成为方法的重载。
-
实现理论:
- 方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。
package tk.method;
//方法重载
public class Demo03 {
public static void main(String[] args) {
int add = add(3, 4);
int add1 = add(3, 4, 5);
double add2 = add(2.1, 2.2);
double add3 = add(2.1, 2.2, 2.3);
System.out.println(add);
System.out.println("===========");
System.out.println(add1);
System.out.println("===========");
System.out.println(add2);
System.out.println("===========");
System.out.println(add3);
System.out.println("===========");
}
public static int add(int a,int b){
return a+b;
}
public static int add(int a,int b,int c){
return a+b+c;
}
public static double add(double a,double b){
return a+b;
}
public static double add(double a,double b,double c){
return a+b+c;
}
}
4.命令行传参
- 有时候你希望运行一个程序时候再传递给它消息。这要靠传递命令行参数给main()函数实现。
package tk.method;
public class Demo04 {
public static void main(String[] args) {
//args.length:数组长度
for (int i = 0; i < args.length; i++) {
System.out.println(i+"args:"+args[i]);
}
}
}
>> javac Demo04.java
>> cd ..
>> cd ..
>> java Demo04 this is yhl baixf
5.可变参数
- JDK 1.5开始,Java支持传递同类型的可变参数给一个方法。
- 在方法声明中,在指定参数类型后加一个省略号(.…)。
- 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
package tk.method;
//调用可变参数
//减小多余方法重载定义
public class Demo06 {
public static void main(String[] args) {
double add = add(2.1, 3.2);
System.out.println(add);
double add1 = add(1.0,5,6,8);
System.out.println(add1);
double add2 = add();
System.out.println(add2);
//new对象调用方法
System.out.println("=============");
Demo06 demo06 = new Demo06();
double add3 = demo06.add(1, 2);
System.out.println(add3);
}
//add方法
public static double add(double... numbers){
if (numbers.length==0){
System.out.println("null");
return 0;
}else {
double result = 0;
for (int i = 0; i < numbers.length; i++) {
result += numbers[i];
}
return result;
}
}
}
package tk.method;
//调用可变参数
public class Demo05 {
public static void main(String[] args) {
printMax(1,2,3,5,6);
printMax(new double[]{1,2,3,5});
}
public static void printMax(double...numbers){
if (numbers.length==0){
System.out.println("没有输入值!");
return;
}
double result=numbers[0];
for (int i = 1; i <numbers.length ; i++) {
if (numbers[i]>result){
result=numbers[i];
}
}
System.out.println("最大值是:"+result);
}
}
6.递归
- 递归就是:A方法调用A方法!就是自己调用自己
- 利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
- 递归结构包括两个部分:
- 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
- 递归体:什么时候需要调用自身方法。
package tk.method;
public class Demo07 {
public static void main(String[] args) {
int i = rankMultiply(4);
System.out.println(i);
System.out.println(rankMultiply(1));
System.out.println(rankMultiply(6));
}
//5! 5*4*3*2*1
//4! f(4)*f(3)*f(2)*1
public static int rankMultiply(int value){
if (value==1){
return 1;
}else {
return(value * rankMultiply(value - 1));
}
}
}
原理
栈机制:递归会带来大量的函数调用,产生很多额外的时间开销,对于深度大的情况,占用大量占用,程序会报错。
小计算可以用递归;大计算则不好!只是一种很好的算法机制!
7.练习
计算器:加减乘除
写四个方法:加减乘除
利用循环+switch进行交互
传递需要操作的数
输出结果
package tk.method;
import sun.awt.Symbol;
import java.util.Scanner;
//计算器
public class praDemo01 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你要输的第一个数:");
double v1 = scanner.nextDouble();
System.out.println("请输入你要进行的操作:");
String next = scanner.next();
System.out.println("请输入你要输的第二个数:");
double v2 = scanner.nextDouble();
scanner.close();
switch (next){
case "+":
System.out.println(add(v1,v2));
break;
case "-":
System.out.println(reduce(v1,v2));
break;
case "*":
System.out.println(multiply(v1,v2));
break;
case "/":
if (v2==0) {
System.out.println("除数不能为0!");
}else {
System.out.println(v1 + next + v2 + "=" + divide(v1, v2));
}
break;
default:
System.out.println("输入的符号有误!");
}
}
public static double add(double a,double b){
return a+b;
}
public static double reduce(double a,double b){
return a-b;
}
public static double multiply(double a,double b){
return a*b;
}
public static double divide(double a,double b){
return a/b;
}
}
package tk.method;
//改进版,000退出系统
import sun.awt.Symbol;
import java.util.Scanner;
//计算器
public class praDemo01 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(true) {
System.out.println("输入000即可退出此系统");
System.out.println("请输入你要输的第一个数:");
double v1 = scanner.nextDouble();
if (v1==000){
break;
}
System.out.println("请输入你要进行的操作:");
String next = scanner.next();
System.out.println("请输入你要输的第二个数:");
double v2 = scanner.nextDouble();
switch (next) {
case "+":
System.out.println(add(v1, v2));
break;
case "-":
System.out.println(reduce(v1, v2));
break;
case "*":
System.out.println(multiply(v1, v2));
break;
case "/":
if (v2 == 0) {
System.out.println("除数不能为0!");
} else {
System.out.println(v1 + next + v2 + "=" + divide(v1, v2));
}
break;
default:
System.out.println("输入的符号有误!");
}
}
scanner.close();
}
public static double add(double a,double b){
return a+b;
}
public static double reduce(double a,double b){
return a-b;
}
public static double multiply(double a,double b){
return a*b;
}
public static double divide(double a,double b){
return a/b;
}
}
五、数组
1.数组概述
- 数组是相同类型数据的有序集合。
- 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。
- 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。
2.数组声明创建
- 首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量
的语法:
dataType[] arrayRefVar;//首选的方法
或
dataType arrayRefVar[];//效果相同,但不是首选方法
- Java语言使用new操作符来创建数组,语法如下:
dataType[] arrayRefVar = new dataType[ arraySize];
- 数组的元素是通过索引访问的,数组索引从0开始。
- 获取数组长度:
arrays.length
package tk.array;
public class ArrayDemo01 {
//变量的类型 变量的名字 = 变量的值;
//数组类型‘
public static void main(String[] args) {
//int[] nums; 声明一个数组
//nums=new int[10]; 为数组开辟一个空间
int[] nums = new int[10];
for (int i = 0; i < 8; i++) {
nums[i]=i;
}
for (int i = 0; i < 10; i++) {
System.out.print(nums[i]);
}
}
}
内存分析
package tk.array;
public class ArrayDemo02 {
public static void main(String[] args) {
//1.声明一个数组
int[] numbers;
//2.创建一个数组
numbers = new int[10];
//3.给数组中的元素赋值
for (int i = 0; i <numbers.length ; i++) {
numbers[i]=1;
}
//4.取值
System.out.println(numbers[10]);
//Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10
// at tk.array.ArrayDemo02.main(ArrayDemo02.java:15)
}
}
数组的三种初始化
- 静态初始化
int[] a = {1,2,3};
Man[] mans={new Man(1,1),new Man(2,2)};
package tk.array;
public class ArrayDemo03 {
public static void main(String[] args) {
//静态初始化 创建+赋值
int[] a={1,2,3};
//Man[] mans={new Man(),new Man()};
System.out.println(a[0]);
System.out.println(a[1]);
}
}
- 动态初始化
int[] a = new int[2];
a[0]=1;
a[1]=2;
package tk.array;
public class ArrayDemo03 {
public static void main(String[] args) {
//动态初始化:包含默认初始值
int[] b=new int[10];
b[0]=1;
System.out.println(b[0]);
System.out.println(b[1]);
}
}
- 数组的默认初始化
- 数组是引用类型它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
package tk.array;
public class ArrayDemo03 {
public static void main(String[] args) {
//动态初始化:包含默认初始值
int[] b=new int[10];
b[0]=1;
System.out.println(b[0]);
System.out.println(b[1]);
}
}
数组的基本特点
- 其长度是确定的。数组一旦被创建,它的大小就是不可以改变的。
- 其元素必须是相同类型,不允许出现混合类型。
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型。
- 数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
数组边界
- 下标的合法区间:[0, length-1],如果越界就会报错;
public static void main(String[] args) {
int[] a=new int[2];
system.out.print1n(a[2]);
}
- ArraylndexOutOfBoundsException :数组下标越界异常!
小结
- 数组是相同数据类型(数据类型可以为任意类型)的有序集合。
- 数组也是对象。数组元素相当于对象的成员变量
- 数组长度的确定的,不可变的。如果越界,则报:ArrayIndexOutofBounds。
3.数组使用
普通For循环
package tk.array;
public class ArrayDemo04 {
public static void main(String[] args) {
int[] a = new int[10];
//遍历为a赋值
for (int i = 0; i < a.length; i++) {
a[i] = i;
}
//求和
int sum=0;
for (int i = 0; i < a.length; i++) {
sum+=a[i];
}
System.out.println("sum="+sum);
//求最大值
int max=a[0];
for (int i = 0; i < a.length ; i++) {
if (a[i]>max){
max=a[i];
}
}
System.out.println("max="+max);
}
}
For-Each循环
package tk.array;
public class ArrayDemo05 {
public static void main(String[] args) {
int[] a={1,2,3,6,9,5};
//JDK1.5
//但不支持按下标操作
for (int i : a) {
System.out.println(i);
}
}
}
数组作方法入参
数组作返回值
package tk.array;
public class ArrayDemo06 {
public static void main(String[] args) {
int[] array={1,5,3,6,9};
printArray(array);
System.out.println("===========");
printArray(reverse(array));
}
//打印数组方法
public static void printArray(int[] array){
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]);
}
}
//反转数组
public static int[] reverse(int[] array){
int[] result=new int[array.length];
for (int i = 0,j=array.length-1; i < array.length; i++,j=array.length-1-i) {
result[i]=array[j];
}
return result;
}
}
4.多维数组
-
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。
-
二维数组
int a[][] = new int[2][5];
- 解析:以上二维数组a可以看成一个两行五列的数组。
package tk.array;
public class ArrayDemo07 {
public static void main(String[] args) {
int[][] array=new int[4][2];
for (int i = 0; i <array.length ; i++) {
for (int j = 0; j < array[i].length; j++) {
array[i][j]=i+j;
}
}
System.out.println(array[0]);
System.out.println("===========");
printArray(array[0]);
System.out.println("===========");
System.out.println(array[0][0]);
System.out.println("===========");
printArray2(array);
}
//打印数组方法
public static void printArray(int[] array){
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
//遍历打印二维数组
public static void printArray2(int[][] array){
for (int i = 0; i < array.length; i++) {
for (int j = 0; j <array[i].length ; j++) {
System.out.print(array[i][j]);
}
}
}
}
三维数组
package tk.array;
public class ArrayDemo08 {
public static void main(String[] args) {
int[][][] array={{{1,2,3},{2,3,4}},{{1,2,3},{2,3,4}}};
for (int i = 0; i < array.length ; i++) {
for (int j = 0; j <array[i].length ; j++) {
for (int k = 0; k < array[i][j].length; k++) {
System.out.print(array[i][j][k]);
}
System.out.println();
}
}
}
}
5.Arrays
-
数组的工具类java.util.Arrays
-
由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。
-
查看JDK帮助文档
-
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而"不用"使用对象来调用(注意:是"不用”而不是"不能")
-
具有以下常用功能:
-
给数组赋值:通过fill方法。
-
对数组排序:通过sort方法,按升序。
-
比较数组:通过equals 方法比较数组中元素值是否相等。
-
查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作。
-
Array.toString()方法
//Array.toString()方法
public static String toString(int[] a) {
if (a == null)
return "null";
int iMax = a.length - 1;
if (iMax == -1)
return "[]";
StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++) {
b.append(a[i]);
if (i == iMax)
return b.append(']').toString();
b.append(", ");
}
}
返回的为String类型,可接收数据。
//自写Array.toString()方法
//造轮子
package tk.array;
import java.lang.reflect.Array;
import java.util.Arrays;
public class ArrayDemo09 {
public static void main(String[] args) {
double[] array=new double[10];
for (int i = 0; i <array.length ; i++) {
array[i]= Math.random();
}
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]);
}
System.out.println("\n");
System.out.println("==================");
System.out.println(Arrays.toString(array));
System.out.println("==================");
toString(array);
}
public static void toString(double[] array){
for (int i = 0; i < array.length; i++) {
if (i==0){
System.out.print("["+array[i]+",");
}else if (i==array.length-1){
System.out.print(array[i]+"]");
}else{
System.out.print(array[i]+",");
}
}
}
}
Array.sort()
sort方法只是对原数组进行排序,并未改变原数组长度,即对原数组长度没有影响,因此不需要定义一个数组接收它 ,即不需要返回值。
package tk.array;
import java.util.Arrays;
public class ArrayDemo10 {
public static void main(String[] args) {
int[] array={151,22,63,45,66,88,62,33,45,36,35};
Arrays.sort(array);//数组进行升序排序
System.out.println(array);
System.out.println("==========");
System.out.println(Arrays.toString(array));
}
}
Array.fill()
package tk.array;
import java.util.Arrays;
public class ArrayDemo11 {
public static void main(String[] args) {
int[] array={12,56,89,56,55,61,33,69};
Arrays.fill(array,2,4,0);// arrays,fromindex,toindex,value
System.out.println(Arrays.toString(array));
Arrays.fill(array,0);// arrays,value
System.out.println(Arrays.toString(array));
}
}
冒泡排序
-
冒泡排序无疑是最为出名的排序算法之一,总共有八大排序!
-
冒泡的代码还是相当简单的,两层循环,外层冒泡轮数,里层依次比较,江湖中人人尽皆知。
-
我们看到嵌套循环,应该立马就可以得出这个算法的时间复杂度为O(n2)。
package tk.array;
import java.util.Arrays;
public class ArrayDemo12 {
public static void main(String[] args) {
int[] array={12,5,6,89,56,45,26,98,42};
System.out.println(Arrays.toString(array));
int swap=0;
//冒泡排序
//1.比较数组中,两个相邻元素,小的放后面
//2.每次比较产生一个最小值
//3.下一轮减小依次排序
//4.依次循环,直到结束!
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length-i-1; j++) {
if (array[j]<array[j+1]){
swap=array[j+1];
array[j+1]=array[j];
array[j]=swap;
}
}
System.out.println(Arrays.toString(array));
}
}
}
//优化版
package tk.array;
import java.util.Arrays;
public class ArrayDemo12 {
public static void main(String[] args) {
int[] array={12,5,6,89,56,45,26,98,42};
System.out.println(Arrays.toString(array));
int swap=0;
//冒泡排序
//1.比较数组中,两个相邻元素,小的放后面
//2.每次比较产生一个最小值
//3.下一轮减小依次排序
//4.依次循环,直到结束!
for (int i = 0; i < array.length; i++) {
boolean flag=false;
for (int j = 0; j < array.length-i-1; j++) {
if (array[j]<array[j+1]){
swap=array[j+1];
array[j+1]=array[j];
array[j]=swap;
flag=true;
}
}
if (flag==false){
break;
}
System.out.println(Arrays.toString(array));
}
System.out.println("最终排序结果:"+Arrays.toString(array));
}
}
6.稀疏数组
- 当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀
- 疏数组来保存该数组。稀疏数组的处理方式是:
- 记录数组一共有几行几列,有多少个不同值
- 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模。
example
package tk.array;
public class ArrayDemo13 {
public static void main(String[] args) {
int[][] array=new int[11][10];
array[1][2]=1;
array[2][3]=2;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
System.out.print(array[i][j]+"\t");
}
System.out.println();
}
System.out.println("============");
int sum=0;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
if (array[i][j]!=0){
sum+=1;
}
}
}
//System.out.println(sum);
int count=0;
int[][] array01=new int[sum+1][3];
array01[0][0]=array.length;
array01[0][1]=array[0].length;
array01[0][2]=sum;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
if (array[i][j]!=0){
count++;
array01[count][0]=i;
array01[count][1]=j;
array01[count][2]=array[i][j];
}
}
}
for (int i = 0; i < array01.length; i++) {
for (int j = 0; j < array01[i].length; j++) {
System.out.print(array01[i][j]+"\t");
}
System.out.println();
}
System.out.println("==============");
int[][] array02=new int[array01[0][0]][array01[0][1]];
for (int i = 1; i < array01.length; i++) {
array02[array01[i][0]][array01[i][1]]=array01[i][2];
}
for (int i = 0; i < array02.length; i++) {
for (int j = 0; j < array02[i].length; j++) {
System.out.print(array02[i][j]+"\t");
}
System.out.println();
}
}
}
六、面向对象编程
Java核心思想,OOP。
1.初始面向对象
面向过程 && 面向对象
-
面向过程思想
- 步骤清晰简单,第一步做什么,第二步做什么...
- 面对过程适合处理一些较为简单的问题
-
面向对象思想
- 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
-
对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。
什么是面向对象
方法+属性=类!
- 面向对象编程(Object-Oriented Programming, oOP)
面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据。 - 抽象:核心思想。
- 三大特性:
- 封装
- 继承
- **多态 **
- 从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象。
- 从代码运行角度考虑是先有类后有对象。类是对象的模板。
2.方法回顾和加深
- 方法的定义
- 修饰符
- 返回类型
- break和return的区别
break:跳出switch,结束循环;return:结束方法。
- 方法名
- 参数列表
- 异常抛出
package oop.demo01;
//Demo01就是一个类
public class Demo01 {
//main方法
public static void main(String[] args) {
}
/*
修饰符 (返回值类型) 方法名 (数据类型 参数){
//方法体
return 返回值;
}
*/
public String sayHello(){
return "hello,world";
//System.out.println("1");
}
public void printString(String string){
System.out.println("string!");
return;
}
}
return结束方法,后面的代码将不会执行,也不允许执行。
- 方法的调用
- 静态方法
- 非静态方法
package oop.demo01;
public class Demo02 {
public static void main(String[] args) {
//不可以调用
//原因:static静态方法是和类一起创建的
// 而非静态方法h()是类实例化对象创建后才创建的
public static void g(){
h();
}
public void h(){
}
}
- 形参和实参
- 值传递和引用传递
package oop.demo01;
public class Demo03 {
public static void main(String[] args) {
//值传递
int a =1;
change(a);
System.out.println(a);
System.out.println("==========");
//引用传递:对象,本质还是值传递
Person person = new Person();
change(person);
System.out.println(person.name);
}
public static void change(int a){
a=10;
}
public static void change(Person person){
//person是一个对象:指向的---> Person person = new Person();这是一个具体的人,可以改变属性!
person.name="白小飞";
}
}
class Person{
String name;
}
- this关键字
this.代表当前类的,=后面的一般为传过来的值。
package oop.demo03;
public class Person {
String name;
//alt + insert 可快速调出构造器
//无参构造
public Person() {
this.name="王冰冰";
}
//有参构造
public Person(String name) {
this.name=name;
}
}
3.创建对象
类与对象的关系
对象,是具体的事物。类,是抽象的,是对对象的抽象。
- 类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物.
- 动物、植物、手机、电脑.…....
- Person类、Pet类、Car类等,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为
- 对象是抽象概念的具体实例
- 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。
- 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念.
创建与初始化对象
- 使用new关键字创建对象。
- 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
//Girlfriend类
package oop.demo02;
//女朋友类
public class Girlfriend {
//属性:字段
String name;
int age;
int height;
//方法
public void travel(){
System.out.println(this.name+"和白小飞去游玩了!");
}
}
//Application
package oop.demo02;
public class Application {
//类:抽象的;需要将其实例化为对象
//类实例化后会返回自己的对象!
//冰冰,书欣,lisa...对象就是一个个Girlfriend类的具体实例!
public static void main(String[] args) {
Girlfriend no1 = new Girlfriend();
Girlfriend no2 = new Girlfriend();
Girlfriend no3 = new Girlfriend();
System.out.print(no1.name);
System.out.print(no1.age);
System.out.print(no1.height);
System.out.println("=========");
no1.name="王冰冰";
no1.age=31;
no1.height=165;
no2.name="虞书欣";
no3.name="Lisa";
System.out.println("女友一号:"+no1.name+",年龄,"+no1.age+",身高:"+no1.height);
System.out.println("女友二号:"+no1.name);
System.out.println("女友三号:"+no1.name);
}
}
- 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下俩个特点:
- 1.必须和类的名字相同
- ⒉.必须没有返回类型,也不能写void
//Person类
package oop.demo03;
public class Person {
//一个类即使什么都不写,他也会存在一个方法
String name;
}
//Application
package oop.demo03;
public class Application {
//一个项目应该只存在一个main方法
public static void main(String[] args) {
//new 实例化一个对象
Person person = new Person();
System.out.println(person.name);
}
}
//编写构造器
//Person类
package oop.demo03;
public class Person {
//一个类即使什么都不写,他也会存在一个方法
String name;
//alt + insert 可快速调出构造器
//1.使用new关键字,本质是再调用构造器
//2.构造器用来初始化值
//无参构造
public Person() {
this.name="王冰冰";
}
//有参构造
public Person(String name) {
this.name=name;
}
}
//Application
package oop.demo03;
public class Application {
//一个项目应该只存在一个main方法
public static void main(String[] args) {
//new 实例化一个对象
Person person = new Person();
System.out.println(person.name);
Person person2 = new Person("虞书欣");
System.out.println(person2.name);
}
}
小结
-
类:
- 静态的属性——属性
- 动态的行为——方法
-
构造器:
- 和类名相同;
- 没有返回值。
-
作用:
- new 本质就是在调用构造器;
- 初始化对象的值。
-
注意点:
- 定义有参构造之后,如果使用无参构造,将会显示没有为该对象定义无参的构造函数。
4.对象的创建分析
//Pet类
package oop.demo04;
public class Pet {
String name;
int age;
//默认存在无参构造对属性进行初始化!
public void shout(){
System.out.println(this.age+"岁的"+this.name+"正在叫!");
}
}
//Application
package oop.demo04;
public class Application {
public static void main(String[] args) {
Pet dog = new Pet();
dog.name="旺财";
dog.age=3;
dog.shout();
Pet cat = new Pet();
}
}
对象的引用:
- 引用类型:基本类型(8种)
- 对象是通过引用来操作的,栈--->堆(内存地址)
5.面向对象的三大特征
封装
- 该露的露,该藏的藏
- 我们程序设计要追求 “高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
- 封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
- 记住这句话就够了: 属性私有,get/set
//Girlfriend
package oop.demo05;
//类 private:私有
public class Girlfriend {
//属性私有
private String name; //名字
private int age; //年龄
private String phone; //手机号
//提供一些可以操作这些属性的方法
//提供一些public的get、set方法
//赋值
public void setName(String name){
this.name=name;
}
//取值
public String getName(){
return this.name;
}
//alt+insert
//自动生成get、set方法
public int getAge() {
return age;
}
public void setAge(int age) {
if (age!=18){
System.out.println("冰冰永远18岁!");
this.age=18;
}else {
this.age = age;
}
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
//Application
package oop.demo05;
public class Application {
public static void main(String[] args) {
Girlfriend no01 = new Girlfriend();
System.out.println(no01.getName());
System.out.println("========");
no01.setName("王冰冰");
no01.setAge(31);//不行,冰冰18岁!
System.out.println("=========");
System.out.println(no01.getName()+"の年龄是"+no01.getAge()+"岁!");
}
}
封装的好处:
- 提高程序的交全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 系统可维护增加了
继承
final定义的类无法被继承!
- 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
- extands的意思是“扩展”。子类是父类的扩展。
- JAVA中类只有单继承,没有多继承!
- 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
- 继承关系的俩个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
- 子类和父类之间,从意义上讲应该具有"is a"的关系.
//Person
package oop.demo06;
//Person 人:父类
public class Person {
//一般属性才是私有的
//public
//protected
//default
//private
private String name;
public int money=100_0000;
public void study(){
System.out.println(this.name+"在学习");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//Bai
package oop.demo06;
//学生 is 人 : 派生类 , 子类
//子类继承了父类,就会拥有父类的全部方法!
public class Bai extends Person {
}
//Application
package oop.demo06;
public class Application {
public static void main(String[] args) {
Bai bai = new Bai();
bai.setName("白小飞");
bai.study();
System.out.println(bai.money);
}
}
- object类
crtl+h //调出继承树状结构
- super
super调用父类属性
//Pet
//在java中,所有的类默认继承object类
package oop.demo07;
public class Pet {
String name="宠物";
}
//Cat
package oop.demo07;
public class Cat extends Pet{
String name="小猫";
public void shout(String name){
System.out.println(name); //main函数调用这个方法时传进来的参数
System.out.println(this.name); //cat类中name的初始值
System.out.println(super.name); //父类pet中name的初始值
}
}
//Application
package oop.demo07;
public class Application {
public static void main(String[] args) {
Cat cat1 = new Cat();
cat1.shout("旺财");
}
}
super调用父类方法
//Pet
package oop.demo07;
public class Pet {
protected String name="宠物";
public void print(){
System.out.println("Pet");
}
}
//Cat
package oop.demo07;
public class Cat extends Pet{
private String name="小猫";
public void shout(String name){
System.out.println(name); //main函数调用这个方法时传进来的参数
System.out.println(this.name); //cat类中name的初始值
System.out.println(super.name); //父类pet中name的初始值
}
public void print(){
System.out.println("Cat");
}
public void test01(){
print(); //调用自己的print方法
this.print(); //同上,实质一样
super.print(); //调用父类方法
}
}
//Application
package oop.demo07;
public class Application {
public static void main(String[] args) {
Cat cat1 = new Cat();
cat1.shout("旺财");
cat1.test01();
}
}
但是当父类的方法设为私有时将无法通过super调用,同理,私有属性也无法调用!
无参构造器
//Pet
package oop.demo08;
public class Pet {
public Pet() {
System.out.println("Pet的无参构造器被执行了!");
}
}
//Cat
package oop.demo08;
public class Cat extends Pet{
public Cat() {
//隐藏代码:调用了父类的无参构造器!
super(); //必须要放在子类构造器的第一行
//this(); this也必须要放在第一行
System.out.println("Cat的无参构造器被执行了!");
}
}
//Application
package oop.demo08;
public class Application {
public static void main(String[] args) {
Cat cat = new Cat();
}
}
子类中隐藏存在着无参构造,在子类的无参构造中也隐藏存在着super()关键字,且super()只能放在第一行。
如果父类中不存在无参构造,那个子类也将不允许出现无参构造(因为子类的无参构造中隐藏着super()对父类的无参调用);父类只存在有参构造器时,可以通过super(参数)来使用。
小结
super注意点:
- super调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现在子类的方法或者构造方法中!
- super和 this不能同时调用构造方法!
vs this:
- 代表的对象不同:
- this:本身调用者这个对象
- super:代表父类对象的应用前提
- this:没哟继承也可以使用
- super:只能在继承条件才可以使用构造方法
- this():本类的构造
- super():父类的构造!
- 方法重写
静态方法重写
非静态方法重写
//Pet
package oop.demo09;
public class Pet {
public void shout(){
System.out.println("动物叫!");
}
}
//Cat
package oop.demo09;
//继承
public class Cat extends Pet {
//重写都是方法的重写,和属性无关
//alt+insert @Overwrite方法重写
//注释:有功能的注释!
@Override
public void shout() {
super.shout();
}
}
//Application
package oop.demo09;
public class Application {
public static void main(String[] args) {
//静态方法与非静态方法区别很大!
//静态方法:方法的调用只和左边,定义的数据类型有关
//非静态方法:重写
Cat cat01 = new Cat();
Pet cat02 = new Cat();
cat01.shout();
cat02.shout();
}
}
方法重写与重载
重载是在本类中进行;重写需要有继承关系;出现在子类与父类之间。
方法重写:overwrite
1.方法名必须相同
2.参数列表必须相同
3.修饰符:public>protected>default>private
4.抛出的异常:范围可以缩小,但不能扩大;
5.子类与父类的方法体不同!
为什么需要方法重写
父类的功能,子类可能不需要,或者不一定满足。
多态
-
即同一方法可以根据发送对象的不同而采用多种不同的行为方式。
-
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多。
-
多态存在的条件
- 有继承关系
-
子类重写父类方法
- 父类引用指向子类对象
-
注意:多态是方法的多态,属性没有多态性。
//Person
package oop.demo10;
public class Person {
public void run(){
System.out.println("father");
}
}
//Student
package oop.demo10;
public class Student extends Person{
@Override
public void run() {
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
//Application
package oop.demo10;
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Person();
//可以指向的引用类型就不确定了:父类的引用指向子类
//student能调用的方法都是自己或者继承父亲的!
Student student01 = new Student();
//person父类型,可以指向子类,但是不能调用子类独有的方法
Person student02 = new Student();
student01.run();
student02.run(); //子类重写了父类的方法,就会执行子类的方法体!
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
student01.eat();
//父类没有,子类有的方法需要通过强制转换降级才可以调用该方法!
((Student) student02).eat();
}
}
多态注意事项:
1.多态是方法的多态,属性没有多态。
2.父类和子类有联系 类型转换异常 ClassCastException!
3.存在条件:继承关系,方法需要重写,父类引用指向子类!Father f1=new Son();
不可以继承的方法
1.static 方法,属于类,他不属于实例
2.final 常量;
3.private方法;
- instanceof
package oop.demo12;
import oop.demo06.Person;
public class Application {
public static void main(String[] args) {
Student stu01 = new Student();
Teacher tea01 = new Teacher();
Person per01 = new Person();
Object obj01 = new Student();
//object > string
//object > person > student
//object > person > teacher
System.out.println(stu01 instanceof oop.demo12.Person);//true
System.out.println(tea01 instanceof oop.demo12.Person);//true
System.out.println(stu01 instanceof Object);//true
System.out.println(tea01 instanceof Object);//true
//System.out.println(stu01 instanceof String); 编译报错
//System.out.println(tea01 instanceof String); 编译报错
System.out.println(per01 instanceof Object);//true
//System.out.println(per01 instanceof Student); 编译报错
System.out.println(stu01 instanceof oop.demo12.Person);//true
System.out.println(stu01 instanceof oop.demo12.Person);//true
System.out.println(obj01 instanceof String);//false
System.out.println(obj01 instanceof oop.demo12.Person);//true
}
}
对象的类型转换
//Person
package oop.demo12;
public class Person {
public static void run(){
System.out.println("run");
}
}
//Student
package oop.demo12;
public class Student extends Person{
public static void study(){
System.out.println("study");
}
}
//Application
package oop.demo12;
public class Application {
public static void main(String[] args) {
//类型之间的转换 高---》低
//高转低
Person student = new Student();
student.run();
//student.study();编译报错 不能调用父类没有定义的方法
//将这个对象转换为Student类型后,我们就可以使用student类型的方法了
((Student) student).study();
//将低级的类转换为高级的类
Student stu1 = new Student();
Person per1 = stu1;
//但是子类转换为父类后可能会丢失一些子类的方法
//per1.study(); 编译报错
//仍可以通过强制类型转换
((Student)stu1).study();
}
}
小结
1.父类引用指向子类的对象
2.把子类转换为父类,向上转型,直接新建一个父类对象,直接赋值即可。
3.把父类转为子类,向下转型,需要强制转换。
4.方便方法的抽象,减少重复的代码,简洁。
6.stastic
package oop.demo13;
public class Student {
public static String name; //静态属性 多线程
public int age; //非静态属性
public static void run(){
System.out.println("run");
}
public void say(){
System.out.println("say");
}
public static void main(String[] args) {
Student student = new Student();
System.out.println(Student.name);
//非静态属性不可以直接输出类变量!!
//System.out.println(Student.age);编译报错
System.out.println(student.name);
System.out.println(student.age);
System.out.println("===============");
student.say();
student.run();
//同理,非静态方法也不可以通过类方法的形式调用!
//Student.say(); 编译出错
Student.run();
}
}
匿名代码块、静态代码块与内存分析
1.静态代码块只执行一次,和类一起加载
2.匿名代码块和对象一起产生,但是在方法前执行!用来赋初始值~
3.构造器(类的方法,创建对象时生成,但是执行晚于匿名代码块)
package oop.demo13;
public class Teacher {
//1.只执行一次,和类一起加载
static {
System.out.println("静态代码块");
}
//2.和对象一起产生,但是在方法前执行!用来赋初始值~
{
System.out.println("匿名代码块");
}
//3
public Teacher() {
System.out.println("构造器");
}
public static void main(String[] args) {
Teacher teacher = new Teacher();
System.out.println("===============");
Teacher teacher1 = new Teacher();
}
}
静态导入包
package oop.demo13;
import static java.lang.Math.PI;
import static java.lang.Math.random;
public class APP {
public static void main(String[] args) {
//导入前调用
System.out.println(Math.random());
//导入后调用
System.out.println(PI);
System.out.println(random());
}
}
7.抽象类
//A
package oop.demo14;
//抽象类: 类 extends: 单继承 (但是接口可以多继承!!)
public abstract class A {
//约束 ~ 有人帮我们实现!
public void run(){
System.out.println("A");
}
//abstract , 抽象方法,只有方法名字,没有方法的实现!
public abstract void say();
}
//B
package oop.demo14;
public class B extends A{
//继承抽象类的子类必须要重写父类的抽象方法,除非她也是抽象类~
@Override
public void say() {
System.out.println("say");
}
}
小结
实质:抽象的抽象!
1.不能new这个抽象类
2.抽象类中可以写普通的方法
3.抽象方法必须在抽象类中
4.抽象类不可以被new为一个对象
思考:抽象类是否存在构造器?存在!
抽象类存在的意义?提高开发效率
8.接口
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)都有!
接口:只有规范!
- 接口就是规范,定义的是一组规则。
- 接口的本质是契约!
- OO的精髓是,是对对象的抽象,最能体现这一点的是接口。
- 声明类的关键字是class;声明接口的关键字是interface。
- 接口实现了约束和实现的分离,面向接口编程!
//UserService
package oop.demo15;
//interface 定义的关键字。 接口都需要有实现类
public interface UserService {
//常量 public static final
int age=99;
//接口中的所有定义的方法其实都是公共抽象的 public abstract
void add();
void delete();
void query();
void update();
}
//TimeService
package oop.demo15;
public interface TimeService {
void timmer();
}
//UserServiceImpl
package oop.demo15;
//抽象类:extends 单继承
//类 可以实现接口:implements 接口 多继承
//实现了接口的类,必须要重写接口的方法
//多继承 利用接口实现多继承
public class UserServiceImpl implements UserService,TimeService{
@Override
public void add() {
}
@Override
public void delete() {
}
@Override
public void query() {
}
@Override
public void update() {
}
@Override
public void timmer() {
}
}
作用
1.接口是一个约束,实现了约束和实现的分离!
2.定义了一些方法,让不同的人实现。
3.接口中的所有定义的方法其实public abstract。
4.接口中的属性默认 public static final。
5.接口不能被实例化。
6.通过implement可以实现接口多继承!
9.内部类
内部类就是在一个类的内部在定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。
成员内部类
//Outer && Inner
package oop.demo16;
import java.sql.SQLOutput;
public class Outer {
private String name="IU知恩";
public void out(){
System.out.println("这是外部类的方法!");
}
public class inner{
public void in(){
System.out.println("这是内部类方法!");
}
//内部类方法:调用外部类私有变量
public void getPri(){
System.out.println(name);
}
}
}
//APP
package oop.demo16;
public class App {
public static void main(String[] args) {
//创建外部类对象
Outer outer = new Outer();
outer.out();
//创建内部类对象
Outer.inner inner = outer.new inner();
inner.in();
inner.getPri();
}
}
静态内部类
static是随class创建时产生的,所以内部类是无法调用外部类的属性值的,他们的创建是在class之后的。
而且 Java 中普通内部类为何不能有static数据和static字段,也不能包含嵌套类。
局部内部类
package oop.demo19;
public class Outer {
//局部内部类
public void run(){
System.out.println("run");
class A{
public void say(){
System.out.println("hello");
}
}
}
public static void main(String[] args) {
Outer outer = new Outer();
outer.run();
}
}
匿名内部类
package oop.demo19;
public class APP {
public static void main(String[] args) {
//匿名内部类
//匿名对象
//没有名字初始化类,不用将实例保存到变量中
new A().pr();
UserService hello = new UserService() {
@Override
public void pr() {
System.out.println("hello");
}
};
hello.pr();
}
}
class A{
public void pr() {
System.out.println("hi");
}
}
interface UserService{
void pr();
}
拓展
- 一个Java类中可以有多个class类,但只能有一个public class。
- 一般用于测试 main()。
package oop.demo18;
public class Outer {
}
//一个Java类中可以有多个class类,但只能有一个public class
//一般用于测试 main()
class A{
public static void main(String[] args) {
}
}
七、异常机制
1.什么是异常
- 实际工作中,遇到的情况不可能是非常完美的。比如:你写的某个模块,用户输入不一定符合你的要求、你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等。我们的程序再跑着,内存或硬盘可能满了。等等。
- 软件程序在运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是:Exception,意思是例外。这些,例外情况,或者叫异常,怎么让我们写的程序做出合理的处理。而不至于程序崩溃。
- 异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。
- 异常发生在程序运行期间,它影响了正常的程序执行流程。
package Exception.demo01;
public class App {
public static void main(String[] args) {
System.out.println(9/0);
}
}
package Exception.demo01;
public class App {
public static void main(String[] args) {
new App().a();
}
public void a(){
b();
}
public void b(){
a();
}
}
异常分类
-
检查性异常
语法异常,编译异常.....
-
运行时异常
-
异常
2.异常体系结构
- Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。
- 在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。
错误(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通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。
3.Java异常处理机制
-
抛出异常
-
捕获异常
4.处理异常
异常处理五个关键字
- try、catch、finall
package Exception.demo01;
public class App {
public static void main(String[] args) {
//ctrl+alt+t 快捷键
//假设要捕获多个异常:从小到大!
try { //try 监控区域
new App().a();
} catch (Error e) { //catch(要捕获的异常类型) 捕获异常
System.out.println("ERROR");
}catch (Exception e) {
System.out.println("Exception");
}catch (Throwable e) {
System.out.println("Throwable");
} finally { //处理善后工作
System.out.println("完成");
}
//finally可以不写,一般用于异常时 对 IO等资源关闭!
}
public void a(){
b();
}
public void b(){
a();
}
}
- throw、throws
主动的抛出异常。一般在方法中使用
//throw
package Exception.demo02;
public class App {
public static void main(String[] args) {
App app = new App();
app.divide(2,0);
}
//主动的抛出异常。一般在方法中使用
public void divide(int a,int b){
if (b == 0) {
throw new ArithmeticException();
}
}
}
package Exception.demo03;
public class App {
public static void main(String[] args) {
try {
new App().divide(1,0);
} catch (ArithmeticException e) {
e.printStackTrace();
}
}
//假设方法内部无法处理这个异常,方法上抛出异常
public void divide(int a,int b) throws ArithmeticException{
if (b == 0) {
throw new ArithmeticException();
}
}
}
5.总结
- 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
- 在多重catch块后面,可以加一个catch (Exception)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch,处理潜在的异常
- 尽量去处理异常,切忌只是简单地调用printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句块去释放占用的资源
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)