1-java零基础学习视频通俗易懂
java使用规范
1、大小写敏感
2、尽量使用英文
3、文件名和类名一致,首字母大写
IDEA使用
一般建空项目,在项目中建立模块(也可以不建),然后在模块中建立类,类上面可以用软件包归类package
常用语法
//
就是单行写注释
/* */
多行注释
数据类型
基本类型
引用类型
//整数
int num1=10;//最常用
byte num2=20;
short num3=30;
long num4=30L;//long类型要在数字后面加个L
//小数,浮点数
float num5=50.1F;//float类型要在数字后面加F
double num6=3.124343;
//字符
char name="国“;//单字符
//字符串,String不是关键字,是类
//String name="陈陈";
//布尔值:是非
boolean flag=true;
类型转换
强制类型转换:高转换成低 -(类型)变量名
int i=128;
byte b=(byte)i
自动类型转换:低转换成高
int i=128;
double b=i
注意点:
布尔值不能转换
转换可能存在内存溢出问题
计算注意点
public class Demo01 {
public static void main(String[] args) {
int money=10_0000_0000;
int year=20;
int total=money*year;//-1474836480
long total2=money*year;//-1474836480,转换之前已经出现问题
long total3=money*(long)year;//计算前先进行转换就不会出现问题20000000000
System.out.println(total3);
}
}
变量
变量作用域
类变量:加了static关键字,随着类出现,也随着类消失,static为修饰符
实例变量:从属于对象,如果不自行初始化,这个类型默认值为0,布什值为false,除了基本类型,其他主null
局部变量:是指在方法内的变量,必须声明和初始化值
public class Helloworld {
static int allclicks = 0;//类变量
String name = "Hello, World!";//实例变量
public void method1() {
int i = 0;//局部变量
}
}
例子
public class Helloworld {
static double salary=25000;
String name;
int age;
public static void main(String[] args) {
int i = 10;
System.out.println(i);//10
Helloworld obj = new Helloworld();
System.out.println(obj.name);//null
System.out.println(obj.age);//0
System.out.println(salary);//25000
}
}
常量
final 常量类型 常量名 =值
命名规范
基本运算符
一元运算符,++,-- 自增 自减
public class Demo01 {
public static void main(String[] args) {
int a=3;
int b=a++;//b=3, a=4,a先赋值给了b,然后a自增,a++ a=a+1
int c=++a;//c=5, a=5,a先自增,然后赋值给了c
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
}
逻辑与运算
逻辑运算符
public class Demo01 {
public static void main(String[] args) {
boolean a = true;
boolean b = false;
system.out.println(a && b); // false,一个为false则结果为false
system.out.println(a || b); // true,一个为true则结果为true
system.out.println(!a); // false,取反
}
}
补充短路运算
public class Demo01 {
public static void main(String[] args) {
//短路运算
int a = 10;
boolean b = (a<9)&&(a++>5);
System.out.println(b); //输出false,第一个是false,第二个表达式a++>5不执行,所以a=10,所以b=false
System.out.println(a); //输出10
}
}
位运算符,底层
public class Demo01 {
public static void main(String[] args) {
//位运算符
/*
A=00111100;
B=00001101;
A&B=00001100;
A|B=00111101;
A^B=00110001;
~A=11000011;
2*8=16 2*2*2*2=16
<< *2
>> /2
*/
System.out.println(2<<3);//16
}
}
扩展
public class Demo01 {
public static void main(String[] args) {
int a = 10;
int b = 5;
a+=b; // a= a + b, a=15
a-=b; // a = a - b
//字符串连接符 +string
System.out.println(""+a+b);//输出105,
System.out.println(a+b+"");//输出15
}
}
三元运算符
public class Demo01 {
public static void main(String[] args) {
//x?y:z
//如果x为true,则返回y,否则返回z
int score = 85;
String type=score>=90?"优秀":"良好";
System.out.println(type);//输出:良好
}
}
javadoc
/**
*@author
*@param
*/
文档能写在类中也能写在方法中
使用idea生产javadoc文档
JAVA流程控制
用户交互scanner
public class Demo01 {
public static void main(String[] args) {
//从键盘接收数据
Scanner scanner = new Scanner(System.in);
System.out.println("Enter your text: ");
String str = scanner.nextLine();//把Enter前的内容赋值给变量str,next是有空格就断了,比较少用
System.out.println("你输入的内容是: "+str);
scanner.close();//属于IO流,必须关闭,否则会一直执行,占用资源
}
}
//固定语句,在里面输入
Scanner scanner = new Scanner(System.in);
..
scanner.close();
ctrl+类名可以查看这个类中有什么方法,
补充scanner其它方法
public class Demo01 {
public static void main(String[] args) {
//从键盘接收数据
Scanner scanner = new Scanner(System.in);
int i=0;
float f=0.0f;
System.out.print("请输入整数:");
if(scanner.hasNextInt()){//判断输入的是否为整数
i = scanner.nextInt();
System.out.println("整数为:" + i);
}else{
System.out.println("输入有误,请输入整数!");
}
scanner.close();//属于IO流,必须关闭,否则会一直执行,占用资源
}
}
流程控制
if结构
public class Demo01 {
public static void main(String[] args) {
if (布尔表达式) {
}
}
}
public class Demo01 {
public static void main(String[] args) {
if (布尔表达式) {
}else{
}
}
}
public class Demo01 {
public static void main(String[] args) {
if (布尔表达式) {
}else if (布尔表达式) {
}else if (布尔表达式) {
}else {
}
}
switch结构
public class Demo01 {
public static void main(String[] args) {
char grade = 'F';//switch现在也支持String类型
switch (grade) {
case 'a':
System.out.println("Excellent");
break;//如何没加break,会执行后面的语句
case 'b':
System.out.println("Good");
break;
case 'c':
System.out.println("Satisfactory");
break;
case 'd':
System.out.println("Pass");
break;
case 'f':
System.out.println("Fail");
break;
default:
System.out.println("未知等级");
}
}
}
把class文件拉到idea的src中可以进行反编译
while循环结构
while(布尔表达式){
循环内容
}
public class Demo01 {
public static void main(String[] args) {
//输出1-100
int i =0;
while(i<100){
i++;
System.out.println(i);
}
}
}
Dowhile循环
do{
//代码语句
}while(布尔表达式)
与while的区别,while是先判断后执行,dowhile是先执行后判断
public class Demo01 {
public static void main(String[] args) {
int a=0;
while(a<0){
System.out.println(a);
a++;
}
System.out.println("========");
do{
System.out.println(a);
a++;
}while(a<0);
}
}
//上面不输出任何东西,下面输出0
for循环
for(初始化;布尔表达式;更新){
//代码语句
}
public class Demo01 {
public static void main(String[] args) {
int a=1;
while(a<=100){
System.out.println(a);
a+=2;
}
System.out.println("whilt循环结束");
for(int i=1;i<=100;i++){
System.out.println(i);//输出1到100,逻辑就是和while循环一样,先执行print(循环体里面的代码模块),然后i++
}
System.out.println("for循环结束");
}
}
增加for循环-一般是用于数组或集合
for(声明语句:表达式)
{
//代码句子
}
public class Demo01 {
public static void main(String[] args) {
int [] numbers = {1, 2, 3, 4, 5};
for(int x : numbers){
System.out.println(x);
}
}
}
break强行退出循环
public class Demo01 {
public static void main(String[] args) {
int i =0;
while(i<100){
i++;
System.out.println(i);
if(i==30){
break;
}
}
}
}
continue用于终止某次循环过程
public class Demo01 {
public static void main(String[] args) {
int i =0;
while(i<100){
i++;
if(i%10==0){
System.out.println();
continue;//当等于10时,直接跳过下面的代码,又回到while循环的开头,继续执行
}
System.out.print(i);
}
}
}
//123456789
//111213141516171819
//212223242526272829
//313233343536373839
//414243444546474849
//515253545556575859
//616263646566676869
//717273747576777879
//818283848586878889
//919293949596979899
goto了解就行,一般是配合标签跳到指定循环
多用Debug的方式调试,在对应的行打断点,点击飘虫,下面会输当前变量的值 ,然后再下一行,可以实时看到变量的值和程序的运行
方法
public class Demo01 {
public static void main(String[] args) {
int sum = add(10, 20);
System.out.println(sum);
}
//加法
public static int add(int a, int b){
return a+b;
}
}
java的方法类似其他语言的函数,用来完成特定功能的代码片段
Java的包=python的库
Java的类=python的模块
Java的方法=python的函数
方法包含方法头和方法体:
方法头构成
修饰符:可选,告诉编译器如何调用该方法,定义了该方法的访问类型
返回值类型:方法可能有返回值,返回值的数据类型,如果没有返回值就用void
方法名
参数类型,参数也是可选的
方法体
格式
修饰符 返回值类型 方法名(参数类型 参数名){
方法体
return 返回值
}
return不单可以返回值,但为0时,就是终止程序
public class Demo01 {
public static void main(String[] args) {
int result = max(10, 10);
System.out.println("最大值:" + result);
}
//加法
public static int max(int a, int b) {
int result = 0;
if (a == b) {
System.out.println("两个数相等");
return 0;//这里的return 0 是终止方法,跳出方法,不执行后续代码
} else if (a > b) {
result = a;
} else {
result = b;
}
return result;
}
}
方法调用
当方法返回一个值时,就方法调用通常被当成一个值,需要用变量承载
int larger=max(30,40);
当方法返回值是void时,方法调用一定是一条语句
system.out.println()
方法的重载
重载就是在一个类中,有相同的函数名称,但形参不同的函数
规则:
1、方法名称要一样
2、参数列表要不同(个数,类型,顺序不同)
3、返回类型可以相同也可以不同
举例,调用max(),参数可以2个也可以3个,类型也可以不一样,但是要在方法定义好
命令行传参了解下就可以了
可变参数
方法声明时,指定参数类型后加一个省略号...
一个方法只能指定一个可变参数,而且是方法的最后一个参数,任何普通参数要在它之前声明
public class Demo01 {
public static void main(String[] args) {
Demo01 demo = new Demo01();
demo.test(1,2,3,4,5);// 1
}
public void test(int ...i){
System.out.println(i[0]);
}
}
递归
递归就是:A方法调用A方法,自己调用自己
递归结构包括两个部分:
递归头:什么时候不调用自身方法,如何没有头,将陷入死循环
递归体:什么时候需要调用自身方法
public class Demo01 {
public static void main(String[] args) {
System.out.println(f(3));//数少还行,数多容易崩,递归方法以不用就不用,了解即可
}
public static int f(int n){
if(n==1){
return 1;//递归头
}else{
return n*f(n-1);//输入n=3时,,就是3*2*1,最后等于6//递归体
}
}
}
数组
数组就是相同类型数据的有序集合
数组的声明和创建
public class Demo01 {
public static void main(String[] args) {
//变量类型 变量名字=变量的值
//数组类型int[]
//1、先声明数组变量,2、再使用new关键字创建数组,1和2可以合并3、再给数组元素赋值
//int[] nums;//声明数组,首选,也能写成int nums[];
int[] nums=new int[2];
nums[0]=1;//如果没有赋值会默认0
nums[1]=2;
System.out.println(nums[0]);//1
}
}
栈和堆的概念
在栈中声明数组的变量
在堆中创建数组空间,只要是用到new的,都是一个对象,数组也是对象,都是放在堆中
三种初始化
1、静态初始化
2、动态初始化
3、默认初始化
public class Demo01 {
public static void main(String[] args) {
//静态初始化:创建+赋值
int [] a={1,2,3,4,5};//可以直接初始化数组,跳过new操作
System.out.println(a[0]);//输出数组第一个元素
//动态初始化:包含默认初始化,就是还没赋值的元素都为0
int[] b=new int[10];
b[0]=10;
System.out.println(b[0]);//10
System.out.println(b[1]);//0
}
}
数组的长度是确定的,不可变的,如果越界,则报ArrayIndexOutofBounds的错误提示
数组使用
1、for循环
2、for-each循环
3、数组作方法入参
4、数组作返回值
第一种方式
public class Demo01 {
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]);
}
}
}
第二种方式-快捷键arrays.for+ctrl&enter
public class Demo01 {
public static void main(String[] args) {
int [] arrays={1,2,3,4,5};
for (int array : arrays) {
System.out.println(array);
}
}
}
第三种方式
public class Demo01 {
public static void main(String[] args) {
int [] arrays={1,2,3,4,5};
printArray(arrays);
}
public static void printArray(int[] arrays){
for(int i=0;i<arrays.length;i++) {
System.out.println(arrays[i]);
}
}
}
多维数组
public class Demo01 {
public static void main(String[] args) {
/*
1 2
2 3
3 4
4 5
*/
int[][] array={{1,2},{2,3},{3,4},{4,5}};
System.out.println(array[0][0]);//1
System.out.println(array[0][1]);//2
}
}
arrays类讲解
public class Demo01 {
public static void main(String[] args) {
int[]a={1,3,45,45,563,46,7,8,9,10};
System.out.println(Arrays.toString(a));
Arrays.sort(a);//排序
System.out.println(Arrays.toString(a));//[1, 3, 7, 8, 9, 10, 45, 45, 46, 563]
}
}
冒泡排序
最为出名的排序算法之一,总共有八大排序
public class Demo01 {
public static void main(String[] args) {
//冒泡排序
//1、比较数组中,两个相邻的元素,如果第一个元素比第二数大,就交换他们的位置
//2、每一次比较,都会产生一个最大一个最小
//3、下一轮则可以少一次排序;
//4、重复以上步骤,直到数组排序完成。
int[] arr = {5, 3, 8, 6, 2, 7, 1, 4};
sort(arr);
System.out.println(Arrays.toString(arr));
}
public static int[] sort(int[] array) {
int temp = 0;//临时变量,通过这个第三方变量来交换元素
//外层循环判断要走多少次
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;
}
}
}
return array;
}
}
稀疏数祖
面向对象编程
1、面向对象的思路来分析整个系统,具体到微观操作,仍然需要面向过程的思路去处理
2、面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据
3、抽象:就是把共同的特征抽取出来,把象的特征抽取出来
4、三大特性:
封装
继承
多态
5、从认识角度考虑先有对象后有类,对象,是具体的事物,类,是抽象的,是对对象的抽象,-也就是把相似的特征抽象成类
但从代码运行角度考虑是先有类后有对象,类是对象的模板
方法回顾
方法调用
静态方法和非静态方法的区别,有没加static的区别
有加static,另一个类调用,可以直接类加方法调用
非静态方法,需要先new一个对象出来才能用类方法
类和对象的创建
使用new关键字创建的时候,除了分配内存空间之外(参考数组的new),还会给创建好的对象进行默认初始化以及对类中构造器的调用
Student s1=new Student();
Student s1是对象引用
使用new时相当于调用了类的构造器,并走了一遍构造器后,才给s1进行赋值
构造器详解
1、构造器(可以理解为是类自带的方法)是建完类后自动生成的,通常格式是public+类名,没有返回值
2、new后,是走完一遍构造器,才生成对象。可以理解new的本质就是在调用构造器(可以用debug试下)
3、构造器,一般拿来初始化值
4、快捷键,属标右键生成,可以构造有参或无参的构造器
5、this+变量名,this表示当前类
6、如果构造器写了有参构造,那就把无参构造也一起写了,否则new的时候会报错,一般new的时候不写参数,会自动调用无参构造,如果这个时候发现类没有无参构造,就会报错,除非new的时候马上写上参数,
7、构造器分为无参构造,有参构造,默认构造(就是无参构造,里面什么方法都没有)
创建对象内存分析
栈只是放了个变量名,真正的对象是放在堆中
封装
属性私有get/set
封装一般是用于属性
生成里面有自动生成get和set的方法
public class Student {
//属性私有
private String name;
private int id;
private char sex;
//提供可以操作这个属性的方法
//提供一些public的get\set方法
//get 获得这个数据
public String getName() {
return this.name;
}
//set 设置这个数据
public void setName(String name) {
this.name = name;
}
}
package operator;
//一个项目应用只有一个main方法
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
//s1.name//因为Student的name属性是private的,所以不能直接访问,需要通过getter方法获取
s1.setName("Tom");
System.out.println(s1.getName());
封装的意义,可以在类的方法中限定条件,列如年龄的限制,使用得对象赋值更加合理
封闭的意义
1、提高程序的安全性,保护数据
2、隐藏代码的实现细节
3、统一接口,只能get或set
4,系统可维护增加了
继承
extends
public class Student extends Person{
}
ctrl+H,可以快速查看继承关系
package operator;
//父类
//子类继承了父类,就会拥有父类的全部方法
public class Person {
//public方法,如果想让子类继承父类所有东西,就得用public方法
//private,无法被子类继承,但会通过留有的方法来实现继承功能
public void say(){
System.out.println("I am a person.");
}
}
import operator.Student;
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.say();
}
}
JAVA中,所有的类,都默认直接或间接继承Object类
JAVA中类只有单继承,没有多继承,只有一个爸爸,但是爸爸可以有多个儿子
super详解
package operator;
public class Person {
public Person(String name) {
System.out.println(name);
}
protected String name="cjf";
private int age=25;
}
package operator;
//派生类或叫子类
public class Student extends Person{
public Student() {
super("cjf");
//有隐藏代码,调用了父类的无参构造,这个隐藏代码就是super();
//调用父类的构造器,必须要在子类的构造器之前调用,否则会报错。无参时默认调用,不用写。除非父类有参数,就要写了.注意,父类如果是有参构造时,顺便把无参构造也写了,否则子类在调用父类的构造器时会报错,除非马上把super(参数)也写了
//this()和super()只能选一个,又不调用父类构造器,又不调用子类构造器,调完再写自身的构造器的方法,this可用于调用自身构造器的方法,列如同时写了无参和有参构造器方法,无参构造器用this调用有参构造器
System.out.println("Student 无参执行");
}
//protected String name="cjfcjf";
//public void test(String name){
//System.out.println(name);//john
// System.out.println(this.name);//类的方法
//System.out.println(super.name);//父类的属性
// System.out.println(super.age);//父类的属性加了private,就不能继承
//}
}
import operator.Student;
public class Application {
public static void main(String[] args) {
Student student = new Student();//调用构造器时,会先调用父类的构造器,然后才是子类的构造器,
// Person 无参执行
//Student 无参执行
//有参后
cjf
Student 无参执行
//student.test("John");
}
}
super注意点
1、super调用父类的构造方法,要在构造方法的第一个,父类是无参构造方法时,子类super可以默认不写,如果父类是有参构造方法时,子类要先写super(参数),再写子类的构造方法
2、super必须只能出现现在子类的方法或者构造方法中
3、super和this不能同时调用构造方法
vs this
代表的对象不同
this 本身调用者这个对象
super代表父类对象的应用
前提
this 没继承者也可以使用
super只有继承条件才可以使用
构造方法
this()本类的构造
super()父类的构造
方法重写
方法重写都是和方法相关,和属性无关
package operator;
public class Person {
public static void test() {
System.out.println("person=<test()");
}
}
package operator;
//派生类或叫子类
public class Student extends Person {
public static void test() {
System.out.println("Student=>test()");
}
}
import operator.Student;
import operator.Person;
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.test();
//静态的方法和非静态的方法区别很大
//静态方法,方法的调用只和左边,定义的数据类型有关,就是以子类和父类的方法都加了static关键字
Person P = new Student();
P.test();
//Student=>test()
//person=<test()
//student.test("John");
}
}
当子类和父类方法都加static时,调用的都是各自类的方法
当子类和父类方法都不加static时,调用的都是子类的方法(重写后的方法)
更多参考看这个链接https://mp.weixin.qq.com/s/N6SeN6p0UbR7a84fo64iPg
package operator;
public class Person {
public void test() {
System.out.println("person=<test()");
}
}
package operator;
public class Student extends Person {
public void test() {
System.out.println("Student=>test()");
}
}
import operator.Student;
import operator.Person;
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.test();
//静态的方法和非静态的方法区别很大
//静态方法,方法的调用只和左边,定义的数据类型有关,就是以子类和父类的方法都加了static关键字
Person P = new Student();
P.test();
//Student=>test()
//Student=>test()
}
}
子类重写父类方法的快捷键:右键,生成,重写方法,会自动生成
public class Student extends Person {
@Override
public void test() {
super.test();
}
}
重写:需要继承关系,子类重写父类方法
1、方法名,必须相同
2、参数列表必须相同
3、修饰符,范围可以扩大不能缩小,public>protested>Default>private
4,抛出的异常范围,可以被缩小,但不能扩大,classnotfoundexception<exceltion
重写,子类方法和父类要一致,方法体不同
为什么要重写,父类的功能,子类不一定需要,或者不一定满足
多态
package operator;
//派生类或叫子类
public class Student extends Person {
@Override
public void run() {
System.out.println("学生在跑步");
}
public void study() {
System.out.println("学生在学习");
}
}
import operator.Student;
import operator.Person;
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
Person s2 = new Student();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
s2.run();//学生在跑步,因为子类父类方法都去掉static修饰符了,子类方法重写了,所以s2调用的是子类的run方法
s1.run();//学生在跑步,
s2.study(); //报错了,因为s2是Person类型,没有study方法,对象能对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
s1.study(); //学生在学习
student能调用的方法都是自己的或者继承父类的
person父类型,可以指向子类,但是不能调用子类独有的方法
package operator;
//派生类或叫子类
public class Student extends Person {
@Override
public void run() {
System.out.println("学生在跑步");
}
public void study() {
System.out.println("学生在学习");
}
}
import operator.Student;
import operator.Person;
public class Application {
public static void main(String[] args) {
//student能调用的方法都是自己的或者继承父类的
Student s1 = new Student();
//person父类型,可以指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
s2.run();//学生在跑步,因为子类父类方法都去掉static修饰符了,子类方法重写了,所以s2调用的是子类的run方法
s1.run();//学生在跑步,
s2.study(); //报错了,因为s2是Person类型,没有study方法,对象能对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
s1.study(); //学生在学习
}
}
总结,
当使用多态方式Father f1=new Son();调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
如果子类没有重写方法,那实例化后的对象,调用的方法都是父类的方法
如果子类重写了方法,那用多态方式后的f1,调用的方法都是子类的方法,但是方法不能有static,例如public void study()
person对象无法调用子类的新方法,只有student对象可以调用子类的新方法,需要使用到强制转换,也就是(Rabbit)zoo。
格式为:(类型名)变量名。
多态注意事项
1、多态是方法的多态,属性没有多态
2、父类和子类有联系,类型转换异常会报classcastexception
3、多态存在条件,缺一不可:1、继承关系,2、方法需要重写,3、父类引用指向子类对象Father f1=new Son();
标注:(3)向上转型:就是要将父类引用指向子类对象,只有这样该引用才既能调用父类的方法,又能调用子类的方法。只有满足了以上3个条件才能实现多态,开发人员也才能在同一个继承结构中,使用统一的代码实现来处理不同的对象,从而执行不同的行为。-不重写就能调用父类的方法,重写就能调用子类的方法-只看左边类型,无重写调用父类方法,有重写调用子类方法
package operator;
public class Person {
public void run() {
System.out.println("run");
}
public void eat() {
System.out.println("eat");
}
}
package operator;
public class Student extends Person {
@Override
public void eat() {
System.out.println("我是中文吃吃吃");
}
}
import operator.Student;
import operator.Person;
public class Application {
public static void main(String[] args) {
Person s1 = new Student();
s1.run();//run
s1.eat();//我是中文吃吃吃
}
}
哪些方法不能被重写
a,static方法,属于类,它不属于实例
b,final常量
c,private方法
instanceof和类型转换
//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 teacher);//false
类型转化
package operator;
public class Student extends Person {
public void study() {
System.out.println("I am studying.");
}
}
import operator.Student;
import operator.Person;
public class Application {
public static void main(String[] args) {
//类型之间的转化:父 子
//高 低
Person p = new Student();//低转高,不需要强行转化
//将这个p对象转换成Student类型,我们就可以调用Student的方法了,高转低,需要强行转化
Student p1 = (Student) p;
p1.study();//I am studying.也能简写成((Student) p).study();
//子类转为父类,可能会丢失自己本来的一些方法
Student student = new Student();
student.study();
Person person = student;//小转大,不需要强行转化
person.study();-出现报错,向上转型,会丢失子类中原本可直接调用的特有方法(增加的方法)
}
}
1、父类引用指向子类的对象
2、把子类转换成父类,向上转型
3、把父类转换成子类,向下转型,强制转换,高转低
4、方便方法的调用,减少重复的代码
总结:
1、new子类对象时,会先走子类的构造方法,但是子类构造方法中开头会有super(),所以会再走去父类的构造器,走完再回子类的构造器,最后回到new的对象
package operator;
public class Person {
public Person() {
}
public Person(String name) {
System.out.println("Hello, my name is " + name + "!");
}
public void say() {
System.out.println("Hello, I am a person.");
}
}
package operator;
public class Student extends Person {
public Student() {
super("Student");
System.out.println("Student Constructor");
}
}
2、new对象后,调用方法时,如果调用该方法子类没有的话,会去父类中调(子类继承父类的方法的原理),如果子类重写了方法,则调用该方法,会到子类调完就回来主程序了
3、Student student = new Student();
Person student2 = new Student();子类重写了方法后,两个对象调用方法走了是一样的路径,不同时前面的对象可以直接调用子类的其它方法,后面要做转化才能做转化
4、sudent2s相当于new Student了一个子类对象,然后赋值给了父类对象student2,所以stduent2可以用子类的方法,(相当于子转父,不需要强转)
package operator;
public class Person {
public void sayHello() {
System.out.println("Hello, I am a person.");
}
}
package operator;
public class Student extends Person {
public void sayHello() {
System.out.println("Hello, I am a student.");
}
}
import operator.Student;
import operator.Person;
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.sayHello();//Hello, I am a student.
Person student2 = new Student();
student2.sayHello();//Hello, I am a student.
}
}
static关键词详解
static是类独有的方法,只要加了,其他人就用不了,只有本类能用
package operator;
public class Student extends Person {
private static int age;//静态的变量
private double score;//非静态的变量
public void run() {
}
public static void go() {
}
public static void main(String[] args) {
Student s1 = new Student();
System.out.println(Student.age);//类变量
//System.out.println(Student.score);//报错,非静态变量
System.out.println(s1.age);//实例变量
System.out.println(s1.score);//实例变量
go();//可以直接调用静态方法
Student student = new Student();
student.run();
}
}
package operator;
public class Person {
{
//代码块,(匿名代码块),在构造器之前执行
}
static{
//静态代码块,(静态初始化块),在类被加载时执行一次,
}
}
public class Person {
{
System.out.println("匿名代码块");//一般拿来赋初值
}
static{
System.out.println("静态代码块");//只执行一次
}
public Person() {
System.out.println("构造方法");
}
public static void main(String[] args) {
Person p = new Person();
//输出结果静态代码块
//匿名代码块
//构造方法
Person p2 = new Person();
//匿名代码块
//构造方法
}
静态导入包,了解即可,很少这么玩
用final修饰后,就不能被继承了,例如pubic final class person,
抽象类
1、抽象类不能new,只能靠子类去实现
2、抽象类可以写普通方法
3、抽象方法只能在抽象类中
package operator;
//abstract抽象类,类只能单继承
public abstract class Action {
//约束,别人帮忙实现这个方法
//抽象方法,只有方法名字,没有方法实现
public abstract void doSomething() {
}
package operator;
//抽象类的方法,经过继承后,子类必须实现该方法
public class A extends Action{
@Override
public void doSomething() {
}
}
接口
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)都有
接口:只有规范,自己无法写方法,专业的约束,约束和实现分离,面向接口编程
package operator;
//interface 定义的关键词,接口都需要有实现类
public interface UserService {
//接口中的所有定义其实都是抽象的
//接口中所有定义的方法其实都是抽象的public abstract,只是可以省略不写
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
package operator;
//类可以实现接口,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) {
}
}
作用
1、约束
2、定义一些方法,让不同的人实现
3、所有的方法都是public abstract可以省略不写
4、所有的常量都是public static final
5、接口不能被实例化,接口中没有构造方法
6、imliemens可以实现多个接口
7、必须重写接口中的方法
内部类
A类中定义一个B类,那么B类相对A类来说就是内部类,A类相对B类来说就是外部类
1、成员内部类
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);
}
}
}
package operator;
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.getId();
}
}
2、静态内部类
就是内部类加上static
内部类可访问static,但是static的内部类不能访问外部非静态的属性
package operator;
public class Outer {
}
//一个java类可以有多个class 类,但是只能有一个目标public class
class A{
//可以拿来做测试写main方法
}
3、局部内部类
package operator;
public class Outer {
// 局部内部类
public void method() {
class Inner {
public void innerMethod() {
}
}
}
4、匿名内部类
package operator;
public class Outer {
public static void main(String[] args) {
//没有名字的初始化类,不用实例保存到变量中
new Inner().method();
new UserService() {
@Override
public void hello() {
}
}
}
}
class Inner {
public void method() {
System.out.println("Inner method");
}
}
interface UserService {
void hello();
}
异常机制
Exception例外,就是异常
文件找不到,网络连接失败,非法参数等等
三种异常
1、检查性异常
2、运行时异常
3、错误error(大部分错误和程序无关)
Exception一般是程序逻辑错误引起(可能编译都无法通过)
error通常是灾难性的,程序无法控制 ,遇到这些情况时,JVM会直接终止进程,Exception通常可以被程序处理,并且在程序中尽可能去处理这些异常
异常:捕获和抛出异常
try catch finally,throw,throws
package operator;
public class Test {
public static void main(String[] args) {
int a=1;
int b=0;
try {//try监控区域
System.out.println(a / b);
}catch(ArithmeticException e) {//出现这个异常,就会执行catch块,可以写最大的异常处理,也可以写好几个catch,一般把最大的异常放在最后一个
System.out.println("程序出现 异常");
}finally {//无论是否出现异常,都会执行finally块
System.out.println("程序执行结束");
}
//finally 可以不用,假设IO,资源关闭,善后工作
}
}
ctrl+Alt+t,快捷键
throw用法
package operator;
public class Test {
public static void main(String[] args) {
try {
new Test().test(10, 0);
} catch (ArithmeticException e) {
e.printStackTrace();//主动抛出异常,显示Cannot divide by zero,程序终止
}
}
//假设这方法中,处理不了异常,方法上抛出
public void test(int a, int b) throws ArithmeticException {
if(b==0){
throw new ArithmeticException("Cannot divide by zero");//主动抛出异常,一般在方法中使用
}
}
}
自定义异常
用户可以自定义类,只需继承Exception类即可
双击shift打开搜索功能
参考throw的用法
总结
1、处理异常时,采用try catch处理
2、多重catch,可以加一个catch(Exception)来处理可能会遗漏的异常
3、尽量添加finally语句去释放占用的资源
、
最后总结补充
1、数据类型分为基础类型和引用类型
基础类型:整数(byte\int\short\long),浮点数(float\double),字符(char),布尔(boolean)共8种
引用类型:类、接口、数组
2、大部分引用类型都是需要通过new才行,走内部的构造方法,除了像String等比较特殊,可以直接赋值
引用类型就是类的类型,例如Stduent,所有的对象都是引用类型,包括数组对象。引用类型必须使用new调用构造方法进行赋值,引用类型的变量(对象引用)拥有自己的属性和方法,
数组和列表不一样,数组里面的类型要一样,列表可以不一样
3、Car myCar = new Car();
左边:Car就是引用类型,myCar就是对象引用,
右边:就是对象,被new出来的对象
在堆中创建一个对象,然后引用赋值给myCar,mycar变量在栈中,
这行代码会在内存中创建一个新的Car对象,并将它的引用赋值给myCar。创建对象后,可以通过点操作符(.)来访问对象的属性和方法:
4、引用类型和对象的关系主要体现在引用类型用于存储对象的引用,而不是对象本身。引用类型变量(对象引用)存储的是对象在内存中的地址,通过这个地址可以间接访问和操作对象。
引用类型是一种数据类型,用于存储对象引用(或称为句柄)。当声明一个引用类型的变量时,该变量并不直接存储对象本身,而是存储了一个指向对象在内存中位置的地址。这意味着通过引用类型的变量,可以间接地操作对象,(不像基本类型,变量直接存储值)
定义和创建:对象是类的实例,而对象引用是用于指向这些对象的变量。例如,在Java中,Person person = new Person("张三"); 这行代码创建了一个Person类的对象(右边),而person就是一个对象引用,它指向这个新创建的对象
关系:一个对象可以被一个或多个对象引用所引用,而一个对象引用可以指向零个或一个对象。这种关系类似于一夫多妻制,一个丈夫(对象)可以有多个妻子(对象引用),而一个妻子(对象引用)只能有一个丈夫(指向一个对象)
区别:引用类型变量存储的是对象的地址,而对象本身是类的实例。例如,在Java中,Person person; 这行代码声明了一个引用类型变量person,但它并没有指向任何对象。只有通过person = new Person("张三"); 这行代码,person才真正指向了一个新创建的对象
联系:通过引用类型的变量,可以间接访问和操作对象。例如,可以通过person.name或person["name"]来访问对象的属性
4、基本数据类型保存在栈里面,可以直接访问它的值,引用数据类型保存在堆里面,栈里面保存的是地址,通过栈里面的地址去访问堆里面的值
栈和堆文章参考https://zhuanlan.zhihu.com/p/28654272
5、命名规范:
类,StudnetOne
变量和方法:teacherOne
常量:STUDENT_ONE
6,a\同一个包的类不需要import,可以直接类名+方式或new
b\如果类中的属性或方法加上了static,那像主程序引入类时,可以直接类名+方法,或类名+属性,没加static,只能通过new了对象,再通过对象使用方法或属性,可以理解加了staic后,方法和属性就是类独有的-只是会很少这样用
c\static是类独有的方法,只要加了,其他人就用不了,只有本类能用,继承时父类的方法不能用static,不然子类重写不了方法
7、什么时候可以定义静态变量?当类中出现所有对象都共有的数据时,该字段就可以定义成静态的。比如刚才说的学生类里的国家这个字段就可以定义成静态的
什么时候可以定义静态方法?当方法内部没有使用到非静态数据(对象的特有数据)时,那么该方法就可以定义成静态的大家平常见到的工具类 XxxUtils就很符合上边的场景,所以大家见到的工具类基本上都是静态的,不用new对象,直接XxxUtils.xxx()调用
3、静态的其他内容理解 理解了上述内容后,下边的内容就不难理解了静态:static关键字static关键字的用法:它是一个修饰符,用于修饰成员(成员变量,成员方法)静态的特点:1、随着类的加载而加载(就是说这个类一被加载进内存,静态的东西就随着加载进去了, 这时候对象还不存在呢)2、静态先于对象存在3、被所有的对象共享4、可以直接被类名调用,也可以被对象调用
静态使用的注意事项:1、静态方法只能访问静态成员(属性和方法),不能访问非静态成员。因为静态在的时候非静态的还没在呢2、非静态方法可以访问静态成员,也可以访问非静态成员3、因为静态先于对象的存在而存在,所以静态方法中不可以出现this、super关键字。
静态的利弊:1、利:对于所有对象都共有的数据,没必要每个对象中都存在一份,可以使用静态,节省空间;可以不new对象,直接用类名调用2、弊:因为静态是随着类存在的,所以生命周期过长;访问出现局限性,只能访问静态
https://mp.weixin.qq.com/s/-_HERFTyMiAkv0wQ--RXqA
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理