JavaSE笔记
Markdown学习
标题:
二级标题
三级标题
四级标题
字体
粗体
斜体
斜体加粗
删除线
引用
学习markdown
分割线
图片
超链接
列表
- a
- b
- c
- a
- b
- c
表格
名字 | 性别 | 生日 |
---|---|---|
陈伟强 | 男 | 2002 |
代码
public
windows常用快捷键
ctrl+C:复制
ctrl+V:粘贴
ctrl+A:全选
ctrl+X:剪切
ctrl+Z:撤销
ctrl+S:保存
ALT+F4:关闭窗口
shift+delete:永久删除
windows+R:打开运行窗口
Ctrl+shift+esc:打开任务管理器
windows+tab:切换界面
Dos命令
常用的Dos命令
#盘符切换
D:(英文模式下)
#查看当前目录下的所以文件
dir
#切换目录
cd /d f:(英文模式下)
cd /d E:\IDE
cd ..(返回上一目录)
#清空屏幕
cls (clear screan)
#退出终端
exit
#查看电脑的ip
ipconfig
#打开应用
##计算机(calc)
##画图(mspaint)
##记事本(notepad)
#ping命令
ping www.****.com
#文件操作
##创建目录
md test
##目录里建文件
cd>*.txt
##删除文件
del
##移除目录
rd test
Java入门
java特性和优势
- 简单性
- 面向对象
- 可移植性
- 高性能
- 分布式
- 动态性
- 多线程
- 安全性
- 健壮性
java的三大版本
-
Write Once、Run Anywhere(编写一次、所有电脑都能跑)
-
javaSE:标准版(桌面控制、控制台开发·····)重点
-
javaME:嵌入式开发(手机、小家电·····) -
javaEE:E企业级开发(web端、服务器开发······)
JDK、JRE、JVM
- JDK:Java Development Kit
- JRE:Java Runtime Environment
- JVM:Java Virtual Machine
卸载JDK
- 删除java的安装目录
- 删除JAVA_HOME
- 删除path下关于java的目录
- java -version
安装JDK
- 百度搜索JDK8,找到下载地址
-
同意协议
-
下载电脑对应的版本
-
双击安装JDK
-
记住安装的路径
-
配置环境变量
- 我的电脑-->右键-->属性
- 环境变量-->JAVA_HOME
- 配置path变量
-
测试JDK是否安装成功
- 打开cmd
- java -version
HelloWorld
-
随便新建一个文件夹,存放代码
-
新建一个java文件
- 文件后缀名为.java
- Hello.java
-
编写代码
public class Hello{ public static void main(String[] args){ System.out.print("Hello,world!"); } }
-
编译javac java文件,会生成一个class文件
-
运行class文件,java class文件
注意事项
- 每个单词的大小不能出现问题,Java是大小写敏感的
- 尽量使用英文
- 文件名和类名必须保证一致,并且首字母大写
- 符号不要使用中文
Java程序运行机制
- 编译型(操作。例:c\c++.....)
- 解释型(网页、速度型脚本。例:java、python····)
- 程序运行机制
IDEA破解版下载
下载链接:IDEA破解版
提取码:lihr
教程:教程地址
IDEA里的一些基本设置
-
项目结构
-
字体的设置
Java基础(base)
注释
-
注释并不会被执行,是给我们写代码的人看的
-
书写注释是一个非常好的习惯
-
Java中的注释有三种:
-
单行注释
//单行注释
-
多行注释
/*多行注释 多行注释 多行注释 多行注释 */
-
JavaDoc:文档注释
/** *@Description HelloWorld *@author */
-
标识符
关键字
- Java所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。
标识符注意点
数据类型
强类型语言
- 要求变量的使用要严格符合规定,所有变量都必须先定义后才能使用
弱类型语言
Java的数据类型分为两大类
- 基本数据类型(primitive type)
- 数值类型
- 整数类型(整数)
- byte占1个字节
- short占2个字节
- int占4个字节
- long占8个字节(要在数字后面加“L”)
- 浮点类型(小数)
- float占4个字节(要在数字后面加“F”)
- double占8个字节
- 字符类型(一个字)
- char占2个字节
- 整数类型(整数)
- boolean类型
- 占1位其值只有true和false两个
- 数值类型
- 引用数据类型(reference type)
- 类
- String
- 接口
- 数组
- 类
数据类型的拓展
整数拓展:进制
-
二进制(开头‘0b’)
0b10 = 2
-
十进制
-
八进制(开头‘0’)
010 = 8
-
十六进制(开头‘0x’)
0x10 = 16
浮点数拓展
银行业务怎么表示?钱
BigDecimal 数学工具类
- float 有限 离散 舍入误差 大约 接近但不等于
- double
- 最好完全避免使用浮点数进行比较!!!
- 最好完全避免使用浮点数进行比较!!!
- 最好完全避免使用浮点数进行比较!!!
float f = 0.1f; //0.1
double d = 1.0/10; //0.1
System.out.print(f == d); //false
float d1 = 21451351552f;
float d2 = d1 + 1;
System.out.print(d1 == d2); //true
字符拓展
char c1 = 'a';
char c2 = '中';
System.out.print(c1); //a
System.out.print((int)c1); //强制类型转换 //97
System.out.print(c2); //中
System.out.print((int)c2); //强制类型转换 //20013
//所有的字符本质还是数字
//编码 Unicode -->表(97 = a,65 = A ) 2字节 0-65536
//U0000 ~ UFFFF
char c3 = '\u0061';
System.out.print(c3); //a
- 转义字符
布尔值拓展
boolean flag = true;
if(flag == true){} //新手
if(flag){} // 老手
//两个代码一样
**//Less is More! 代码要精简易读
类型转换
-
由于Java是强类型语言,所以要进行有些运算的时候,需要用到类型转换。
低------------------------------------------------->高 byte,short,char-->int-->long-->float-->double
-
运算中,不同类型的数据先转化为同一类型,然后进行运算。
int i = 128; byte b = (byte)i; //内存溢出 double c = i; //强制转换 (类型)变量名 高-->低 //自动转换 低-->高 System.out.print(i); //128 System.out.print(b); //-128 System.out.print(c); //128.0
注意点
-
不能对布尔值进行转换
-
不能把对象类型转换为不相干的类型
-
在把高容量转换到低容量的时候,强制转换
-
转换的时候可能存在内存溢出,或精度问题
-
-
操作比较大的数的时候,注意溢出问题
//JDK7新特性,数字之间可以用下划线分割 int money = 10_0000_0000; int years = 20; int total = money*years; //计算的时候溢出了 long total2 = money*years; //默认是int,转换之前已经存在问题了 System.out.print(money); //1000000000 System.out.print(total); //-1474836480 System.out.print(total2); //-1474836480 long total3 = money*((long)years);//先把一个数转换为Long System.out.print(total3); //20000000000
变量、常量、作用域
变量
- 变量是什么:就是可以变化的量!
- Java是一种强类型语言,每个变量都必须声明其类型。
- Java变量是程序中最基本的存储单位,其要素包括变量名,变量类型和作用域。
注意事项:
- 每个变量都有类型,类型可以是基本类型,也可以是引用类型。
- 变量名必须是合法的标识符。
- 变量声明是一条完整的语句,因此每一个声明都必须以分号结束。
//int a,b,c; *不建议
//int a=1,b=2,c=3; *不建议 //程序的可读性
String name = "cwq";
char x = 'X';
double pi = 3.14;
作用域
变量作用域
- 类变量
- 实例变量
- 局部变量
public class Variable{
static int allClicks=0; //类变量 static(静态的)
String str="hello world"; //实例变量
public void method(){
int i = 0; //局部变量
}
}
例:
public class Demo{
//类变量 static
static double salary = 2500;
//属性:变量
//实例变量:从属于对象;如果不自行初始化,这个类型的默认值 0 0.0 0000
//布尔值:默认是false
//除了基本类型,其余的默认值都是unll;
String name;
int age;
//main方法
public static void main(String[] args){
//局部变量:必须声明和初始化值
int i = 10;
System.out.println(i);
//变量类型 变量名字 = new Demo();
Demo demo = new Demo();
System.out.println(demo.age);
System.out.println(demo.name);
//类变量 static
System.out.println(salary);
}
//其他方法
public void add(){
System.out.println(i);
}
}
常量
-
常量(Constant):初始化(initialize)后不能再改变值!不会变动的值。
-
所谓常量可以理解成一种特殊的变量,它的值被设定后,在程序运行过程中不允许被改变。
final 常量名=值; final double PI=3.14;
-
常量名一般使用大写字母。
public class Demo1{
//修饰符,不存在先后顺序(static,public····)
static final double PI = 3.14;
public static void main(String[] args){
System.out.println(PI);
}
}
变量的命名规范
运算符(operator)
- Java语言支持如下运算符:
- 算术运算符:+, - , *, /, %, ++, --
- 赋值运算符: =
- 关系运算符:>, <, >=, <=, ==, != , instanceof //返回的结果:正确,错误 布尔值
- 逻辑运算符:&&, ||, !
- 位运算符:&, |, ^, ~, >>, <<, >>>(了解!!!)
- 条件运算符:?, :
- 扩展赋值运算符:+=, -=, *=, /=
自增自减运算符
public class Demo2{
public static void main(String[] args){
//++ -- 自增,自减 一元运算符
int a = 3;
int b = a++; //执行完这行代码后,先给b赋值,再自增
//a++ a = a+1
System.out.println(a); //4
//++a a = a+1
int c = ++a; //执行完这行代码前,先自增,再给c赋值
System.out.println(a); //5
System.out.println(b); //3
System.out.println(c); //5
}
}
逻辑运算符
public class Demo3{
public static void main(String[] args){
// 与 (and) 或 (or) 非(取反)
boolean a = true;
boolean b = false;
System.out.println("a && b:"+(a&&b)); //逻辑与运算:两个变量为真,结果才是true
System.out.println("a || b:"+(a||b)); //逻辑或运算:两个变量有一个为真,则结果才是true
System.out.println("!(a && b):"+!(a&&b)); //逻辑非运算:真变为假,假变为真
//短路运算
int c = 5;
boolean d = (c<4)&&(c++<4); //运算到(c<4)是false的时候短路了,不运行与后面的代码
System.out.println(d); //false
System.out.println(c); //5
}
}
位运算符
public class Demo4{
public static void main(String[] args){
/*
A = 0011 1100
B = 0000 1101
------------------------
A&B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001
~B = 1111 0010
2*8 = 16 2*2*2*2
效率极高!!!
<< *2
>> /2
0000 0000 0
0000 0001 1
0000 0010 2
0000 0100 4
0000 1000 8
0001 0000 16
*/
System.out.println(2<<3); //16 二进制的2向左移动3位
}
}
扩展赋值运算符
public class Demo5{
public static void main(String[] args){
int a = 10;
int b = 20;
a+=b; //a = a+b;
System.out.println(a); //30
a-=b; //a = a-b;
//字符串连接符 + , String
System.out.println(a+b); //30 这里为int类型
System.out.println(a+b+""); //30 先相加这里为String类型
System.out.println(""+a+b); //1020
}
}
三元运算符
public class Demo6{
public static void main(String[] args){
//x ? y : z
//如果x == true,则结果为y,否则结果为z
int score = 50;
String type = score <60?"不及格":"及格"; //必须掌握
System.out.println(type); //不及格
}
}
包机制
-
为了更好地组织类,Java提供了包机制,用于区别类名的命名空间。
-
包语句的语法格式为:
package pkg1[.pkg2[.pks3···]];
-
一般利用公司域名倒置作为报名:www.baidu.com package com.baidu.www
-
为了能够使用某一包的成员,我们需要在Java程序中明确导入该包。使用"import"语句可完成次功能
import java.util.Date; import pkg1[.pkg2[.pks3···]]; import java.util.*; //'*'通配符
JavaDoc生成文档
Java SE 帮助文档:https://docs.oracle.com/javase/8/docs/api/
通过命令行生成JavaDoc文档
-
先在Java里写如参数信息
例:
package cwq; /** *@author cwq *@version 1.0 *@since 1.8 */ public class Doc{ String name; /** *@author cwq *@param name *@return *@throws Exception */ public String test(String name) throws Exception{ return name; } }
-
在IDEA里找到程序的位置:
) -
在导航栏里输入cmd进入终端
) -
在里面输入
javadoc -encoding UTF-8 -charset UTF-8 Doc.java
通过IDEA生成JavaDoc文档
1.创建一个存放JavaDoc的文件夹。
2.打开idea上方工具(Tools),生成JavaDoc文档(Generate JavaDoc...)。
3.选择我们要生成的类。
4.在output directory中选择我们刚才建立的存放JavaDoc的文件路径。
5.然后再Locale和其他命令行参数输入如下代码,以防止中文带来的乱码。
6.进入存放JavaDoc 文件中点击index.html即可看到我们生成的JavaDoc文档。
Java流程控制
Scanner对象
-
我们可以通过Scanner类来获取用户的输入。
-
基本语法:
Scanner s = new Scanner(System.in);
-
通过Scanner类的next()与nextLine()方法获取输入的字符串,在读取前我们一般需要使用hasNext()与hasLine()判断是否还有输入的数据。
import java.util.Scanner; public class Demo1{ 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(); } }
import java.util.Scanner;
public class Demo{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int i = 0;
float f = 0.0f;
System.out.println("请输入整数:");
//如果····那么··
if(scanner.hasNextInt()){
i = scanner.NextInt();
System.out.println("整数数据:"+i);
}else{
System.out.println("输入的不是整数数据!");
}
System.out.println("请输入小数:");
//如果····那么··
if(scanner.hasNextFloat()){
f = scanner.NextFloat();
System.out.println("小数数据:"+f);
}else{
System.out.println("输入的不是小数数据!");
}
scanner.close();
}
}
Scanner例题
- 我们可以输入多个数字,并求其总和与平均数,每输入一个数字就用回车确认,通过输入非数字来结束输入并输出执行结果;
import java.util.Scanner;
public class Demo{
public static void main(String[] args){
//我们可以输入多个数字,并求其总和与平均数,每输入一个数字就用回车确认,通过输入非数字来结束输入并输出执行结果;
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);
System.out.println(m+"个数的平均值是"+(sum / m);
scanner.close();
}
}
顺序结构
-
Java的基本结构就是顺序结构,除非特别指出,否则就按照顺序一步一步执行。
-
顺序结构是最简单的算法结构。
-
语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本结构。
选择结构
- if单选择结构
- if双选择结构
- if多选择结构
- 嵌套的if结构
- switch多选择结构
if单选择结构
-
我们很多时候需要去判断一个东西是否可行,然后我们才去执行,这样一个过程在程序中用if语句来表示
-
语法:
if(布尔表达式){ //如果布尔表达式为true将执行的语句 }
例:
import java.util.Scanner; public class IfDemo{ public static void main(String[] args){ Scanner scanner = new Scanner(System.in); System.out.println("请输入内容:"); String s = scanner.NextLine(); //equals:判断字符串是否相等 if(s.equals("Hello")){ System.out.println(s); } System.out.println("End"); scanner.close(); } //如果输入Hello 输出 Hello End ;否则只输出End }
if双选择结构
-
语法:
if(布尔表达式){ //如果布尔表达式为true将执行的语句 }else{ //如果布尔表达式为false将执行的语句 }
例:
import java.util.Scanner; public class IfDemo1{ public static void main(String[] args){ //考试分数大于60就是及格,小于60分就不及格 Scanner scanner = new Scanner(System.in); System.out.println("请输入成绩:"); int score = scanner.NextInt(); if(score >60){ System.out.println("及格"); }else{ System.out.println("不及格"); } scanner.close(); } }
if多选择结构
-
语法:
if(布尔表达式1){ //如果布尔表达式1为true将执行的语句 }else if(布尔表达式2){ //如果布尔表达式2为true将执行的语句 }else if(布尔表达式3){ //如果布尔表达式3为true将执行的语句 }else{ //如果以上布尔表达式都不为true将执行的语句 }
例:
import java.util.Scanner; public class IfDemo2{ public static void main(String[] args){ Scanner scanner = new Scanner(System.in); System.out.println("请输入成绩:"); int score = scanner.NextInt(); if(score == 100){ System.out.println("恭喜满分"); }else if(score<100 && score>=90){ System.out.println("A"); }else if(score<90 && score>=80){ System.out.println("B"); }else if(score<80 && score>=70){ System.out.println("C"); }else if(score<70 && score>=60){ System.out.println("D"); }else if(score<60 && score>=0){ System.out.println("不及格"); }else{ System.out.println("成绩不合法"); } scanner.close(); } }
嵌套的if结构
-
语法:
if(布尔表达式1){ //如果布尔表达式1为true将执行的语句 if(布尔表达式2){ //如果布尔表达式2为true将执行的语句 } }
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: //可选 //语句 }
例:
public class SwitchDemo1{ 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("未知等级"); break; } } }
- switch语句中的变量类型可以是:
-
从Java SE 7开始
-
switch 支持字符串String类型了
public class SwitchDemo2{ public static void main(String[] args){ char name = '陈伟强'; //JDK7的新特性,表达式结果可以是字符串!!! //字符的本质还是数字 switch(name){ case '陈伟强': System.out.println("陈伟强"); break; //可选 case '刘庆峰': System.out.println("刘庆峰"); break; default: System.out.println("未知名称"); break; } } }
反编译 java---class(字节码文件)----反编译(IDEA)
- 打开项目结构
- 复制Project compiler output的地址,我的电脑地址栏粘贴打开
- IDEA打开文件夹
-
把2的文件复制过去
5.在IDEA中打开,右边的文件就是代码的反编译
一个对象都有对应的hashCode
循环结构
-
while循环
-
do····while循环
-
for循环
-
在Java5中引入了一种主要用于数组的增强型for循环。
while循环
-
while是最基本的循环,它的结构为:
while(布尔表达式){ //循环内容 }
-
只要布尔表达式为true,循环就会一直执行下去。
-
我们大多数情况是会让循环停止下来的,我们需要一个让表达式失效的方式来结束循环。
-
少部分情况需要循环一直执行,比如服务器的请求响应监听等。//定时检测
-
循环条件一直为true就会造成无限循环{死循环},我们正常的业务编程中应该尽量避免死循环。会影响程序性能或者造成程序卡死崩溃!
public class WhileDemo1{ public static void main(String[] args){ //输出1~100 int i = 0; while(i<100){ i++; System.out.println(i); } } }
do···while循环
-
对于while语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少执行一次。
-
do···while循环和while循环相似,不同的是,do···while循环至少执行一次。
do{ //代码语句 }while(布尔表达式);
例:
public class DoWhileDemo1{ public static void main(String[] args){ //输出1~100相加 int i = 0; //初始化 int sun = 0; do{ sum = sum + i; i++; //迭代 }while(i<=100) //条件判断 System.out.println(sum); } }
-
While和do-While的区别
- while先判断后执行。do-while是先执行后判断!
- Do···while总是保证循环体会至少执行一次!这是他们的主要差别。
For循环
-
虽然所有循环结构都可以用while或者都do···while表示,但Java提供了另一种语句——for循环,使一些循环结构变得更加简单。
-
for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构。
-
for循环执行的次数是在执行前就确定的。语法格式如下:
for(初始化;布尔表达式;更新迭代){ //代码语句 } for(int i = 0;i <= n; i++){ //Idea中直接打n.for回车可直接打出for }
例:
public class ForDemo1{ public static void main(String[] args){ //初始化//条件判断//迭代 for(int i;i<=100;i++){ System.out.println(i); } //死循环 for(;;){ } } }
增强For循环
Java5新引入的。
Java增强for循环语法格式如下:
for(声明语句:表达式){
//代码句子
}
例:
public class ForDemo{
public static void main(String[] args){
int[] numbers = {10,20.30,40,50};//定义一个数组
//遍历数组的元素
for(int x:numbers){
System.out.println(x);
}
}
}
练习:计算0到100之间的奇数和偶数的和
public class ForDemo2{
public static void main(String[] args){
int oddSum = 0;
int evenSum = 0;
for(int i = 0; i <= 100; i++){
if(i%2!=0){//奇数
oddSum += i; //oddSum = oddSum + i;
}else{//偶数
evenSum += i;
}
}
System.out.println("奇数的和:"+oddSum);
System.out.println("偶数的和:"+evenSum);
}
}
练习:九九乘法表打印输出
public class ForDemo3{
public static void main(String[] args){
//1.我们先打印第一列
//2.我们打固定的1再用一个循环包起来
//3.去掉重复项,i = j;
//4.调整样式
for(int j = 1; j<=9; j++){
for(int i = 1; i<=j; i++){
System.out.print(j+"*"+i+"="+(j*i)+"\t");
}
System.out.println();
}
}
}
break、continue、goto
-
break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)
例:
public class BreakDemo{ public static void main(String[] args){ int i = 0; while(i<100){ i++; System.out.println(i); if(i==30){ //到30跳出循环 break; } } System.out.println("123");//跳出循环程序还会继续运行下去 } }
-
continue 语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。
public class ContinueDemo{ public static void main(String[] args){ int i = 0; while(i<100){ i++; if(i%10==0){ //到10的倍数跳过继续循环 System.out.println(); continue; //碰到就会直接跳到循环的开头继续循环 } System.out.print(i); } } }
-
关于goto关键字
- goto关键字很早就在程序设计语言中出现,尽管goto仍是Java的一个保留字,但并未在语言中得到正式使用;Java没有goto。然而,在break和continue这两个关键字的身上,我们仍然能看出一些goto的影子---带标签的break和continue。
- “标签”是指后面跟一个冒号的标识符,例如:label:
- 对Java来说唯一用到标签的地方是在循环语句之前,而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方。
练习:打印三角形
public class ContinueDemo{
public static void main(String[] args){
//打印三角形 5行
for(int i = 1; i<=5; i++){
for(int j = 5; j>=i; i--){
System.out.print(" ");
}
for(int j = 1; j<=i; i++){
System.out.print("*");
}
for(int j = 1; j<i; i++){
System.out.print("*");
}
System.out.println();
}
}
}
Java方法详解
什么是方法
-
Java方法是语句的集合,它们在一起执行一个功能。
- 方法是解决一类问题的步骤的有序集合
- 方法包含于类或对象中
- 方法在程序中被创建,在其他地方被引用
-
设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成1个功能,这样利于我们后期的扩展。
public class Demo01{ //main方法 public static void main(String[] args){ int sum = add(1,2); System.out.println(sum); } //加法 public static int add(int a,int b){ return a+b; } }
方法的定义和调用
方法的定义
-
Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法:
-
方法包含一个方法头和一个方法体。下面是一个方法的所有部分:
- 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
- 返回值类型:方法可能会返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。这种情况下,returnValueType是关键词void。
- 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
- 参数类型:参数像是一个占位符。当方法被调用时,传递值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数个数。参数是可选的,方法可以不包含任何参数。
- 形式参数:在方法被调用时用于接收外界输入的数据。
- 实参:调用方法时实际传给方法的数据。
- 方法体:方法体包含具体的语句,定义该方法的功能。
修饰符 返回值类型 方法名(参数类型 参数名){
···
方法名
···
return 返回值;
}
public class Demo02{
public static void main(String[] args){
int max = max(10,20);
System.out.println(max);
}
//比大小
public static int max(int num1,int num2){
int reault = 0;
if(num1 == num2){
System.out.println("num1 == num2");
return 0;//终止方法
}
if(num1>num2){
reault = num1;
}else{
reault = num2;
}
}
}
方法的调用
-
调用方法:对象名.方法名(实参列表)
-
Java 支持两种调用方法的方式,根据方法是否返回值来选择。
-
当方法返回一个值的时候,方法调用通常被当做一个值。例如:
-
int larger = max(30,40);
-
如果方法返回值是void,方法调用一定是一条语句。
System.out.println("hello world");
-
课后拓展了解:值传递(Java)和引用传递
//值传递
public class Demo04{
public static void main(String[] args){
int a = 1;
System.out.println(a);
Demo04.change(a);
System.out.println(a); //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); // weiqiang
}
//返回值为空
public static void change(Person person){
//person 是一个对象:指向的 ---》Person person = new Person()
person.name = "weiqiang";
}
}
//定义一个Person类,有一个属性:name
class Person{
String name; //null
}
- 类之间的调用
public class Demo02{
public static void main(String[] args){
// Student.say();
//实例化这个类new
//对象类型 对象名 = 对象值;
Student student = new Student();
student.say();
}
}
public class Student{
//public static void say(){
//System.out.println("学生说话了");
//}
public void say(){
System.out.println("学生说话了");
}
}
方法的重载
-
重载就是在一个类中,有相同的函数名称,但形参不同的函数。
-
方法的重载的规则:
- 方法名称必须相同。
- 参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)。
- 方法的返回类型可以相同也可以不相同。
- 仅仅返回类型不同不足以成为方法的重载。
-
实现理论:
- 方法名称相同时,编译器会根据调用方法的参数个数,参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。
public class Demo02{
public static void main(String[] args){
double max = max(10.0,20.0);
int max = max(10,20);
System.out.println(max);
}
//比大小
public static double max(double num1,double num2){
int reault = 0;
if(num1 == num2){
System.out.println("num1 == num2");
return 0;//终止方法
}
if(num1>num2){
reault = num1;
}else{
reault = num2;
}
}
//比大小
public static int max(int num1,int num2){
int reault = 0;
if(num1 == num2){
System.out.println("num1 == num2");
return 0;//终止方法
}
if(num1>num2){
reault = num1;
}else{
reault = num2;
}
}
}
命令行传参
-
有时候你希望运行一个程序时候再传递给它消息。这要靠传递命令行参数给main()函数实现。
public class CommandLine{ public static void main(String[] args){ for(int i=0; i<args.length; i++){ System.out.println("args[" + i +"]: " + args[i]); } } }
可变参数
-
JDK1.5开始,Java支持传递同类型的可变参数给一个方法。
-
在方法声明中,在指定参数类型后加一个省略号(...)。
-
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
public class CommandLine{ 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方法!就是自己调用自己
public class Demo05{
//递归思想
public static void main(String[] args){
System.out.println(f(5));
}
public static int f(int n){
if (n==1){
return 1;
}else{
return n*f(n-1);
}
}
}
-
利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
-
递归结构包括两个部分:
- 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
- 递归体:什么时候需要调用自身方法。
-
温馨提示:最好用于小计算程序,大计算程序电脑容易崩。
计算器的代码
import java.util.Scanner;
public class demo01 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextDouble()){
double x = scanner.nextDouble();
String m = scanner.next();
double y = scanner.nextDouble();
switch (m){
case "+":
add(x,y);
break;
case "-":
minus(x,y);
break;
case "*":
multiply(x,y);
break;
case "/":
except(x,y);
break;
}
System.out.println("请输入任意字母退出!");
}
scanner.close();
}
public static void add(double a,double b){
System.out.println(a+b);
}
public static void minus(double a,double b){
System.out.println(a-b);
}
public static void multiply(double a,double b){
System.out.println(a*b);
}
public static void except(double a,double b){
if(b==0){
System.out.println("分母不能为0");
}else{
System.out.println( a / b);
}
}
}
Java数组
数组的定义
- 数组是相同类型数据的有序集合。
- 数组描述的是想同类型的若干个数据,按照一定的先后次序排列组合而成。
- 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。
数组的声明和创建
- 首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法:
dataType[] arrayRefVar; //首先的方法
或
dataType arrayRefVar[]; //效果相同,但不是首选方法
- Java语言使用new操作符来创建数组,语法如下:
dataType[] arrayRefVar = new dataType[arraySize];
public class ArratDemo01{
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;
int sum = 0;
for(int i = 0; i < nums.length ; i++){
sum = sum + nums[i];
}
System.out.println("总和:" + sum);
}
}
-
数组的元素是通过索引访问的,数组索引从0开始。
-
获取数组长度:
arrays.length
三种初始化及内存分析
三种初始化
- 静态初始化
//静态初始化:创建+赋值
int[] a = {1,2,3};
Man[] mans = {new Man(1,1),new Man(2,2)};
- 动态初始化:包含默认初始化(0)
int[] a = new int[2];
a[0]=1;
a[1]=2;
- 数组的默认初始化
- 数组的引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
内存分析
数组的四个基本定义
-
其长度是确定的,数组一旦被创建,它的大小就是不可以改变。
-
其元素必须是相同类型,不允许出现混合类型。
-
数组中的元素可以是任何数据类型,包括基本类型和引用类型。
-
数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。
数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
数组的边界
-
下标的合法区间:[0,length-1],如果越界就会报错;
public static void main(String[] args){ int[] a = new int[2]; System.out.println(a[2]); }
-
ArraylndexOutOfBoundsException:数组下标越界异常!
-
小结:
- 数组是相同数据类型的有序集合
- 数组也是对象。数组元素相当于对象的成员变量
- 数组长度的确定的,不可变的。如果越界,则报:ArraylndexOutOfBounds
数组的使用
- For-Each 循环
public class ArrayDemo02{
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);
}
}
- 数组作方法入参
- 数组作返回值
public class ArrayDemo03{
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[] result = new int[arrays.length];
//反转操作
for(int i = 0;j = result.length-1;i < arrays.length;i++;j--){
result[j] = arrays[i];
}
return result;
}
//打印数组元素
public static void printArray(int[] arrays){
for(int i = 0;i<arrays.length;i++){
System.out.println(arrays[i] + "");
}
}
}
多维数组
-
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。
-
二维数组
int a[][] = new int[2][5];
public class ArrayDemo04{ public static void main(String[] args){ int[] arrays = {{1,2},{3,4},{5,6}}; //[3][2] printArray(array[0]);//输出1 2 System.out.print(array[0][0])//输出1 System.out.print(array[0][1])//输出2 } //打印数组元素 public static void printArray(int[] arrays){ for(int i = 0;i<arrays.length;i++){ System.out.println(arrays[i] + ""); } } }
-
解析:以上二维数组a可以看成一个两行五列的数组。
Arrays类
-
数组的工具类java.util.Arrays
-
由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据进行一些基本操作。
-
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而“不用”使用对象来调用(注意:是“不用”而不是“不能”)
-
具有以下常用功能:
- 给数组赋值:通过fill方法。
- 对数组排序:通过sort方法,按升序。
- 比较数组:通过equals方法比较数组中元素值是否相等。
- 查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作。
import java.util.Arrays;
public class ArrayDemo05{
public static void main(String[] args){
int[] a = {1,5,4,4,54,65,15,42};
//System.out.println(a); //[I@4554617c
//打印数组元素Arrays.toString
//System.out.println(Arrays.toString(a));
Arrays.sort(a);//数组进行排序:升序
System.out.println(Arrays.toString(a));//输出[1, 4, 4, 5, 15, 42, 54, 65]
Array.fill(a,0);//数组填充
Array.fill(a,2,4,0);//2到4之间进行填充//输出[1, 4, 0, 0, 15, 42, 54, 65]
System.out.println(Arrays.toString(a));//输出[0, 0, 0, 0, 0, 0, 0, 0]
}
//跟打印数组元素Arrays.toString一样
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] + ", ");
}
}
}
}
冒泡排序
- 冒泡排序无疑是最为出名的排序算法之一,总共有八种排序!
- 冒泡的代码还是相当简单的,两层循环,外层冒泡轮数,里层依次比较,
- 我们看到嵌套循环,应该立马就可以得出这个算法的时间复杂度为O(n2)。
public class ArrayDemo06{
public static void main(String[] args){
int[] a = {1,5,4,64,25,4,87,6};
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;
flag = true;
}
}
if(flag == false){
break;
}
}
return array;
}
}
稀疏数组(拓展)
- 当一个数组中大部分元素为0,或者为同一个的数组时,可以使用稀疏数组来保存该数组。
- 稀疏数组的处理方式是:
- 记录数组一个几行几列,有多少个不同值
- 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模
- 如下图:左边是原始数组,右边是稀疏数组
public class ArrayDemo06{
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();
}
System.out.println("=====================");
//转换为稀疏数组保存
//获取有效值的个数
int sum = 0;
for(int i = 0;i<array1.length;i++){
for(int j = 0;j<array1[i].length;j++){
if(array1[i][j]!=0){
sum++;
}
}
}
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];
}
//打印
System.out.println("还原");
for(int[] ints : array1){
for(int anInt : ints){
System.out.print(anInt+"\t");
}
System.out.println();
}
}
}
面向对象
面向过程&面向对象
-
面向过程思想
- 步骤清晰简单,第一步做什么,第二步做什么·····
- 面对过程适合处理一些较为简单的问题
-
面向对象思想
- 物以类聚,分类的思想模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
-
对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。
什么是面向对象
-
面向对象编程(Object-Oriented Programming,OOP)
-
面向对象编程的本质就是:以类的方式组织代码,以对象的形式组织(封装)数据。
-
抽象
-
三大特征:
- 封装
- 继承
- 多态
-
从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
-
从代码运行角度考虑是先有类后有对象。类是对象的模板
类与对象的关系
- 类是一个抽象的数据类型,它是对某一个事物整体描述/定义,但是并不能代表某一个具体的事物。
- 动物、植物、手机、电脑·······
- Person类、Pet类、Car类等,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为
- 对象是抽象概念的具体实例
- 张三就是人的一个具体实例,张三家里的旺财就是狗的具体实例。
- 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念。
创建和初始化对象
-
使用new关键词创建对象
-
使用new关键词创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用
-
类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
- 1.必须和类的名字相同
- 2.必须没有返回类型,也不能写void
-
构造器必须掌握
//学生类
public class Student{
//属性:字段
String name;
int age;
//方法
public void study(){
System.out.println(this.name + "在学习");
}
}
//一个项目应该只存一个main方法
public class Application{
public static void main(String[] args){
//类:抽象的,实例化
//类实例化后返回一个自己的对象!
//student对象就是一个Student类的具体实例!
Student xiaoming = new Student();
Student xiaohong = new Student();
xiaoming.name = "小明";
xiaoming.age = "3";
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
xiaohong.name = "小红";
xiaohong.age = "3";
System.out.println(xiaohong.name);
System.out.println(xiaohong.age);
}
}
构造器详解
- 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
- 1.必须和类的名字相同
- 2.必须没有返回类型,也不能写void
- 作用:
- 1.使用new关键字,必须要有构造器,本质是在调用构造器
- 2.用来初始化值
- 注意点:
- 1.定义有参构造之后,如果想使用无参构造,显示定义一个无参的构造
- alt + insert :自动生成构造器
public class Person{
//一个类即使什么都不写,它也会存在一个构造方法:默认构造器
//显示的定义构造器
String name;
//实例化初始值
//1.使用new关键字,必须要有构造器,本质是在调用构造器
//2.用来初始化值
public Person(){
this.name = "weiqing";
}
//有参构造:一旦定义了有参构造,无参就必须显示定义
public Person(){
}
public Person(String name){
this.name = name;
}
//alt + insert :自动生成构造器
}
public class Application{
public static void main(String[] args){
//new 实例化了一个对象
Person person = new Person();
//有参构造的
Person person = new Person("weiqing");
Systrm.out.println(person.name);
}
}
创建对象内存分析
public class Pet{
public String name;
public int age;
public void shout(){
System.out.println("叫一声");
}
}
import com.javase.demo03.Pet;
public class Application{
public static void main(String[] args){
//new 实例化了一个对象
Pet dog = new Pet();
dog.name = "旺财";
dog.age = 3;
dog.shout();
Systrm.out.println(dog.name);
Systrm.out.println(dog.age);
Pet cat = new Pet();
}
}
dog:
cat:
简单小结类与对象
-
类与对象:
- 类是一个模板:抽象,对象是一个具体的实例
-
方法:
- 定义、调用!
-
对象的引用:
- 引用类型 基本类型(8)
- 引用类型:对象是通过引用来操作的:栈---->堆
-
属性:字段Field 成员变量
- 默认初始值:
- 数字:0 0.0
- char: u0000
- Boolean: false
- 引用: null
- 修饰符 属性类型 属性名 = 属性值!
- 默认初始值:
-
对象的创建和使用
- 必须使用new 关键字创建对象, 构造器 Person weiqiang = new Person();
- 对象的属性 weiqiang.name
- 对象的方法 weiqiang.sleep();
-
类:
-
静态的属性 属性
-
动态的行为 方法
-
封装
- 该露的露,该藏的藏
- 我们程序设计要追求"高内聚,低耦合"。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
- 封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
- 记住这句话就够了:属性私有,get/set
//类 private:私有
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;
}
public String getAge(){
return this.age;
}
//set 给这个数据设置值
public void setAge(int age){
if(age>123 || age<0){//不合法
this.age = 3;
}else{
this.age = age;
}
}
}
import com.javase.demo04.Student;
/*
1.提高程序的安全性,保护数据
2.隐藏代码的实现细节
3.统一接口
4.系统可维护增加了
*/
public class Application{
public static void main(String[] args){
//new 实例化了一个对象
Student s1 = new Student();
s1.setName("weiqiang");
System.out.println(s1.getName());
s1.setAge(999);//不合法
System.out.println(s1.getAge()); //输出:3
}
}
- alt + insert :自动生成get、set
继承
-
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
-
extends的意思是“扩展”。子类是父类的扩展。
-
JAVA中类只能单继承,没有多继承!
-
继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
-
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键词extends来表示。
-
子类和父类之间,从意义上讲应该具有“is a”的关系。
import com.javase.demo04.Student;
public class Application{
public static void main(String[] args){
Student student = new Student();
student.say();
System.out.println(student.money);
// System.out.println(student.money2);//报错
}
}
//在JAVA中,所以的类,都默认继承object类,
//Person 人 父类
public class Person{
//public
//protected 受保护的
//default 默认
//private 私有不能继承
// int money2 = 10_0000_0000;
private int money2 = 10_0000_0000;
public int money = 10_0000_0000;
public void say(){
System.out.println("说了一句话");
}
public int getMoney2(){
return money2;
}
public void setMoney2(int money2){
this.money2 = money2;
}
}
//学生 is 人 :派生类、子类
//子类继承父类,就会拥有父类的全部方法!
public class Student extends Person{
}
//Teacher is 人
public class Teacher extends Person{
}
- Ctrl + h
Super
super注意点:
- 1.super调用父类的构造方法,必须在构造方法的第一个
- 2.super必须只能出现在子类的方法或者构造方法中!
- 3.super和this不能同时调用构造方法!
Vs this:
- 代表的对象不同:
- this: 本身调用者这个对象
- super: 代表父类对象的应用
- 前提
- this:没有继承也可以使用
- super: 只能在继承条件中才可以使用
- 构造方法
- this(); :本类的构造
- super(); :父类的构造!
import com.javase.demo04.Student;
public class Application{
public static void main(String[] args){
Student student = new Student(); //先输出Student无参执行了,在输出Person无参执行了
// student.test("weiqiang01");
//student.test1();
}
}
//在JAVA中,所以的类,都默认继承object类,
//Person 人 父类
public class Person{
public Person(){
System.out.println("Person无参执行了");
}
protected String name = "henshuai";
//private 私有的东西无法被继承!
public void print(){
System.out.println("Person");
}
}
//学生 is 人 :派生类、子类
//子类继承父类,就会拥有父类的全部方法!
public class Student extends Person{
public Student(){
//隐藏代码:调用了父类的无参构造
//调用构造器要么调用父类,要么调用子类
//如果不写默认调用无参构造器,如果父类有有参就必须写调用有参构造器
super();//调用父类的构造器,必须要在子类构造器的第一行
System.out.println("Student无参执行了");
}
private String name = "weiqiang";
public void print(){
System.out.println("Student");
}
public void tset1(String name){
print(); //Student
this.print(); //Student
super.print(); //Person
}
public void tset(String name){
System.out.println(name); //weiqiang01
System.out.println(this.name); //weiqiang
System.out.println(super.name); //henshuai
}
}
方法的重写
-
重写:需要有继承关系,子类重写父类的方法!
- 1.方法名必须相同
- 2.参数列表必须相同
- 3.修饰符:范围可以扩大但不能缩小: public>protected>Default>private
- 4.抛出的异常:范围,可以被缩小,但不能被扩大; ClassNotFoundException-->Exception(大)
-
重写,子类的方法和父类必须一致:方法体不同。
-
不能重写的:
- static 方法,属于类,它不属于实例
- final 常量:
- private方法:私有
-
为什么要重写:
- 父类的功能,子类不一定需要,或者不一定满足!
public class A extends B{
public static void test(){
System.out.println("A=>test()");
}
// alt+insert:Override Methods重写
@Override //注解:有功能的注释
public void test(){
System.out.println("A=>test()");
}
}
//重写都是方法的重写,和属性无关
public class B{
public static void test(){
System.out.println("B=>test()");
}
public void test(){
System.out.println("B=>test()");
}
}
import com.javase.demo05.A;
public class Application{
//静态的方法和非静态的方法区别很大!
//静态方法:
//非静态:重写
public static void main(String[] args){
//方法的调用只和左边,定义的数据类型有关
A a = new A();
a.test(); //A A
//父类的引用指向了子类
B b = new A(); //子类重写了父类的方法
b.test(); // B A
}
}
多态
-
动态编译:类型:可扩展性
-
即同一个方法可以根据发送对象的不同而采用多种不同的行为方式。
-
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类,有关系的类)
-
多态存在的条件
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
-
多态注意事项:
- 多态是方法的多态,属性没有多态
- 父类和子类,有联系 类型转换异常! ClassCastException!
-
instanceof (类型转换) 引用类型
public class Student extends Person{
public void run(){
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
public class Person{
public void run(){
System.out.println("run");
}
}
import com.javase.demo05.Student;
public class Application{
public static void main(String[] args){
//一个对象的实际类型是确定的
//new Student();
//new Person();
//可以指向的引用类型就不确定了:父类的引用指向子类
//Student 能调用的方法都是自己的或继承父类的!
Student s1 = new Student();
//Person 父类型,可以指向子类,但是不能调用子类独有的方法!
Person s2 = new Student();
Object s3 = new Student();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大!
s2.run(); //子类重写了父类的方法,执行子类的方法
s1.run();
// s2.eat(); //报错
}
}
instanceof和类型转换
-
instanceof (类型转换) 引用类型,判断一个对象是什么类型~
-
类型转换:
- 父类引用指向子类的对象
- 把子类转换为父类,向上转型
- 把父类转换为子类,向下转型:强制转换
- 方便方法的调用,减少重复的代码!简洁
public class Student extends Person{
public void go(){
}
}
public class Teacher extends Person{
}
public class Person{
public void run(){
System.out.println("run");
}
}
import com.javase.demo05.Student;
public class Application{
public static void main(String[] args){
//类型之间的转化 :父 子
//高 低
Person obj = new Student();
//student将这个对象转换为Student类型,我们就可以使用Student类型的方法了!
((Student)obj).go();
Student student = (Student) obj;
student.go();
//子类转换为父类,可能丢失自己的本来的一些方法!
Student student = new Student();
student.go();
Person person = student;
}
}
import com.javase.demo05.Student;
public class Application{
public static void main(String[] args){
//Object > String
//Object > Person > Teacher
//Object > Person > Student
Object object = new Student();
// System.out.println(X instanceof Y);//能不能编译通过:判断有没有父子关系
System.out.println(object instanceof Student); //true
System.out.println(object instanceof Person); //true
System.out.println(object instanceof Object); //true
System.out.println(object instanceof Teacher); //false
System.out.println(object instanceof String); //false
System.out.println("================================");
Person person = new Student();
System.out.println(person instanceof Student); //true
System.out.println(person instanceof Person); //true
System.out.println(person instanceof Object); //true
System.out.println(person instanceof Teacher); //false
// System.out.println(person instanceof String); //编译报错
System.out.println("================================");
Student student = new Student();
System.out.println(student instanceof Student); //true
System.out.println(student instanceof Person); //true
System.out.println(student instanceof Object); //true
//System.out.println(student instanceof Teacher); //编译报错
// System.out.println(student instanceof String); //编译报错
}
}
static详解
public class Student{
private static int age; //静态变量
private double score; //非静态变量
public static void main()(String[] args){
Student s1 = new Student();
System.out.println(Student.age);
System.out.println(s1.age);
System.out.println(s1.scoer);
// System.out.println(Student.scoer);//报错 非静态方法
go();
// run();//报错 不能调用非静态方法
}
public void run(){
}
public static void go(){
}
}
public class Person{
//2 赋初值
{
System.out.println("匿名代码块");
}
//1 跟随类一起加载,且只执行一次
static{
System.out.println("静态代码块");
}
//3
public Person(){
System.out.println("构造方法");
}
public static void main()(String[] args){
Person person = new Person();//静态代码块 匿名代码块 构造方法
System.out.println("===========================");
Person person2 = new Person();//匿名代码块 构造方法
}
}
//静态导入包~
import static java.lang.Math.random;
public class Test{
public static void main()(String[] args){
//随机数
System.out.println(Math.random());
System.out.println(random());
}
}
抽象类
-
abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
-
抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
-
抽象类,不能使用new关键词来创建对象,它是用来让子类继承的。
-
抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
-
子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
//abstract 抽象类:类 extends: 单继承 (接口可以多继承)
public abstract class Action{
//约束~有人帮我们实现~
//abstract ,抽象方法,只有方法名字,没有方法的实现!
public abstract void doSomething();
//1.不能new这个抽象类,只能靠子类去实现它:约束~
//2.抽象类可以写普通方法~
//3.抽象方法必须在抽象类中~
//抽象的抽象:约束~
//存在的意义:抽象出来~ 提高开发效率
}
//抽象类的所有方法,继承了它的子类,都必须要实现它的方法~除非子类也是abstract
public class A extends Action{
public void doSomething(){
}
}
接口的定义与实现
-
普通类:只有具体的实现
-
抽象类:具体实现和规范(抽象方法)都有!
-
接口:只有规范!自己无法写方法~专业的约束! 约束和实现分离:面向接口编程~
-
接口就是规范,定义的是一组规则,体现了现实世界中“如果你是···则必须能····”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你是好人,则必须干掉坏人等等。
-
接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。
-
声明类的关键词是class,声明接口的关键词是interface
-
作用:
- 1.约束
- 2.定义一些方法,让不同的人实现~ 10------>1
- 3.public abstract
- 4.public static final
- 5.接口不能被实例化,接口中没有构造方法
- 6.implements可以实现多个接口
- 7.必须要重写接口的方法~
//抽象的思维~ Java 架构师~
//interface 定义的关键字,接口都需要有实现类
public interface UserService{
//接口中的所有定义的方法其实都是抽象的 public abstract
public abstract void run();
//常量 public static final
int Age = 99;
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
//抽象类:extends
//类 可以实现接口 implements 接口
//实现了接口的类,就需要重写接口中的方法
public class UserServiceImpl implements UserService,TimeService{
@Override
public void add(String name){
}
@Override
public void delete(String name){
}
@Override
public void update(String name){
}
@Override
public void query(String name){
}
@Override
public void timer(){
}
}
public interface TimeService{
void timer();
}
内部类
-
内部类就是在一个类的内部在定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。
-
1.成员内部类
-
2.静态内部类
-
3.局部内部类
-
4.匿名内部类
public class Outer{
private int id = 10;
public void out(){
System.out.println("外部类");
}
public class Inner{
public void in(){
System.out.println("内部类");
}
//获得外部类的私有属性和私有方法~
public void getID(){
System.out.println(id);
}
}
//无法调用外部类里面的方法和属性
public static class Inners{
public void in(){
System.out.println("静态内部类");
}
}
//局部内部类
public void method(){
class Inner{
public void in(){
}
}
}
}
//一个Java类中可以有多个class类,但是只能有一个public class类
class A{
}
public class Application{
public static void main(String[] args){
Outer outer = new Outer();
//通过这个外部类来实例化内部类~
Outer.Inner inner = Outer.new Inner();
inner.in();//内部类
inner.getID();//10
}
}
//匿名内部类
public class Test{
public static void main(String[] args){
//没有名字初始化类,不用讲实例保存到变量中
new Apple().eat();
new UserService(){
@Override
public void hello(){
}
};
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
interface UserService{
void hello();
}
异常
-
实际工作中,遇到的情况不可能是非常完美的。比如:你写的某个模块,用户输入不一定符合你的要求、你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等。我们的程序在跑着,内存或者硬盘可能满了。等等。
-
软件程序运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是:Exception,意思是例外。这些,例外情况,或者叫异常,怎么让我们写的程序做出合理的处理。而不至于程序崩溃。
-
异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。
-
异常发生在程序运行期间,它影响了正常的程序执行流程。
-
异常处理框架
-
检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在的文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
-
运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
-
错误Error:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
异常体系结构
- Java把异常当作对象处理,并定义一个java.lang.Throwable作为所有异常的超类。
- 在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。
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通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。
捕获和抛出异常
- 异常处理五个关键词
- try、catch、finally、throw、throws
- 选中要捕获异常的信息+Ctrl + Alt + t
public class Test{
public static void main(String[] args){
try{
new Test().test(1,0);
}catch(ArithmeticException e){
e.printStackTrace();
}
int a = 1;
int b = 0;
//假设要捕获多个异常:从小到大!
try{ //try监控区域
System.out.print(a/b);
}catch(Exception e){ //catch(想要捕获的异常类型)捕获异常
System.out,println("Exception");
}catch(Error e){
System.out,println("Error");
e.printStackTrace(); //打印错误的栈信息
}catch(Throwable t){
System.out,println("Throwable");
}finally{ //处理善后工作
System.out.print("finally");
}
//finally 可以不要finallly, 假设IO,资源,关闭!
}
//假设这方法中,处理不了这个异常,方法上抛出异常
public void test() throws ArithmeticException{
if(b==0){// throw
throw new ArithmeticException();// 主动的抛出异常,一般在方法中使用
}
}
}
自定义异常
-
使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需继承Exception类即可。
-
在程序中使用自定义异常类,大体可分为以下几个步骤:
- 1.创建自定义异常类。
- 2.在方法中通过throw关键字抛出异常对象。
- 3.如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
- 4.在出现异常方法的调用者中捕获并处理异常。
//自定义的异常类
public class MyException extends Exception{
//传递数字>10;
private int detail;
public MyException(int a){
this.detail = a;
}
//toString:异常的打印信息
@Override
public String toString(){
return "MyException{" +
"detail=" + 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(MyException e){
//增加一些处理异常的代码块
System.out.println("MyException=>" +e);//输出:MyException=>MyException{11}
}
}
}
实际应用中的经验总结:
- 处理运行时异常时,采用逻辑去合理规避同时辅助 try-catch处理
- 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch,处理潜在的异常
- 尽量去处理异常,切忌只是简单地调用 printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句块去释放占用的资源,IO~ Scanner~