JAVA基础知识
基本概念
简单性 面向对象 可移植性 跨平台 高性能 分布式 动态性 分布式 动态性 多线程 安全性 健壮性
javaSE标准版 javaME嵌入式 javaEEE企业开发(Web端)
JDK:java Development Kit最大包含其他
JRE: java Runtime Environment java运行环境
JVM:java虚拟机
C:\Program Files\Java\jdk1.8.0_201
jAVA_HOME:路径jdk存储路径W
bin目录:可执行程序exe
jre目录
src目录:java库
include:引入头文件
%JAVA_HOME%jre\bin
测试JDK是否安装成功:java -version
直接运行java文件:
①cmd 在代码目录下javac java文件
②运行java java文件
类型
Long类型要在数后加L
float类型后要加F
String 不是关键词
整数扩展:
二进制0b 八进制0 十六进制0x
浮点数(银行业务怎么表示):
float f=0.1f
double d=1.0/10
浮点数存在误差 离散接近但不等于 最好避免完全使用浮点数进行比较
大数类型:BigDecimal 数学工具类
字符拓展:
所有字符本质还是数字(强制转换可以把数字表示为数字)
**编码unicode表两个字节 **65536
(U0000~UFFFF):97=a 65=A
//0061是十六进制,转换为十进制是97
char c3='\u0061'
String sa= new String("Hello world");
String sb=new String("Hello world");
System.out.println(sa==sb);
转义字符:\t制表符 \n换行符
对象:从内存分析
布尔值扩展:if(flag)
类型转换:
byte short char int long float double简单到复杂
类型转换简单记忆法则:人只能往高处爬
运算中,不同数据类型转换为同一类型,然后再进行运算
强制转换:(类型)变量名(高–>低)
int i=124;
byte b=(byte)i;
自动转换:低到高,例如:int–>double
int i=128;
double b=i;
注意:
1.不能对布尔进行转化
2.不能把对象类型转换为不相干的类型
3.在把高容量转换到低容量时,强制转换。
4.转换时候可能存在内存溢出或精度问题
5.操作比较大数注意数据溢出问题
JDK7特性,数字之间可以使用下划线隔开
char c='a';
//低转高
int d=c+1;
char s=(char)d;
int money=10_000_000;
//数据溢出问题
int years=20;
int total=year*money;//计算溢出
long toal=year*(long)money;//转换之前防止溢出
变量
数据类型 变量名 作用域
变量名编写规则:除第一个单词以外,后面单词首字母大写
类名:首字母大写,驼峰原则
public class Varible{
static int allchilcks=0;//类变量加static关键词
static final double s=0.01;//final修饰符不存在顺序,静态常量不变
String str="Hello world";//实例变量:通过创建类实例对象,调用变量
public void method(){
int i=0;//局部变量(函数里面的,必须声明和初始化值{}内使用)
}
public static void main(String[] args) {
Varible v=new Varible();
}
运算符:
逻辑运算符 算数 赋值 关系 逻辑 位 条件(?😃 扩展赋值运算符(+= -= *=)
+也可作为字符串连接符
//字符串连接符+
int a=10;
int b=12;
System.out.println(""+a+b);//空串在前拼接
System.out.println(a+b+"");//空串在后先算
public class Demo {
public static void main(String[] args) {
//二元运算符(Ctrl+d 复制当前行到下一行)
long a=22323266663L;
int b=123;
short c=10;
byte d=8;
System.out.println(a+b+c+d);//long
System.out.println(b+c+d);//int
System.out.println(c+d);//int
}
}
public class Demo02 {
public static void main(String[] args) {
//++ --自增 自减
int a=3;
int b= a++;//a=a+1;执行完后,先给b赋值,再自增
System.out.println(a);
int c= ++a;//a=a+1;执行完前,先给再自增,再赋值
System.out.println(a);
System.out.println(a);
System.out.println(b);
System.out.println(c);
//幂运算 2*3使用工具类操作
double pow = Math.pow(2, 3);
System.out.println(pow);
}}
public class Demo3 {
public static void main(String[] args) {
//逻辑运算符 与(and)或(or) 非(取反)
boolean a=true;
boolean b=false;
System.out.println("a && b:"+(a&&b));
System.out.println("a || b:"+(a||b));
System.out.println("!(a && b):"+!(a&&b));
//短路运算且运算时左边为假就不看右边的了
int c=5;
boolean d=(c<4)&&(c++<4);
System.out.println(d);
}
}
位运算
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
>>右移除2
0000 0000 0
0000 0001 1
0000 0010 2
*/
System.out.println(2<<3);
}
三元运算符
//三元运算符 X?Y:Z
//如果x==true 结果为y,否则结果为z
int score=80;
String type=score<60 ?"不及格":"及格";
System.out.println(type);
包机制
包的本质就是文件夹,一般使用公司域名倒置作为包名。
导包Import
JAVADOC
生成自己的API文档
/**
* @author :tan
* @version 1.0(版本号)
* @since 1.0((指明最早使用jdk版本)
*/
public class Demo5 {
String name;
/**
* @param name(参数名)
* @return(返回值情况)
* @throws Exception(抛出异常)
*/
public String test(String name){
return name;
}
javadoc文档生成步骤:
右击项目 show in explor
cmd命令转到指定文件夹下,路径前导航加cmd,输入命令:
javadoc -encoding UTF-8 -charset UTF-8 类名.java
生成文档找index.html
Java流程控制
用户交互Scanner
获取用户输入
next():
1.一定要读取到有效字符后才可以结束输入
2.对输入有效字符之前遇到的空白,next(方法会自动将其去掉)
3.next()不能得到带有空格的字符串
4.只有输入有效字符后才将其后输入的空白作为分隔符或者结束符
nextLine():
1.以Enter为结束符,返回输入回车之前的所有字符
2.可以获得空白
//创建Scanner对象(扫描器)
Scanner s=new Scanner(System.in);
System.out.println("使用next方式接收:");
//判断用户有没有输入字符串
if(s.hasNext()){
//接收用户输入
String str=s.next();
System.out.println(str);
}
//用完关闭
s.close();
//创建Scanner对象(扫描器)
Scanner s=new Scanner(System.in);
System.out.println("使用nextLine方式接收:");
//判断用户有没有输入字符串
if(s.hasNextLine()){
//接收用户输入
String str=s.nextLine();
System.out.println(str);
}
//用完关闭
s.close();
输入小数整数
Scanner s=new Scanner(System.in);
//从键盘接收数据
int i=0;
float f=0.0f;
System.out.println("请输入整数:");
if(s.hasNextInt()){
i=s.nextInt();
System.out.println(i);
}else{
System.out.println("你输入的不是整数");
}
System.out.println("请输入小数:");
if(s.hasNextFloat()){
f=s.nextFloat();
System.out.println(f);
}else{
System.out.println("你输入的不是小数");
}
小例子:
//输入多个数字,并求其总和和平均数,没输入一个数回车确认,通过非数字结束输入
Scanner s= new Scanner(System.in);
double sum=0;
//计算输入多少个数字
int m=0;
通过循环判断是否正在输入,并在里面进行求和和统计
while(s.hasNextDouble()){
double x=s.nextDouble();
m=m+1;
sum+=x;
}
System.out.println(m+"个数总和为:"+sum);
System.out.println(m+"个数平均值为:"+(sum/m));
s.close();
选择结构
- 单选结构
if(布尔表达式){}
Scanner s=new Scanner(System.in);
System.out.println("请输入内容");
String str=s.nextLine();
//equals:判断字符串是否相等
if(str.equals("Hello")){
System.out.println(str);
}
System.out.println("End");
s.close();
- 双选结构
if (布尔表达式){}else{}
-
多选择结构
if (布尔表达式){}else if{} else{}
Switch(条件){case value: //语句 break;}
反编译:class->java(看Class源码)
循环结构
- while(布尔表达式){循环内容}
先判断后执行
public static void main(String[] args) {
//计算1+2+3+...100
int i=0;
int sum=0;
while(i<100){
sum=sum+i;
i++;
}
System.out.println(sum);
}
}
- do…while:
先执行后判断(保证循环体至少执行一次)
-
For循环
for(初始化;条件;运算)
100.for()自动生成0~100的循环
关于for语句说明: 最先执行初始化步骤,可以声明一种类型,但可以初始化一个或多个循环控制变量,也可也是空语句 然后,检测布尔表达式的值,如果为true,循环体被执行,如果为false,循环终止,开始执行开始执行循环体后的语句 执行一次循环后,更新循环控制控制变量(迭代因子控制循环变量的增减) 再次检测布尔表达式,循环执行上面的过程。
例子:
//计算0到100之间奇数和偶数的和
int oddSum=0;
int evenSum=0;
for (int i = 0; i < 100; i++) {
if(i%2!=0){//奇数
oddSum+=i;
}
else{//偶数
evenSum+=i;
}
}
System.out.println("奇数的和为"+oddSum);
System.out.println("偶数的和为"+evenSum);
}
//1~1000之间能被5整除的数,并且每行输出3个
for (int i = 0; i <=1000; i++) {
if(i%5==0){
System.out.print(i+"\t");
}
if(i%(5*3)==0){
System.out.println("\n");
}
}
}
//打印九九乘法表
for(int i=1;i<=9;i++){
for(int j=1;j<=i;j++){
int sum=i*j;
System.out.print(i+"*"+j+"="+sum+"\t");
}
System.out.println("");
}
}
- 增强for循环
//遍历数组中的元素
int[] number={12,13,131,414};
for(int x:number){
System.out.println(x);
}
//基础for循环
for (int i = 0; i < 4; i++) {
System.out.println(number[i]);
}
}
- break强制退出循环,跳出所有循环
- continue终止某次循环,跳过循环中尚未执行的语句,接着进行下一次循环 的判定。
- 练习:
public static void main(String[] args) {
//打印三角形 5行
//先打印左上空白三角形
//再打印中间数
for (int i = 0; i < 5; i++) {
for(int j=i;j<4;j++){
System.out.print(""+"\t");
}
for (int j = 1; j <= i; j++) {
System.out.print(j + "\t");
}
for(int j=i+1;j>0;j--){
System.out.print(j+"\t");
}
System.out.println();
}
}
1
1 2 1
1 2 3 2 1
1 2 3 4 3 2 1
1 2 3 4 5 4 3 2 1
JAVA方法
类方法可以直接调用。方法在程序中被创建,在其他地方被引用。一个方法只做一个功能比较好。
方法调用:对象名.方法
值传递(JAVA只有)和引用传递
方法重载:在同一类中,有相同的函数名称,单形参不同的函数。
重载规则:方法名必须相同;**参数列表必须不同;**方法的返回类型可以相同也可以不同;仅仅返回值不同不能构成方法的重载。
例子:
public static void main(String[] args) {
int sum=add(2,3);
System.out.println(sum);
int sum1=add(1,2,3);
}
//加法
public static int add(int a,int b){
return a+b;
}
public static int add(int a,int b,int c){
return a+b;
}
}
命令行传参:
希望程序运行时再给它传递消息,考命令行参数给main()函数实现。
public static void main(String[] args) {
//args.length数组长度
for (int i = 0; i < args.length; i++) {
System.out.println("args["+i+"]="+args[i]);
}
}
//在src路径下输入,hello world为传递参数
java com.java.methos.methodDemo1 hello world
不定项参数
在方法声明中,在指定参数类型后加一个省略号(…),一个方法中只**能指定一个可变参数,必须是方法的最后一个参数,**任何普通参数必须在它之前声明。
public class methoDemo1 {
public static void main(String[] args) {
methoDemo1 DEMO=new methoDemo1();
DEMO.test(1);
}
//类似数组的使用
public void test(int...i){
System.out.println(i[0]);
}
}
递归
- 方法调用自身
递归(使用栈机制)包含:
①递归头:什么时候结束递归调用
②递归体:什么时候需要调用自身方法
public static void main(String[] args) {
System.out.println(f(3));
}
//f(2)=2*f(1) f(1)=1
//3=3*f(2) f(2)=2*f(1) f(1)=1
public static int f(int n){
if(n==1){
return 1;
}
else{
return n*f(n-1);
}
}
练习:简易计算器
package com.java.method;
import java.util.Scanner;
public class jisuanqi {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("请输入两个数");
int a=0;
double b=0,result=0;
if(scanner.hasNext()){
a=scanner.nextInt();
b=scanner.nextInt();
}
System.out.println("请输入需要需要进行的操作");
//next()函数只读下一行的nextLine()读到当下一行没有输入为止
String c=scanner.next();
switch(c){
case "+":{result=add(a,b);
break;}
case "-":{result=jian(a,b);
break;}
case "*":{result=cheng(a,b);
break;}
case "/": {result=chu(a,b);
break;}
}
System.out.println(a+c+b+"的结果为"+result);
}
public static double add(int a,double b){
return a+b;
}
public static double jian(int a,double b){
return a-b;
}
public static double cheng(int a,double b){
return b;
}
public static double chu(int a,double b){
return a/b;
}
}
数组
同类型数据的有序集合:相同类型若干数据按照一定的先后次序排列组合而成。
public static void main(String[] args) {
//变量类型 变量名=变量值
//数组类型
int[] num;//定义
//使用new关键新一个类型的数组
num=new int[10];//开辟0~9十个空间
//数组元素中赋值
num[0]=1;
num[1]=2;
num[2]=3;
num[3]=4;
num[4]=5;
num[5]=6;
num[6]=7;
num[7]=8;
num[8]=9;
num[9]=10;
//计算所有元素和
int sum=0;
for (int i = 0; i < num.length; i++) {
sum+=num[i];
}
System.out.printd3ln("总和为"+sum);
}
}
数组三种初始化方法:
静态初始化
public static void main(String[] args) {
//静态初始化:创建加赋值
int[] a={1,2,3,4,5,6,7,8};
System.out.println(a[0]);
//动态初始化包含默认初始化
//未赋值数组值默认为0
int[] b= new int[10];
b[0]=10;
System.out.println(b[0]);
System.out.println(b[1]);
System.out.println(b[2]);
System.out.println(b[3]);
}
java对象就在堆中
ArrayIndexOutOfBoundsException:数组越界异常!
数组的使用
①for-Each循环
②数组作方法入参
③数组做返回值
public static void main(String[] args) {
int[] arrays={1,2,3,4,5};
// for (int array : arrays) {
// System.out.println(array);
// }
printArray(Reverse(arrays));
}
//数组作为方法入参
public static void printArray(int[] arrays) {
for (int i = 0; i < arrays.length; i++) {
System.out.println(arrays[i]);
}
}
//翻转数组元素,数组作为返回值
public static int[] Reverse(int[] arrays) {
int[] result=new int[arrays.length];
//翻转的操作
for (int i = 0,j=result.length-1;i < arrays.length;j--,i++) {
result[j]=arrays[i];
}
return result;
}
多维数组
二维数组多行多列
public static void main(String[] args) {
//二维数组
//arrays[0]:1,2
int[][] arrays={{1,2},{2,3},{3,4},{4,5}};
printArray(arrays[0]);
}
public static void printArray(int[] arrays) {
for (int i = 0; i < arrays.length; i++) {
System.out.println(arrays[i]);
}
}
}
Arrays类
用于对数据对象进行一些操作。
Arrays中的方法都是static 修饰的静态方法
打印数组元素:Arrays.toString(数组对象);
数组元素进行排序:Arrays.sort(数组对象)
数组赋值:fill()
比较数组:Equals()方法进行比较数组中的元素值是否相等。
查找数组元素:binarySearch()方法对排好序的数组进行二分查找操作。
public static void main(String[] args) {
int[] a={1,2,3,4,8908,324,323,12};
//打印数组
System.out.println(a);
System.out.println(Arrays.toString(a));
printArray(a);
//数组元素进行排序
Arrays.sort(a);
System.out.println( Arrays.toString(a));
//数组填充
Arrays.fill(a,0);
System.out.println(Arrays.toString(a));
}
public static void printArray(int[] a){
for (int i = 0; i < a.length; i++) {
if(i==0){
System.out.print("[");
}
System.out.print(a[i]+",");
if(i==a.length-1){
System.out.print("]");
}
}
}
}
冒泡排序
时间复杂度O(n2)
1.比较数组中,两个响铃的元素,如果第一个数比第二数大交换他们的位置。
2.每一次比较都会产生一个最大或者最小的数。
3.下一轮则少一次排序
4.一次循环,直到结束。
package com.java.method;
import java.util.Arrays;
public class ArrayDemos7 {
public static void main(String[] args) {
int[] a={2,4,2,31,21};
System.out.println(Arrays.toString(sort(a)));
}
public static int[] sort(int[] array){
//外层循环判断排序需要进行多少次
int temp;
boolean flag=false;
for (int i = 0; i < (array.length - 1); i++) {
//内层循环,比较相邻两个数的大小,如果前一个数比第二个数大,交换两个数的位置
//将最小数移到数组最后面,俗称冒泡
for(int j=0;j<array.length-1-i;j++){
if (array[j]<array[j+1]){
temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
flag=true;
}
}
//优化代码
if(flag==false){
break;
}
}
return array;
}
}
稀疏数组
典型压缩算法
处理方法:
1:记录数组一共几行几列,有多少个不同的值
2:把具有不同值的元素和行列值记录在一个小规模数组中,从而缩小程序规模
0 0 0 22 0 0 15
0 11 0 0 0 0 17
0 0 0 -6 0 0 0
0 0 0 0 0 39 0
91 0 0 0 0 0 0
0 0 28 0 0 0 0
a[0]记录数组的行列数以及数组中总共有多少种元素
其余行代表数组中每个有效元素的位置
行 | 列 | 值 |
---|---|---|
【0】6 | 7 | 8 |
【1】0 | 3 | 22 |
【2】0 | 6 | 15 |
【3】1 | 1 | 11 |
【4】1 | 6 | 17 |
【5】2 | 3 | -6 |
【6】3 | 5 | 39 |
【7】4 | 0 | 91 |
【8】5 | 2 | 28 |
package com.java.method;
import java.util.Arrays;
public class Demo08 {
public static void main(String[] args) {
//创建一个二维数组 11*11 0:没有棋子 1:黑 2:白
int[][] array1=new int[11][11];
array1[1][2]=1;
array1[2][3]=2;
//输出原始数组
for (int[] ints : array1) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
//转换成稀疏数组保存
//获取有效值的个数
int sum=0;
for (int i = 0; i < 11; i++) {
for (int j=0;j<11;j++) {
if(array1[i][j]!=0){
sum++;
}
}
}
System.out.println("有效值个数为"+sum);
int[][] array2=new int[sum+1][3];
array2[0][0]=11;
array2[0][1]=11;
array2[0][2]=sum;
//遍历二维数组将非零只存放到稀疏数组中
int count=0;
for (int i = 0; i < array1.length; i++) {
for(int j=0;j<array1[i].length;j++){
if(array1[i][j]!=0){
count++;
//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++) {
for (int i1 = 0; i1 < array2[i].length; i1++) {
System.out.print(array2[i][i1]+"\t");
}
System.out.println();
}
//还原
int[][] array3=new int[array2[0][0]][array2[0][1]];
//给其中元素还原它的值
for (int i = 1; i < array2.length; i++) {
array3[array2[i][0]][array2[i][1]]=array2[i][2];
}
for (int i = 0; i < array3.length; i++) {
for(int j=0;j<array3[i].length;j++){
System.out.print(array3[i][j]+"\t");
}
System.out.println();
}
}
}
面向对象编程
方法调用规则
package com.java.oop;
public class Demo1 {
//main方法
public static void main(String[] args) {
}
/*
修饰符 返回值类型 方法名(...){
//方法体
return 返回值;
}
*/
public String sayHello(){
return "hello world";
}
}
package com.java.oop;
public class Demo02 {
public static void main(String[] args) {
//静态方法 static
Student.say();
//非静态方法
//实例化类
Student student=new Student();
student.talk();
}
public static void a(){
//b()不可调用b方法,静态方法和类一起出现
}
//类实例化后才存在
public void b(){}
}
JAVA值传递和引用传递区别
package com.java.oop;
public class Demo02 {
public static void main(String[] args) {
//静态方法 static
Student.say();
//非静态方法
//实例化类
Student student=new Student();
student.talk();
}
public static void a(){
//b()不可调用b方法,静态方法和类一起出现
}
//类实例化后才存在
public void b(){}
}
package com.java.oop;
//引用传递:对象,本质还是值传递
public class Demo4 {
public static void main(String[] args) {
Person person=new Person();
System.out.println(person.name);
Demo4.change(person);
System.out.println(person.name);
}
public static void change(Person person){
//person是一个对象,是一个具体的人可以改变属性
person.name="hello";
}
}
//定义一个person类有一个属性name
class Person{
String name;
}
类与对象的创建
对象是抽象概念的具体实例
使用new关键字创建对象,对对象进行默认的初始化
Student student=new Student();
一个类中只有属性方法
类中的构造器(构造方法 Alt+insert快捷生成构造器)
ackage com.java.oop;
public class Person {
//一个类即使什么都不写,也会存在一个方法
String name;
//有参构造
//使用new关键字,本质是在构造构造器
//用于初始化值
//构造器没有返回值
//如果定义有参构造,如果继续使用无参构造,需要显式写一个无参构造
public Person(String name) {
this.name = name;
}
public Person(){
this.name="hello";
}
}
构造器详解
总结:类在栈,对象在堆属性在方法。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A8DOw0pJ-1615638132971)(C:\Users\lenovo\Desktop\IMG_20210228_184943.jpg)]
类与对象总结
1.类是一个模板:抽象,对象是一个具体实例
2.方法:定义调用
3.对应的引用
引用类型:基本类型
对象是通过引用来进行操作的
4.属性:字段Field成员变量
默认初始化 修饰符 属性类型 属性名=属性值
封装详解
高内聚,低耦合,隐藏代码细节,提高系统可维护性,将数据进行隐藏
属性私有:get/set(Alt+Insert生成getter或者setter方法)
public class Student {
//名字,学号
private String name;
private int id;
//set给这个属性设置值
public void setName(String name) {
this.name = name;
}
public void setId(int id) {
this.id = id;
}
//获取这个属性的值
public String getName() {
return this.name;
}
public int getId() {
return this.id;
}
}
package com.java.oop;
public class Demo5
{
public static void main(String[] args) {
Student student=new Student();
student.setName("liMing");
student.setId(12345);
System.out.println(student.getName());
System.out.println(student.getId());
}
}
方法重载:方法名相同,但是方法的形参类型不同。
(单)继承
继承是对一批类的抽象,从而实现类实例建模,**继承就是扩展,子类是父类的扩展。 ** Ctrl+H 显示继承关系,在JAVA中,所有类默认继承Object类
package com.java.oop;
public class Persons{
public void say(){
System.out.println("hello");
}
}
package com.java.oop;
public class Teacher extends Persons{
//子类继承父类,可以继承父类公有的方法属性
//Ctrl+H 显示继承关系
}
package com.java.oop;
public class Demo6 {
public static void main(String[] args) {
Teacher dede=new Teacher();
dede.say();
}
}
Super
super注意点:
-
super调用父类的构造方法,必须在构造方法第一个
-
super必须只能出现在子类的方法或构造方法中
-
super和this不能同时调用构造方法
-
VS this:
代表对象不同:this本身调用者这个对象
super:代表父类对象的引用
前提:this没有继承也可以调用,super:只能在继承条件才可以使用
构造方法:this():本类的构造
super():父类的构造
**例1:**父类:persons
package com.java.oop;
public class Persons{
protected String name="父类name";
public void say(){
System.out.println("hello");
}
public void print(){
System.out.println("父类print");
}
}
子类:teacher
package com.java.oop;
public class Teacher extends Persons{
//子类继承父类,可以继承父类公有的方法属性
//Ctrl+H 显示继承关系
private String name="子类name";
public void test(String name){
System.out.println(name);//传递参数
System.out.println(this.name);
System.out.println(super.name);
}
public void print(){
System.out.println("子类print");}
public void test2(){
print();
this.print();
super.print();
}
}
测试:
package com.java.oop;
public class Demo6 {
public static void main(String[] args) {
Teacher dede=new Teacher();
dede.say();
Teacher teacher=new Teacher();
teacher.test("参数name");
teacher.test2();
}
}
结果
hello
参数name
子类name
父类name
子类print
子类print
父类print
例2: 父类:
public class Persons{
public Persons(){
System.out.println("父类的无参构造执行");
}
子类:
public class Teacher extends Persons{
public Teacher(){
//隐藏代码,调用父类无参构造super(),调用父类构造器必须在子类构造器第一行
System.out.println("子类的午餐构造执行");
}}
测试:
public static void main(String[] args) {
Teacher dede=new Teacher();
}
结果:父类的无参构造执行
子类的无参构造执行
**例3:**父类包含有参构造,子类就不能调用无参构造,除非在无参构造中调用父类的有参构造。
父类:
public class Persons{
//父类包含有参构造
public Persons(String name){
this.name=name;}
protected String name="父类name";
}
子类:
public Teacher(){
//隐藏代码,调用父类无参构造super(),调用父类构造器必须在子类构造器第一行
super("hello");
System.out.println("子类的午餐构造执行");
}
方法重写
重写都是方法的重写和属性无关
重写:需要有继承关系,子类重写父类方法
-
方法名必须相同
-
参数列表必须相同
-
修饰符范围可以扩大:public->protected->default->private
-
抛出异常范围:可以被缩小不能扩大:classNotFoundException(小)->Exception(大)
-
重写:子类方法必须要和父类一致,方法体可以不同
-
为什么重写:父类的功能可能子类并不需要
-
Alt+Insert:@override
例:父类
public class B {
public void test(){
System.out.println("B->test");
}
}
子类:
public class A extends B{
@Override//注解,重写
public void test() {
System.out.println("A=>test");
}
}
测试
public class Application {
public static void main(String[] args) {
//静态方法::方法调用只和左边定义的数据类型决定
//静态方法和非静态方法区别很大
//非静态重写
A a=new A();
a.test();
//父类的引用指向子类
B b=new A();//子类重写了父类的方法
b.test();
}
}
多态
多态是方法的多态:统一方法可以根据发送对象的不同采用不同的行为方式
父类和子类有联系,类型转换异常!classcastException
多态存在条件:继承关系,方法需要重写,父类引用指向子类对象 father fa=new Son()
不存在多态:1.static方法属于类,不能重写
2.final常量
3.private方法
例:父类:
public class person {
public void run(){
System.out.println("father");
}
}
子类:
public class man extends person {
public void run(){
System.out.println("son");
}
}
测试
public class Demo7 {
public static void main(String[] args) {
//一个对象的实际类型是确定的
// new man();
//new person();
//可以指向的引用类型是不确定的,父类的引用指向子类
//man可以执行的方法主要是继承父类的或自己的
//person不能调用man独有方法
man s1=new man();
person s2=new man();
Object s3=new man();
//对象能能执行哪些方法主要看对象左边方法和右边关系不大
s2.run();
s1.run();
}
}
结果:son
son
instanceof和类型转换
instanceof判断一个对象是什么类型
System.out.println(X instanceof Y);//能不能编译通过在于X与Y之间是否存在父子关系
父类:
public class person {
public void run(){
System.out.println("father");
}
}
子类
public class man extends person {
public void run(){
System.out.println("son");
}
public void eat(){
System.out.println("hello world");
}
}
测试
public static void main(String[] args) {
//类型之间的转换
//低转高,自动转换,子类转换为父类可能丢失自己的方法,例如s1.eat()不可执行
person s1=new man();
((man) s1).eat();
//man 将这个对象转换为man对象,就可以使用man类型的方法了
//高到低转换,强制转换
man s2=(man)s1;
s2.eat();
static关键字
静态方法中不能调用非静态方法,静态方法和类一起加载
public class woman {
private static int age;//可共享
private double score;
public void run(){
System.out.println("run");
}
public static void go(){
System.out.println("go");
}
public static void main(String[] args) {
woman wo=new woman();
wo.age=12;
System.out.println(woman.age);
System.out.println(wo.age);
System.out.println(wo.score);
woman.go();
wo.run();
go();
}
}
例:静态代码块、匿名代码块执行顺序
public class woman {
{//②对象创建后先走匿名代码块
System.out.println("匿名代码块");
}
static{//①:只执行一次,可用于赋初始值
System.out.println("静态代码块");
}
public woman() {//③
System.out.println("构造方法");
}
public static void main(String[] args) {
woman w=new woman();
System.out.println("=============");
woman w2=new woman();
}
}
结果:
静态代码块
匿名代码块
构造方法
=============
匿名代码块
构造方法
例:静态导入包
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进行实例化,只能依靠子类实现它的方法②抽象类可以写普通方法③抽象方法只能写在抽象类中
抽象类可以写普通方法
public abstract class Action {
//约束—有人帮我们实现
//abstract,抽象方法,只有方法的名字,没有方法的实现
public abstract void dosomething();
}
继承子类:
//继承抽象类的子类必须实现抽象类的方法,除非继承子类也是抽象类
public class C extends Action {
@Override
public void dosomething() {
}
}
接口(比抽象类还要抽象)
约束和实现分离
可以声明接口类型的变量(接口可以定义,但不能实例化)
-
接口的本质是一种约束
-
接口中定义了一些方法,让不同的人实现
-
接口中的方法都是抽象方法
-
接口中定义的变量都是常量
-
implements可以实现 多个接口
-
必须要重写接口中的方法
例:接口1:
package com.java.oop;
//interface
public interface userservice {
//接口中定义的是常量一般不定义在这样
int age=3333;
//接口中的所有定义都是抽象的,接口都要有实现类
void add(String name);
void delete(String name);
void update(String name);
void query(String name);}
接口2:
public interface Timeservice {
void timer();
}
实例:
//类可以实现接口
//实现了接口的类,就需要重写接口中的方法
//利用接口可实现多重继承
public class demo8 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 class outter {
private int ID;
public void out(){
System.out.println("外部类的方法");
}
public class Inner{
public void in(){
System.out.println("内部类方法");
}
//获得外部类思想私有属性
public void getid(){
System.out.println(ID);
}
}
}
测试:
public class Applicationtwo {
public static void main(String[] args) {
outter out=new outter();
//通过外部类实例化内部类
outter .Inner inin= out.new Inner();
inin.in();
inin.getid();
}
}
异常机制
-
检查性异常:用户错误或者问题引起的异常,程序员无法预见。
-
运行时异常:运行时异常是可能被程序员避免的异常,在编译时可悲忽略
-
错误:错误不是异常,错误在代码中通常会忽略,无法预料
java把异常当做对象来处理,并定义了一个基类java.lang.throwable来作为所有异常的超类
Error通常由java虚拟机运行错误生成抛出。当jVM不在有继续执行操作所需内存是,将出现OutOfMemonyError,这些异常发生时,java虚拟机一般会选择进程终止。
Exception:通常情况下可以被程序书里的,并且在程序中尽可能的去处理这些异常。
异常的处理
要捕获多个异常throwable最大异常写在最下面
快捷键:Ctrl Alt t自动生成异常框架
System.exit(0):自动终止程序
public class demo1 {
public static void main(String[] args) {
int a=1;
int b=0;
try{
//try监控区域
System.out.println(a/b);
}catch(ArithmeticException e){//catch(想要捕获的异常类型)捕获异常
System.out.println("程序出现异常,变量b不能为0");
}finally{//处理最后工作
//finally处理I/O流资源关闭工作
System.out.println("finally");
}
}
}
例:主动抛出异常throw/throws
public static void main(String[] args) {
int a=1;
int b=0;
try {
if(b==0){
//主动抛出异常,一般在方法中使用,假设在方法中处理不了异常,在方法名上抛出throws
throw new ArithmeticException();
}
System.out.println(a/b);
} catch (Exception e) {
//打印错误栈信息
e.printStackTrace();
}
}
自定义异常
继承Exception类
Alt+Enter提示键
package com.java.exception;
//自定义异常类
public class MyException extends Exception{
private int detail;
//传递数字大于10
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 {
if (a>10){
throw new MyException(10);
}
System.out.println("OK");
}
public static void main(String[] args) {
try {
test(1);
} catch (MyException e) {
System.out.println("出现异常"+e);
//增加处理异常代码块
}
}
}