一、类和对象
- 所有的Java程序的基本组成单元就是class
- 类是概念,是模板,是图纸,是新的自己定义的引用数据类型;
除了八种基本数据类型外都是引用数据类型。 - 类的作用:用来定义属性和行为;定义好了之后可以用来产生对象。
- 类中有什么属性和行为,你的对象中就有什么属性和行为,成员变量和成员方法只能由对象调用。
- 类与对象的关系:类是对象的模板,对象是类的具体的存在。
形参:在方法定义的时候叫做形参;
实参:在方法调用的时候传入的叫做实参。
//定义一个类
public class Dog {
定义属性:public 数据类型 属性名称;
定义方法:public void 方法名称(数据类型 参数名称){
方法体;
}
}
public class DogTest{
public static void main(String[] args){
Dog dog = new Dog();//实例化对象然后赋值给dog变量
通过dog.属性名 = 属性值;
dog.方法名();
//如果方法有形参就必须在调用的时候传入实参
}
}
二、内存分析
- 栈(stack):是jvm中执行方法的区域,方法执行和局部变量。
特点:后进先出,连续的内存区域,存取速度快;在jvm中占的空间比较小。 - 堆(heap):凡是new出来的东西都在堆里放着;也叫GC堆,因为垃圾回收机制主要管理的是堆空间。
特点:不连续,可以最大化的利用空间,但是存取速度慢;在jvm中占的空间比较大。 - 方法区域(method area):主要用来存放类文件,静态域,字符串常量池;类文件只会被加载一次。
三、访问修饰符
访问修饰符 | 范围 |
---|---|
public(公有的) | 任意类中 |
protected(受保护的) | 同一个包中,或者子类中 |
default(默认的) | 在同一个包中的不同类中访问 |
private(私有的) | 只能在本类中访问 |
四、构造方法
- 概念:构造对象的方法(记住所有产生的对象都是通过调用构造方法实现的)。
- 作用:用来创建对象使用的。
如果一个类中没有写构造方法的话,则编译器会默认给你一个构造方法,这个就是默认的无参构造方法;
如果你一旦写了一个以上的构造方法的话,则默认无参的构造方法就没有了。 - 总结:
①一般使用public修饰,除非你使用单例模式。
②没有返回值类型,不能写void。
③方法名字必须跟类名一模一样。
④真正定义类:属性私有化;提供getter setter 方法;无参构造方法;全参构造方法。
一个类中一般会有两个构造方法:一个是无参数构造方法,一个是有参数构造方法;快捷键(ALT+INS)
五、String类
字符串常用方法:
equals(): string.equals("字符串") 比较内容是否相等
equalsIgnoreCase():忽略大小写进行比较
toUpperCase():转换大写
toLowerCase():转换小写
concat():在字符串1后面拼接字符串2
startsWith():判断字符串1是否以字符串2开头
endsWith():判断字符串1是否以字符串2结尾
indexOf():查找一个子字符串在原始字符串第一次出现的索引
lastIndexOf():查找一个子字符串在原始字符串最后一次次出现的索引
replace(old,new):在原始字符串中将旧的替换成新的
substring(beginIndex):从开始索引截取
substring( beginIndex,endIndex):从开始索引截取,截取到指定的索引
trim(): 清除字符串前后两端的空格(要是想去除所有空格用replace替换""替换"")
length(): 获取字符串的长度
split():拆分字符串得到字符串数组
String.valueOf():转换成String类型
charAt():返回指定索引处char值
contains():判断是否包含某个子字符串
六、static关键字
- 被static修饰的变量叫静态变量(这个变量只在类被加载时初始化一次)。
- 被static修饰的方法叫静态方法。
①在实例方法中可以调用成员方法,成员变量,静态方法,静态变量。
②在静态方法中只能调用静态方法和静态变量。如果非要调用成员方法和成员变量,需要new对象,通过对象去调用。 - 被static修饰的代码块叫静态代码块。
①静态代码块:类代码加载的时候产生,只产生一次,要优先于构造方法执行。
②构造代码块:在创建对象前被调用,在构造方法执行前先调用构造代码块。 - 静态调用 :类名.方法名/属性名
非静态调用 :对象.方法名/属性名
七、时间类
- date类
//获取一个日期对象
Date date = new Date();
//获取一个国际化的日期格式
System.out.println(date);
//获取时间毫秒
System.out.println(date.getTime()));
- SimpleDateFormat类
//转化时间格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//format可以把Date类型转为指定格式的字符串
String date1 = sdf.format(Date date);
//parse方法可以把指定的格式转为Date类型
Date date2 = sdf.parse(String date);
案例:计算你出生了多少天?
public static void main(String[] args) throws ParseException {
Scanner sc = new Scanner(System.in);
long time = System.currentTimeMillis();//获取当前时间的毫秒
//获取出生的时间毫秒
//输入出生的年月日
//然后转化Date 类型,然后换算成毫秒
System.out.println("请输入出生的年月日,以,分割");
String mybirth = sc.next();
String[] birs = mybirth.split(",");
int year = Integer.valueOf(birs[0]);
int month = Integer.valueOf(birs[1]);
int date = Integer.valueOf(birs[2]);
//1999-10-10
String strbirth = year+"-"+month+"-"+date;
//把字符串转为Date类型
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//原字符串和指定
//格式要吻合
Date datebirth = sdf.parse(strbirth);
long bir = datebirth.getTime();//拿到生日的毫秒
long cha = time-bir;//当前时间的毫秒与生日的毫秒相减
System.out.println(cha/1000/60/60/24);
}
- jdk1.8之后的新增时间相关类
LocalDateTime:代表日期时间,通常被视为年月日时分秒,精确到纳秒
LocalDate:表示日期,通常被视为年月日
LocalTime:代表一个时间,通常被看作是小时 - 秒。 时间表示为纳秒精度
DateTimeFormatter:格式化日期对象
Duration:类以秒和纳秒为单位建立数量或时间量
Period:以年,月和日为单位建立数量或时间量
public static void main(String[] args) {
//获取到当前时间的年月日
LocalDate now = LocalDate.now();
//System.out.println(now);
//获取到当前的年月日时分秒
LocalDateTime now1 = LocalDateTime.now();
//System.out.println(now1);
//获取到当前的时分秒
LocalTime now2 = LocalTime.now();
//System.out.println(now2);
//使用DateTimeFormatter 将日期转化成字符串类型
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String format = now.format(dateTimeFormatter);
System.out.println(format);
//使用DateTimeFormatter 将字符串类型转化成Date类型
String str = "2020/12/12";
DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy/MM/dd");
LocalDate parse = LocalDate.parse(str,dateTimeFormatter1);
System.out.println(parse);
}
}
- Calendar类
获取时间:
// 使用默认时区和语言环境获得一个日历
Calendar cal = Calendar.getInstance();
// 赋值时年月日时分秒常用的6个值,注意月份下标从0开始,所以取月份要+1
System.out.println("年:" + cal.get(Calendar.YEAR));
System.out.println("月:" + (cal.get(Calendar.MONTH) + 1));
System.out.println("日:" + cal.get(Calendar.DAY_OF_MONTH));
System.out.println("时:" + cal.get(Calendar.HOUR_OF_DAY));
System.out.println("分:" + cal.get(Calendar.MINUTE));
System.out.println("秒:" + cal.get(Calendar.SECOND));
设置时间:
Calendar cal = Calendar.getInstance();
// 如果想设置为某个日期,可以一次设置年月日时分秒,由于月份下标从0开始赋值月份要-1
// cal.set(year, month, date, hourOfDay, minute, second);
cal.set(2018, 1, 15, 23, 59, 59);
// 或者6个字段分别进行设置,由于月份下标从0开始赋值月份要-1
cal.set(Calendar.YEAR, 2018);
cal.set(Calendar.MONTH, Calendar.FEBRUARY);
cal.set(Calendar.DAY_OF_MONTH, 15);
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
System.out.println(cal.getTime());
Calendar与Date相互转换:
Date d = c.getTime();
c.setTime(d);
八、包装类
- 作用:Java中的基本数据类型没有方法和属性,而包装类就是为了让这些拥有方法和属性,实现对象化交互。
- 8种基本数据类型都有各自的包装类,其对应关系为:
基本类 | 包装类 |
---|---|
byte | Byte |
short | Short |
char | Integer |
int | Byte |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
-
基本数据和包装类之间的转换
装箱:把基本数据类型转为包装类
拆箱:把包装类转化为基本数据类型
自动装箱:在它自己对应的基本类型可以实现自动装箱 -
数据类型的转换
整型转换成为字符串型:
String s1 = i + ""; //第一种方法
String s2 = Integer.toString(i); //第二种方法
String s3 = String.valueOf(i); //第三种方法
字符串型转换成为整型:
int i1 = Integer.valueOf(s); //第一种方法
int i2 = Integer.parseInt(s); //第二种方法
九、面向对象的特征之一:封装性
- 封装的概念:
广义来说:一切共同代码的抽取都可以叫封装。一般体现在公共方法的封装,工具类。
狭义来说:隐藏对象的属性和实现细节。
①将属性私有化,使用private关键字修饰。
②为使用private关键字修饰的属性添加get和set方法。通过get和set方法来操作属性。 - 封装的作用:
①提高了程序的可复用性和可维护性。
②将公共数据和私有数据分离开,保护了私有数据。
③降低程序复杂性、提高可控性。
十、面向对象的特征之二:继承性
-
继承的概念:
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的属性和方法,或子类从父类继承方法,使得子类具有父类相同的行为;
子类可以直接访问父类中的非私有的属性和行为;
通过 extends 关键字让类与类之间产生继承关系。 -
继承的语法格式:
[权限修饰符] class 子类名 extends 父类名{}
-
继承的好处:
①减少了代码的冗余,提高了代码的复用性。
②便于功能的扩展。
③为之后多态的使用,提供了前提。 -
Java中继承性的说明:
①一个类可以被多个类继承。
②类的单继承性:一个类只能有一个父类(单继承,多级实现—>)。
③子父类是相对的概念.子类 直接继承的父类,称为:直接父类;
间接继承的父类,称为:间接父类。
④子类继承了父类以后,就获取了直接父类以及间接父类的中声明的属性和方法。 -
方法重写@override
1、重写(override):发生在父子类中,子类继承父类的方法,方法名相同,参数也相同,但是实现方法体不同。
重载(overload):发生在同一个类中,方法名相同,参数列表不同,不考虑返回值。
2、重写的注意事项:
①必须保证父子类中重写的方法,方法名相同,参数列表相同。
②子类方法的返回值小于或等于父类方法的返回值范围。
③子类抛出的异常小于或等于父类的。
③子类方法的权限必须要大于等于父类方法的权限。 -
super关键字:
1、如果子类既想使用自己的方法,又想使用父类的成员变量和成员方法,需要通过super关键字。
2、super关键字的用法
①在子类的成员方法中访问父类的成员变量和成员方法。
②在子类的构造方法中访问父类的构造方法。
3、使用场景
①当子父类出现同名成员时,可以用super进行区分。
②子类要调用父类构造函数时,可以使用super语句。 -
继承中构造方法的特点(父子类):
①构造方法不能被继承(构造方法是一个类独有的方法)。
②创建子类对象一定是先调用父类构造,再调用子类构造。(并且只有子类构造才能调用父类构造)。
③子类构造可以通过super关键字调用父类有参构造 无参super() 有参super(参数列表) 。
④super父类构造调用,必须是子类构造中的第一行语句(并且一个子类构造,只能调用一次super())。 -
final关键字
1、解释:final代表最终的,不可改变的。
2、final的三种用法:
①可以用来修饰类,final修饰的类不能被继承,也就意味着这个类其中的方法不能被重写。
②可以用来修饰方法,final关键字修饰的方法不能被覆盖重写。表示一个最终的方法。
③可以用来修饰局部变量,final修饰成员变量、常量,命 名必须全大写,一般多个单词使用下划线连接,如:D_AGE,CAT_AGE
- 基本数据类型:使用final修饰的基本数据类型值不能变,并且只能被赋值一次。
- 引用数据类型:使用final修饰的引用类型,引用的地址值不能改变,但是值可以改变。
3、final的赋值方式:
①对于成员变量来说,使用final修饰照样是不可变的,但是因为成员变量有默认值,所以必须手动赋值。
②对final修饰的成员变量来说,可以直接赋值,也可以通过构造方法赋值,但是必须二选一。
③如果要通过构造方法赋值,并且类中有多个构造方法,必须保证每一个构造方法都要对final修饰的成员变量赋值。 -
Object类
1、Object是所有类的父类,任何类都默认继承Object。
2、理论上Object类是所有类的父类,即直接或间接的继承java.lang.Object类。由于所有的类都继承在Object类,因此省略了extends Object关键字。该类中主要有以下方法: toString(),getClass(),equals(),clone(),finalize(), 其中toString(),getClass(),equals()是其中最重要的方法。
3、注意:
Object类中的getClass(),notify(),notifyAll(),wait()等方法被定义为final类型,因此不能重写。
equals()方法 在比较字符串时 比较的是俩个字符串的值。但是实际上equals方法比较的是地址值。
十一、面向对象的特征之三:多态性
- 理解多态性:可以理解为一个事物的多种形态。
- 何为多态性:父类的引用指向子类的对象。
- 多态性的使用前提:①类的继承关系 ②方法的重写
- 多态的使用:
有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写的方法。
①向上转型时,父类引用指向子类对象,编译看左(父类),执行看右(子类)(多态的本质就是向上转型)。
②向下转型时,把父类引用强制转换为子类引用,编译执行都看左(父类)。
③静态方法,编译执行都看左(父类) (静态和类相关,算不上重写,所以,访问还是左边的)。 - 多态的弊端:父类引用不能调用子类独有的属性和方法。
十二、Java的特性之四:抽象类
-
概述:道理上本身不能new出来的,本身就是一个抽象的概念,把这个类定义为抽象类;关键字:abstract;包含抽象方法的类必定是抽象类。
-
抽象方法:用abstract 关键字声明抽象方法,抽象方法只包含一个方法名,而没有方法体。
-
抽象类的使用:如果父类有抽象方法,子类必须重写该抽象方法,如果不想重写自己就变成抽象类。
-
总结:
①抽象类不能实例化。
②抽象类其他使用跟普通类一样,可以有成员变量,构造方法。
③有抽象方法必定是抽象类;抽象类中可以没有抽象方法。
④子类必须重写父类的抽象方法,如果不想重写的话,则必须把自己变成抽象类。
十三、Java的特性之五:接口
-
接口的概述:
接口是抽象方法和常量值的集合。从本质上讲,接口是一种特殊的抽象类,这种抽象类只包含常量和方法的定义,而没有变量和方法的实现。 -
接口的格式:
interface 接口名{}
-
接口的特点:
①接口不能被实例化
②一个类如果实现了接口,要么是抽象类,要么实现接口中的所有方法 -
接口的成员特点:
①成员常量关键字:
public static final(public static final 都可以省略);
常量名字要大写,多个单词使用下划线进行拼接;
调用的时候要使用接口名称.常量。
②抽象方法关键字:
public abstract (public abstract都可以省略),接口里定义的方法是抽象的,(jdk1.8版本后可以有默认方法) -
接口的思想特点:
①接口是对外暴露的规则。
②接口是程序的功能扩展。
③接口的出现降低耦合性(实现了模块化开发,定义好规则,每个人实现自己的模块,大大提高了开发效率)。
④接口可以用来多实现。
⑤多个无关的类可以实现同一个接口。
⑥一个类可以实现多个相互直接没有关系的接口。
⑦与继承关系类似,接口与实现类之间存在多态性。 -
接口和抽象类的区别:
①抽象类可以有构造方法,接口中不能有构造方法。
②抽象类中可以有普通成员变量,接口中没有普通成员变量。
③抽象类中可以包含静态方法,接口中不能包含静态方法。
④一个类可以实现多个接口,但只能继承一个抽象类。
⑤接口可以被多重实现,抽象类只能被单一继承。
⑥如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法。 -
继承和实现的区别:
①类与类之间称为继承关系:因为该类无论是抽象的还是非抽象的,它的内部都可以定义非抽象方法,这个方法可以直接被子类使用,子类继承即可。只能单继承,可以多层继承。
②类与接口之间是实现关系:因为接口中的方法都是抽象的,必须由子类实现才可以实例化。可以单实现,也可以多实现;还可以在继承一个类的同时实现多个接口((class) extends (class) implements (interface1,interface2…))。
③接口与接口之间是继承关系:一个接口可以继承另一个接口,并添加新的属性和抽象方法,并且接口可以多继承((interface) extends (interface1,interface2…))。