Java基础学习笔记

文章详细介绍了Java中的多态特性,包括其好处和调用特点,以及如何通过类型转换来利用多态。接着,讨论了包、final关键字的使用,权限修饰符的分类和规则。此外,还详细阐述了抽象类、抽象方法,以及接口的概念、定义和使用。内部类的部分涵盖了成员内部类、静态内部类、局部内部类和匿名内部类。最后,提到了Math和System类的一些常用方法。
摘要由CSDN通过智能技术生成

目录

多态

多态调用成员的特点

final

权限修饰符

权限修饰符的分类

权限修饰符的使用规则

代码块

抽象类

抽象方法和抽象类的定义格式

要么是抽象类

接口

接口的定义和使用

接口中的成员变量

接口和类之间的关系

JDK8开始接口中的新增的方法

初始内部类

什么是内部类

内部类的分类

成员内部类

静态内部类

局部内部类

匿名内部类

常用API

Math

Math类的常用方法

System

多态

同类型的对象,表现出的不同形态

父类对象 对象名称 = 子类对象;
学生形态
Student s = new Student();
人的形态
Person p = new Student();

多态的前提

*有继承关系        *有父类引用指向子类对象        *有方法重写

F f = new Z(); 

多态的好处:使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利

多态调用成员的特点

*变量调用:编译看左边,运行也看左边

*方法调用:编译看左边,运行看右边

多态的优势

*在多态形势下,右边对象可以实现解耦合,便于扩展和维护

Person p = new Student();
p.work();		//业务逻辑发生改变时,后续代码无需修改

*定义方法的时候,使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利

*方法中,使用父类型作为参数,可以接收所有子类对象

多态的弊端

*不能使用子类的特有功能

引用数据类型的类型转换,有几种方式?

自动类型转换		Person p = new Student();
强制类型转换		Studnet s = (Student)p;

强制类型转换能解决什么问题

*可以转换成真正的子类类型,从而调用子类独有功能

*转换类型与真实对象类型不一致会报错

*转换的时候用instanceof关键字进行判断

//新特性,先判断a是否为Dog类型,如果是,则强转成Dog类型,转换之后变量名为id,如果不是,则不强转,结果直接是false

if(a instanceof Dog d)
{
​	d.lookHome();
}
else if(a intanceof Cat c)
{
​	c.catchMouse();
}
else
{
​	System.out.println("没有这个类型,无法转换");
}

包就是文件夹,用来管理各种不同功能的Java类,方便后期代码维护

*包名的规则:公司域名反写 + 包的作用,需要全部英文小写,见名知意。例如:com.itheima.domain

package com.itheima.domain;
public class Student
{
​	私有化成员变量
​	构造方法
​	成员方法
}

全类名 全限定名(包名 + 类名)

com.itheima.domain.Student

使用其它类的规则

import com.itheima.domain.Student;
public class Test{
​	public static void main(String[] args){
​		Student s = new Student();
​	}
}

*使用同一个包中的类时,不需要导包

*使用java.lang包中的类时,不需要导包

*其他情况都需要导包

*如果同时使用两个包中的同名类,需要用全类名

final

最终的 ->不可被改变

方法 表明该方法是最终方法,不能被重写

类 表明该类是最终类,不能被继承

变量 变成常量,只能被赋值一次

常量:

实际开发中,常量一般作为系统的配置信息,方便维护,提高可读性

命名规范:*单个单词:全部大写 *多个单词:全部大写,单词之间用下划线隔开

细节:

final修饰的变量是基本类型:那么变量储存的数据值不能发生改变

final修饰的变量是引用类型:那么变量储存的地址值不能发生改变,对象内部的可以改变

权限修饰符

*权限修饰符:是用来控制一个成员能够被访问的范围的

*可以修饰成员变量,方法,构造方法,内部类

权限修饰符的分类

private私房钱,只能自己的类用
默认friendly只能本包中能用
protected受保护的,不同包下的无关类不能用,不同包下的子类可以用
public公共的,所有的都可以用

权限修饰符的使用规则

*成员变量私有

*方法公开

特例:如果方法中的代码是抽取其他方法中共性代码,这个方法一般也私有

代码块

*局部代码块(淘汰)

提前结束变量的生命周期

*构造代码块(不够灵活)

1.写在成员位置的代码块

2.作用:可以把多个构造方法中重复的代码抽取出来

3.执行时机:我们在创建本类对象的时候会先执行构造代码块再执行构造方法

*静态代码块

格式:static{}

特点:需要通过static关键字修饰,随着类的加载而加载,而且自动触发,只执行一次

使用场景:在类加载的时候,做一些数据初始化的时候使用

抽象类

*抽象方法:将共性的行为(方法)抽取到父类之后。由于每一个子类执行的内容是不一样的,所

以在父类中不能确定具体的方法体。该方法就可以定义为抽象方法

*抽象类:如果一个类中存在抽象方法,那么该类就必须声明为抽象类

抽象方法和抽象类的定义格式

*抽象方法的定义格式:

	public abstract 返回值类型 方法名(参数列表);

*抽象类的定义格式:

    public abstract class 类名{}
public class Person{
​	public abstract void work();
}

抽象类和抽象方法的注意事项

*抽象类不能实例化

*抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类

*可以有构造方法

*抽象类的子类

要么重写抽象类中的所有抽象方法

要么是抽象类

接口

接口就是一个规则,是对行为的抽象

接口的定义和使用

*接口用关键字interface来定义

public interface 接口名{}

*接口不能实例化

*接口和类之间是实现关系,通过implements关键字表示

public class 类名 implements 接口名{}

*接口的子类(实现类)

要么重写接口中的所有抽象方法

要么是抽象类

注意1:接口和类的实现关系,可以单实现,也可以多实现

public class 类名 implements 接口名1,接口名2{}

注意2:实现类还可以在继承一个类的同时实现多个接口

public class 类名 extends 父类 implements 接口名1,接口名2{}

接口中的成员变量

*成员变量

        只能是常量

        默认修饰符:public static final

*没有构造方法

*成员方法

        只能是抽象方法

        默认修饰符:public abstract

接口和类之间的关系

*类和类的关系

        继承关系,只能单继承,不能多继承,但是可以多层继承

*类和接口的关系

        实现关系,可以单继承,也可以多实现,还可以在继承一个类的同时实现多个接口

*接口和接口的关系

        继承关系,可以单继承,也可以多继承

        细节:如果实现类实现了最下面的子接口,那么就需要重写所有的抽象方法

JDK8开始接口中的新增的方法

*JDK7以前:接口中只能定义抽象方法

*JDK8的新特性:接口中可以定义有方法体的方法(默认,静态)

(1)允许在接口中定义默认方法,需要使用关键字default修饰

作用:解决接口升级的问题

(2)接口中默认方法的定义格式:

*格式:public default 返回值类型 方法名(参数列表){ }
*范例:public default void show(){ }

(3)接口中默认方法的注意事项:

*默认

*JDK9的新特性:接口中可以定义私有方法

初始内部类

类的五大成员:属性、方法、构造方法、代码块、内部类

什么是内部类

在一个类的里面,定义一个类

举例:在A类的内部定义B类,B类就被称为内部类
public class Outer
{		//外部类
​	public class Inner
​	{		//内部类

​	}
}
public class Test
{		//外部其他类
​	public static void main(String[ ] args)
​	{

​	}
}

内部类表示的事物是外部类的一部分

内部类单独出现没有任何意义

内部类的访问特点:

*内部类可以直接访问外部类的成员,包括私有

*外部类要访问内部类的成员,必须创建对象

内部类的分类

*成员内部类        *静态内部类        *局部内部类        *匿名内部类

成员内部类

*写在成员位置的,属于外部类的成员

*成员内部类可以被一些修饰符所修饰,比如:private,默认,protected,public,static等

public class Car
{		//外部类
​	String carName;
​	int carAge;
​	int carColor;
​	class Engine
​	{		//成员内部类
​		String engineName;
​		int engineAge;
​	}
}

获取成员内部类对象

方法一:当成员内部类被private修饰时,在外部类中编写方法,对外提供内部类的对象。

方法二:当成员内部类被非私有修饰时,直接创建格式:外部类名.内部类名. 对象名=外部类对象.内部类对象

范例:Outer.Inner oi = new Outer().new Inner();

当外部类成员变量和内部类成员变量重名时

System.out.println(Outer.this.变量名);

可以直接获取到外部类的成员变量

public class Outer
{
​	private int a = 10;
​	class Inner
​	{
​		private int a = 20;
​		public void show()
​		{
​			int a = 30;
​			System.out.println(a);		//30
​			System.out.println(this.a);		//20
​			System.out.println(Outer.this.a);		//10
​		}
​	}
}

静态内部类

静态内部类是一种特殊的成员内部类,静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建对象

public class Car
{		//外部类
​	String carName;
​	int carAge;
​	int carColor;
​	static class Engine
​	{		//静态内部类
​		String engineName;
​		int engineAge;
​	}
}

创建静态内部类对象的格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();

Outer.Inner oi = new Outer.Inner();

调用非静态方法的格式:先创建对象,用对象调用

调用静态方法的格式:外部类名.内部类名.方法名();

public class Outer
{
​	int a = 10;
​	static int b = 20;
​	static class Inner
​	{
​		public void show1()
​		{
​			Outer o = new Outer();
​			System.out.println(o.a);
​			System.out.println(b);
​		}
​		public static void show2()
​		{		//System.out.println("静态的方法被调用了");
​			Outer o = new Outer();
​			System.out.println(o.a);
​			System.out.println(b);
​		}
​	}
}
//只要是静态的东西,都可以用类名点直接获取
public class Test
{
​	public static void mian(String[ ] args)
​	{
​		Outer.Inner oi = new Outer.Inner();
​		oi.show1();
​		Outer.Inner.show2();		//静态方法
​	}
}

局部内部类

1.将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量

2.外界是无法直接使用,需要在方法内部创建对象并使用

3.该类可以直接访问外部类的成员,也可以访问方法内的局部变量

匿名内部类

匿名内部类本质上就是隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置

格式:
new 类名或者接口名()
{
​	重写方法;							//继承\实现,方法重写,创建对象
};

格式细节:包含了继承或实现,方法重写,创建对象。

整体就是一个类的子类对象或者接口的实现类对象

举例:
new Inter(){
​	public void show()
​	{

​	}
};

小拓展:

//整体我们可以理解为Swim接口的实现类对象

//接口多态

Swim s = new Swim()
{
​	public void swim()
​	{
​		System.out.println("重写之后游泳方式");
​	}
};
//编译看左边,运行看右边的原则
s.swim();

new Swim()
{
​	public void swim()
​	{
​		System.out.println("重写之后游泳方式");
​	}
}.swim();

使用场景:当方法参数是接口或者类时,以接口为例,可以传递这个接口的实现类对象,如果实现类只要使用一次,就可以用匿名内部类简化代码

常用API

Math

*是一个帮助我们用于数学计算的工具类

*私有化构造方法,所有的方法都是静态的

Math类的常用方法

方法名说明
public static int                abs(int a)获取参数绝对值
public static double         ceil(double a)向上取整
public static double         floor(double a)向下取整
public static int                round(float a)四舍五入
public static int                max(int a,int b)获取两个int之中的较大值
public static double         pow(double a,double b)返回a的b次幂的值
public static double         random()返回值为double的随机值,范围[0.0,1.0)

时间原点:1970年1月1日 0:0:0,我国在东八区,有8小时时差

1秒 = 1000毫秒

abs    获取参数绝对值
System.out.println(Math.abs(88));     //88
System.out.println(Math.abs(-88));    //88
//bug:以int类型为例,取值范围: -2147483648 ~ 2147483647
//如果没有正数与负数对应,那么传递负数结果有误,-2147483648没有正数与之对应,所以ads结果产生bug
//System.out.println(Math.abs(-2147483648));     //会报错

进一法:望数轴的正方向进一
System.out.println(Math.ceil(12.34));     //13.0
System.out.println(Math.ceil(12.54));     //13.0
System.out.println(Math.ceil(-12.34));     //-12.0
System.out.println(Math.ceil(-12.54));     //-12.0
//向上取整(进一法),向正无穷大方向获取距离最近的整数

去尾法
System.out.println(Math.floor(12.34));     //12.0
System.out.println(Math.floor(12.54));     //12.0
System.out.println(Math.floor(-12.34));     //-13.0
System.out.println(Math.floor(-12.54));     //-13.0
//向下取整(去尾法),向负无穷大方向获取距离最近的整数

//四舍五入
System.out.println(Math.round(12.34));     //12.0
System.out.println(Math.round(12.54));     //13.0
System.out.println(Math.round(-12.34));     //-12.0
System.out.println(Math.round(-12.54));     //-13.0

//获取两个整数的较大值
System.out.println(Math.max(20,30));     //30
//获取两个整数的较小值
System.out.println(Math.min(20,30));     //20
//获取a的b次幂
System.out.println(Math.pow(2,3));     //8
//如果第二参数为0~1之间的小数
System.out.println(Math.pow(4,0.5));     //2

System.out.println(Math.sqrt(4));     //2    返回平方根
System.out.println(Math.cbrt(8));     //2    返回立方根
获取1~100的随机数:
System.out.println(Math.floor(Math.random() * 100) + 1);
//Math.random()    [0.0 1.0)
//* 100            [0.0 100.0)
//floor            去掉了后面的小数
//+1               [1 100.0]

System

System也是一个工具类,提供了一些与系统相关的方法

方法名说明
public static void exit(int status)终止当前运行的Java虚拟机
public static long currentTimeMillis()返回当前系统的时间毫秒值
public static void arraycopy(数组源数组,起始索引,目的地数组,起始索引,拷贝个数)数组拷贝

exit方法的形参:

0:表示当前虚拟机是正常停止

非0:表示当前虚拟机异常停止

System.exit(0);

 返回当前系统的时间毫秒值的方法可以来计算代码运行时间

long start = System.currentTimeMillis();

........运行的代码

long end = System.currentTimeMillis();
//获取程序运行的总时间
System.out.println(end - start);

拷贝数组

int[] arr1 = {1,2,3,4,5,6,7,8,9,10};
int[] arr2 = new int[10];
//把arr1数组中的数据拷贝到arr2中
System.arraycopy(arr1,0,arr2,0,10);

(1)如果数组源数组和目的地数组都是基本数据类型,那么两者的类型必须保持一致,否则会报错

(2)在拷贝的时候需要考虑数组的长度,如果超出范围也会报错

(3)如果数组源和目的地数组都是引用数据类型,那么子类类型可以赋值给父类类型

(3)
Student s1 = new Student("十八号",18);
Student s2 = new Student("十九号",19);
Student s3 = new Student("二十号",20);
Student[] arr1 = {s1,s2,s3};
Person[] arr2 = new Person[3];
//把arr1中对象的地址值赋值给arr2中
System.arraycopy(arr1,0,arr2,0,3);
//遍历数组arr2
for(int i = 0; i < arr2.length; i++)
{
    Student stu = (Student) arr2[i];
    System.out.println(stu.getName() + ", " + stu.getAge());
}

Runtime

Runtime表示当前虚拟机的运行环境

方法名说明
public static Runtime getRuntime()当前系统的运行环境对象
public void exit(int status)停止虚拟机
public int availableProcessors()获得CPU的线程数
public long maxMemory()JVM能从系统中获取总内存大小(单位byte)
public long totalMemory()JVM已经从系统中获取总内存大小(单位byte)
public long freeMemory()JVM剩余内存大小(单位byte)
public Process exec(String command)运行cmd命令
//1.获取Runtime的对象
Runtime r1 = Runtime.getRuntime();

//2.exit 停止虚拟机
Runtime.getRuntime().exit(0);

//3.获取CPU的线程数
System.out.println(Runtime.getRuntime().availableProcessors());

//4.总内存大小,单位byte字节
System.out.println(Runtime.getRuntime().maxMemory() / 1024 / 1024);

//5.已经获取的总内存大小,单位byte字节
System.out.println(Runtime.getRuntime().totalMemory() / 1024 / 1024);

//6.剩余内存大小
System.out.println(Runtime.getRuntime().freeMemory() / 1024 / 1024);

//7.运行cmd命令
Runtime.getRuntime().exec("shutdown -s -t 多少秒关机");
//shutdown:关机    加上参数才能执行
//-s:默认在1分钟之后关机
//-s -t 指定时间:指定关机时间
//-a:取消关机操作
//-r:关机并重启

Object

*Object是Java中的顶级父类,所有的类都直接或间接的继承于Object类

*Object类中的方法可以被所有子类访问,所以我们要学习Object类和其他的方法

方法名说明
public Object()空参构造

在学继承中的类里的任意构造方法有隐藏的super();为什么是默认访问无参构造而不是有参构造?

因为顶级父类中只有无参构造方法

方法名说明
public String toString()返回对象的字符串表示形式
public boolen equals(Object obj)比较两个对象是否相等
protected Object clone(int a)对象克隆

1.toString        返回对象的字符串表示形式

Object obj = new Object();
String str1 = obj.toString();
System.out.println(str1);
//细节
//System:类名
//out:静态变量
//System.out:获取打印的对象
//println():方法
//参数:表示打印的内容
//核心逻辑:当我们打印一个对象的时候,底层会调用对象的toString方法,把对象变成字符串,然后再打印在控制台上,打印完成换行处理

toString方法的结论:

如果我们打印一个对象,想要看到属性值的话,那么就重写toString方法就可以了,再重写的方法中,把对象的属性值进行拼接

2.equals               比较两个对象是否相等

(1)如果没有重写equals方法,那么默认使用Object中的方法进行比较,比较的是地址值是否相等

(2)一般来讲地址值对于我们意义不大,所以我们会重写,重写之后比较的就是对象内部的属性值

String s = "abc";
StringBuilder sb = new StringBuilder("abc");

System.out.println(s.equals(sb));    //false
//因为equals方法是被s调用的,而s是字符串,所以equals要看String类中的
//字符串中的equals方法,先判断参数是否为字符串,如果是字符串,再比较内部属性,如果参数不是字符串,直接返回false

System.out.println(sb.equals(s));    //false
//因为equals方法是被sb调用的,而sb是StringBuilder,所以这里的equals方法要看StringBuilder中的equals方法,那么在StringBuilder当中,没有重写equals方法,使用的是Object中的,在Object当中默认是使用==号比较两个对象的地址值,而这里的s和sb记录的地址值是不一样的,所以结果返回false

Lambda表达式

假设有这样的一个需求:设计一个设计一个方法,能够实现两个数值的加法和减法运算。java中方法不能单独存在,必须定义在类或接口中,考虑到是一个通用方法,可以设计一个数值计算接口,其中定义该通用方法。代码如下:

//可计算接口
public interface Calculable{
    //计算两个int数值
    int calculateInt(int a,int b);
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值