JAVA语言编程(五):多态、final、内部类、Object类、日期时间类、System类、StringBuilder类
1. 多态:
1.1 多态的格式和使用:
父类引用指向子类对象:父类名称 对象名 = new 子类名称()
或者接口名称 对象名 = new 实现类名称()
1.2 多态中成员变量的使用:
Animal.java
package lch;
public abstract class Animal {
Animal(){
System.out.println("Animal构造函数");
}
public abstract void eat();
public String name = "animal";
}
Cat.java
package lch;
public class Cat extends Animal{
Cat(){
System.out.println("Cat构造函数");
}
public void eat(){
System.out.println("吃鱼");
}
public String name = "cat";
}
fangfa.java
package lch;
public class fangfa {
public static void main(String[] args){
//左边是Animal则用Animal的,是Cat则用Cat的:
Animal c1 = new Cat();
Cat c2 = new Cat();
System.out.println(c1.name); //animal
System.out.println(c2.name); //cat
}
}
1.3 多态中成员方法的使用:
编译看左边,运行看右边。
c++中的概念和java中的概念的对照如下:
虚函数 -------- 普通函数
纯虚函数 ------抽象函数
抽象类 -------- 抽象类
虚基类 -------- 接口
1.4 对象的向上转型:
就是多态写法:父类名称 对象名 = new 子类名称();
含义:创建一个子类对象,当做父类来看待使用。
向上转型一定是安全的。
1.5 对象的向下转型:
对象一旦向上转型就不能再使用子类特有的内容了。
向下转型是一个还原动作:子类名称 对象名 = (子类名称) 父类对象;
将父类对象还原为本来的子类对象。
1.6 类型判断:
使用对象名 instanceof 类名
进行判断。
package lch;
public class fangfa {
public static void main(String[] args){
Animal c1 = new Cat();
Cat c2 = new Cat();
Cat c3 = (Cat) c1;
System.out.println(c1 instanceof Cat);
System.out.println(c2 instanceof Cat);
System.out.println(c3 instanceof Cat);
}
}
2. final关键字:
2.1 final基本用法:
可以修饰类,方法,局部变量,成员变量。
对于类和方法,abstract和final不能同时使用。
2.2 修饰类:
格式:public final class 类名{}
被修饰的类不能有任何子类。
2.3 修饰方法:
修饰方法时,该方法将不能被覆盖重写。
2.4 修饰局部变量:
使该局部变量不能修改值。
但对于引用数据类型,可以间接更改其中的值。
2.5 修饰成员变量:
使该成员变量不可改变。
使用final就必须手动赋值。
对于final的成员变量,要么直接赋值,要么通过构造方法赋值。
3. 四种权限修饰符:
public protected (default) private
同一个类 yes yes yes yes
同一个包 yes yes yes no
不同包子类 yes yes no no
不同包非子类 yes no no no
外部类:public/default
成员内部类:public/protected/default/private
局部内部类:什么都不能写
4. 内部类:
一个类的内部包含另一个类。分为成员内部类和成员内部类。
4.1 成员内部类:
定义:
package lch;
public class Animal {
public void beatbeat(){
Heart h1 = new Heart();
h1.beat();
}
public class Heart{
public void beat(){
System.out.println("心脏跳动");
}
}
}
使用:
package lch;
public class fangfa {
public static void main(String[] args){
//方法1:
Animal c1 = new Cat();
c1.beatbeat();
//方法2:
Animal.Heart h1 = new Animal().new Heart();
h1.beat();
}
}
4.2 内部类的同名变量访问:
package lch;
public class Animal {
int n = 10;
public class Heart{
int n = 20;
public void beat(){
int n = 30;
System.out.println("心脏跳动");
System.out.println(n); //30
System.out.println(this.n); //20
System.out.println(Animal.this.n); //10
}
}
}
4.3 局部内部类:
package lch;
public class Animal {
public void methodout(){
class Heart{
int num = 10;
public void methodin(){
System.out.println(num);
}
}
Heart h1 = new Heart();
h1.methodin();
}
}
package lch;
public class fangfa {
public static void main(String[] args){
Animal c1 = new Cat();
c1.methodout();
}
}
4.4 局部内部类的final问题:
局部内部类如果想要访问所在方法的局部变量,那么这个局部变量必须是有效final的。
Java8+之后可以省略final。
原因:
new出来的对象在堆内存中,方法的局部变量在栈内存中。方法运行完后局部变量立即消失,但该对象持续存在。所以必须保证该局部变量不变,留给对象的数据才正确。
4.5 匿名内部类:
如果接口的实现类只需要使用1次,则可以使用匿名内部类。
package lch;
public class fangfa {
public static void main(String[] args){
MyInterfaceAbstract obj1 = new MyInterfaceAbstract()
{
@Override
public void method() {
System.out.println("匿名内部类实现的method");
}
};
obj1.method();
}
}
4.6 匿名对象:
package lch;
public class fangfa {
public static void main(String[] args){
new MyInterfaceAbstract(){
@Override
public void method() {
System.out.println("匿名内部类实现的method");
}
}.method();
}
}
5. Object类:
Object类是Java中所有类的父类。
5.1 toString方法:
直接打印对象的名字,其实就是调用对象的toString方法。这样没有意义,所以需要重写toString方法。
package lch;
public class Animal {
Animal(){}
Animal(String name, int age){
this.age = age;
this.name = name;
}
private String name;
private int age;
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
5.2 equals方法:
默认比较的是两个对象的地址值。所以需要重写equals方法。
package lch;
import java.util.Objects;
public class Animal {
Animal(){}
Animal(String name, int age){
this.age = age;
this.name = name;
}
private String name;
private int age;
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Animal animal = (Animal) o;
return age == animal.age &&
Objects.equals(name, animal.name);
}
}
5.3 Objects类的equals方法:
防止空指针异常。
package lch;
import java.util.Objects;
public class fangfa {
public static void main(String[] args){
String str1 = "qsq";
String str2 = "qsq";
String str3 = null;
System.out.println(str1==str3);
//System.out.println(str3.equals(str1)); //空指针异常
System.out.println(Objects.equals(str1, str3));
}
}
6. 日期时间类:
6.1 Date类:
表示特定的瞬间,精确到毫秒。
package lch;
import java.util.Date;
import java.util.Objects;
public class fangfa {
public static void main(String[] args){
Date d1 = new Date();
System.out.println(d1);
System.out.println(System.currentTimeMillis());
}
}
6.2 Date类的构造方法和成员方法:
package lch;
import java.util.Date;
public class fangfa {
public static void main(String[] args){
Date d1 = new Date();
System.out.println(d1);
Date d2 = new Date(32112134123234l);
System.out.println(d2);
System.out.println(d2.getTime());
}
}
6.3 DateFormat类:
DateFormat类是日期/时间格式化子类的抽象类,不能直接使用,可以创建其子类SimpleDateFormat使用。
format方法和parse方法:
package lch;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class fangfa {
public static void main(String[] args) throws ParseException {
//y年,M月,d日,H时,m分,s秒
SimpleDateFormat s1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d1 = new Date();
System.out.println(d1);
System.out.println(s1.format(d1));
Date d2 = s1.parse("2020-07-16 09:43:11");
System.out.println(d2);
}
}
6.4 Calendar类:
抽象类,无法直接创建对象使用。提供了很多操作日历字段的方法。
使用静态方法getInstance()
创建。
7. System类:
7.1 currentTimeMillis方法:
package lch;
public class fangfa {
public static void main(String[] args){
long t1 = System.currentTimeMillis();
for(int i=0;i<1000000;i++){
System.out.println(i);
}
System.out.println(System.currentTimeMillis()-t1);
}
}
7.2 arraycopy方法:
package lch;
import java.util.Arrays;
public class fangfa {
public static void main(String[] args){
int[] src = {1,2,3,4,5};
int[] dst = {6,7,8,9,10};
System.out.println(Arrays.toString(src));
System.out.println(Arrays.toString(dst));
System.arraycopy(src, 0, dst, 0, 3);
System.out.println(Arrays.toString(src));
System.out.println(Arrays.toString(dst));
}
}
8. StringBuilder类:
字符串缓冲器,可以提高字符串的操作效率。底层也是一个数组,但是没有被final修饰。
StringBuilder在内存中始终是一个数组,占用空间少,效率高,如果超出了StringBuilder的容量,会自动扩容。
8.1 StringBuilder的构造方法和append方法:
append返回的也是StringBuilder,而且返回的就是原来的对象,所以可以链式编程。
package lch;
public class fangfa {
public static void main(String[] args){
StringBuilder s1 = new StringBuilder("qsw");
System.out.println(s1);
StringBuilder s2 = new StringBuilder();
StringBuilder s3 = s2.append("qsw");
System.out.println(s2);
System.out.println(s1==s2);
System.out.println(s2==s3);
//链式编程:
s3.append(123).append(1231).append(32413);
System.out.println(s3);
}
}
8.2 toString方法:
将StringBuilder转换成String。
package lch;
public class fangfa {
public static void main(String[] args){
StringBuilder s1 = new StringBuilder("qsw");
System.out.println(s1);
String s2 = s1.toString();
System.out.println(s2);
}
}