【Java基础概述-3】多态、实例\静态\局部\匿名内部类、Object类、Objects类、Date日期类
目录
1.多态
??????? 众所周知,面向对象的三大特征为封装、继承、多态,多态的概念是:同一类型的对象,在执行同一种行为的时候,在不同状态下表现出不同的行为特征。
????????1.1 多态的形式
????????父类类型 对象名称 = new 子类构造器。
????????接口? 对象名称 = new 实现类构造器。
????????1.2 多态的识别技巧
??????? 对于方法的调用,编译看左边,运行看右边
??????? 对于变量的调用,编译和运行都看左边。
????????1.3 多态的前提
??????? (1)必须存在父类类型的变量引用子类类型的对象。
??????? (2)必须存在继承关系和实现关系。
??????? (3)必须存在方法重写
案例:
public class PolymorphicDemo {
public static void main(String[] args) {
//父类类型>子类类型范围
Animal dlam=new Cat();
dlam.run();
System.out.println(dlam.name);
Animal td=new Dog();
td.run();
System.out.println(dlam.name);
}
}
class Dog extends Animal{
public String name="狗";
@Override
public void run() {
System.out.println("狗跑的块~~");
}
}
class Cat extends Animal{
public String name="猫";
@Override
public void run(){
System.out.println("猫跑的飞快~~");
}
}
class Animal{
public String name="动物";
public void run(){
System.out.println("动物跑!");
}
}
?????????1.4 多态的优略势(面试重点)
??????????????? 优势:1.在多态形式下,右边对象可以实现组件化切换,业务功能也随之改变,便于扩展和维护。实现泪与泪之间的解耦。
????????????????? 2.在实际开发中,父类类型作为方法参数传入,传递给子类对象方法,可以传入一切子类对象进行方法调用,更能体现出多态的扩展性和便利性
??????? ????????缺点:1,多态形式下不能调用子类特有的功能。因为编译看左边,编译不能通过!!!
例子:
public class PolymorphicDemo {
public static void main(String[] args) {
Animal dog = new Dog();
go(dog);
Animal cat = new Cat();
go(cat);
}
//第2条的解释
//开发一个游戏 所有动物都可以进来比赛
public static void go(Animal animal){
System.out.println("开始。。");
animal.run();
System.out.println("结束。。");
}
}
class Dog extends Animal {
public String name="狗";
@Override
public void run() {
System.out.println("狗跑的块~~");
}
}
class Cat extends Animal {
public String name="猫";
@Override
public void run(){
System.out.println("猫跑的飞快~~");
}
}
class Animal{
public String name="动物";
public void run(){
System.out.println("动物跑!");
}
}
????????1.5 多态下的类型转换
??????? 考虑一下在一个场景上,我们可能不需要用多态的形式了,但是之前用的就是多态形式,或者说以前没用多态,但是现在需要利用多态来进行业务代码的实现,应该如何进行类型转换:
??????? 规则:
??????? 1.小范围类型的变量或者值可以直接赋值给大范围类型的变量。
??????? 2.大范围类型的变量或者值必须强制转换给小范围类型的变量。
??????? 注意:
????? 1.? 父类类型的范围>子类类型的范围
、 ? 2.子类类型的变量或者值可以自动转换赋值给父类类型的变量
??????? 3.引用类型的自动转换不能解决多态的劣势。
例1:
public class PolymorphicDemo {
public static void main(String[] args) {
//1.引用类型的自动类型转换;小范围的对象赋值给大范围的对象
Animal cat = new Cat();
//2.引用类型的自动类型转换:小范围的变量赋值给大范围的变量
Cat cat1 = new Cat();
Animal c = cat1;
}
}
class Dog extends Animal {
public String name="狗";
@Override
public void run() {
System.out.println("狗跑的块~~");
}
}
class Cat extends Animal {
public String name="猫";
@Override
public void run(){
System.out.println("猫跑的飞快~~");
}
}
class Animal{
public String name="动物";
public void run(){
System.out.println("动物跑!");
}
}
例2(强制转换):
public class PolymorphicDemo {
public static void main(String[] args) {
Animal dog = new Dog();
dog.run();
//动物类型转换成狗类型
//大范围到小范围。
Dog d = (Dog) dog;
//看下强转能不能解决多态劣势
d.eat();
// Animal cat = new Cat();
Animal cat = new Dog();
System.out.println("----------------------");
/*
*
* Exception in thread "main" java.lang.ClassCastException: _04多态_强制类型转换.Cat cannot be cast to _04多态_强制类型转换.Dog
at _04多态_强制类型转换.PolymorphicDemo.main(PolymorphicDemo.java:30)
* */
//避免下面这种情况可用instance:
if(cat instanceof Cat){
Cat cat1 = (Cat) cat;//这里把一个猫给了一直狗,编译类型不报错,运行阶段报错
cat1.run();
}else{
Dog ddd = (Dog) cat;
ddd.run();
}
}
}
class Dog extends Animal {
public String name="狗";
@Override
public void run() {
System.out.println("狗跑的块~~");
}
public void eat(){
System.out.println("狗在吃东西~~");
}
}
class Cat extends Animal {
public String name="猫";
@Override
public void run(){
System.out.println("猫跑的飞快~~");
}
}
class Animal{
public String name="动物";
public void run(){
System.out.println("动物跑!");
}
}
注意:
??????? 虽然多态有一定的劣势,但是在开发中,它的优势是大于劣势的,在业务开发中,多态使用还是挺多的。
2.内部类
??????? 概念:定义在一个类里面的类称为内部类,它能提高更好的封装性,内部类有更多的权限修饰符,封装性有更多的控制。
??????? 2.1 内部的分类
- ? 静态内部类
- ? 实例内部类。(成员内部类)
- ? 局部内部类
- ? 匿名内部类(重点)
????????2.2 静态内部类
??????? 类有的成分它有,静态内部类属于外部类本身,只会加载一次
??????? 所以它的特点与外部类是完全一样的,只是位置在别人里面而已。
??????? 外部类:宿主
??????? 内部类:寄生
??????? 静态内部类的访问格式:
??????? 外部类名称.内部类名称
??????? 静态内部类创建对象的格式;
??????? 外部类名称.内部类名称 对象名称 = new 外部类名称.内部类名称。
??????? 注意:静态内部类可以访问外部类的静态成员,但是不能访问外部类的实例成员,外部类的静态成员只有一份,可以被共享,实例成员属于对象,直接访问不可以。
public class InnerClass {
public static void main(String[] args) {
Outter.Inner inner = new Outter.Inner();
inner.setName("张三");
inner.setAge(12);
System.out.println(inner.getName());
System.out.println(inner.getAge());
}
}
class Outter{
private static int age1=12;
private String name1;
public static class Inner{
private String name;
private int age;
@Override
public String toString() {
return "Inner{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public void show(){
System.out.println(age1);
// System.out.println(name1);外部的实例成员不能访问,属于对象,都没实例化,如何拿外部的呢???
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
}
??????? 2.3 实例内部类
??????? 无static修饰的内部类称为实例内部类,属于外部类的每一个对象一个,与对象一起加载。
??????? 实例内部类的特点:
??????? --实例内部类中不能定义静态成员。
??????? --可以定义常量。
?????? 创建对象格式:
??????? 外部类名称.内部类名称 对象名称 = new 外部类构造器.内部类构造器
??????? 实例内部类扩展:
??????? 实例内部类中可以访问外部类的静态成员也可以访问实例成员。
public class InnerDemo {
public static void main(String[] args) {
//实例内部类属于外部类对象,实例内部类属于外部类的对象。
Outter.Inner inner = new Outter().new Inner();
inner.setName("李四");
System.out.println(inner);
}
}
class Outter{
private static int age;
private String schoolName;
public class Inner{
private String name;
// public static String schoolName="黑马";
//C:\Users\zlw\Desktop\Java\JavaPlus\Day03Demo\src\_08内部类_实例内部类\InnerDemo.java:29:30
//java: 内部类_08内部类_实例内部类.Outter.Inner中的静态声明非法
// 修饰符 'static' 仅允许在常量变量声明中使用
//这里说明不能存在静态成员
public static final String schoolName = "黑马";
public void show(){
System.out.println(age);
System.out.println(schoolName);
}
@Override
public String toString() {
return "Inner{" +
"name='" + name + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
??????? 2.4 局部内部类 (几乎不用)
??????? 概念:定义在方法中,构造器中,for循环中的内部类就是局部内部类
??????? 特点:
??????????????? -只能定义实例成员,不能定义静态成员
??????????????? -可以定义常量。
?????? 例子:
public class InnerClass {
public static void main(String[] args) {
class A{
public void test(){
System.out.println("这样写涉嫌装逼嫌疑");
}
}
A a=new A();
}
public static void test(){
class Animal{
}
class Cat extends Animal{
}
}
}
??????? 2.5 匿名内部类 (重点)
??????? 概述:没有名字的局部内部类,其实这里可以把它归结为局部内部类,因为方便区分,把有名字的局部内部类我们这里叫做局部内部类。
??????? 格式:
??????? new 类名|接口名|抽象类(形参){
????????//方法重写
????????}
??????? 匿名内部类的特点:
??????? 1.匿名内部类是一种没有名字的局部内部类。
??????? 2.匿名内部类一旦写出来,就立即创建一个匿名内部类的对象返回。
??????? 3.匿名内部类的对象的类型相当于当前new 那个类型的子类类型。
????????
public class Annoymity {
public static void main(String[] args) {
Animal a = new Animal() {
@Override
public void run() {
System.out.println("猫跑得快");
}
};
a.run();
a.go();
}
}
abstract class Animal{
public abstract void run();
public void go(){
System.out.println("开始go");
}
}
???????? 匿名内部类使用场景多数在于安卓开发,C/S开发,例如:
package _12匿名内部类使用场景;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/*
*
*
*
*
* */
public class Demo {
public static void main(String[] args) {
JFrame win =new JFrame("登录界面");
win.setSize(400,300);
win.setLocationRelativeTo(null);
JButton btn = new JButton("开始登录");
JPanel panel = new JPanel();
panel.add(btn);
win.add(panel);
win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// btn.addActionListener(new ActionListener() {
// @Override
// public void actionPerformed(ActionEvent e) {
// System.out.println("点了按钮");
// }
// });
btn.addActionListener(s -> System.out.println("用户触发了登录"));
win.setVisible(true);
}
}
?
3.Object类
??????? 众所周知,任何类的祖宗类都是Object,Object中常用的两个方法:
??????? 1.public String toString():
??????? -默认返回当前对象所在堆内存信息
??????? -在我们进行输出的时候,实质上也是调用了toString()方法。
??????? -在开发中,我们输出变量的意义是为了看数据,所以父类中的toString()方法存在的意义就是被子类重写,以便输出对象内容信息!!!
??????? 例如:
public class Student {
private String name;
private int age;
private char sex;
public Student() {
}
public Student(String name, int age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
//重写了toString()方法
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}
}
public class ObjectToStringDemo {
public static void main(String[] args) {
Student student = new Student("张三",19,'男');
student.toString();
//直接调用toString方法返回的是对象在内存中的地址
System.out.println(student);
//直接输出对象名称,默认调用toString,所以tostring调用可以不写啊
}
}
???????? 2.equal方法:
??????? public boolean equals():
??????? -默认是比较两个对象的地址是否相同,相同返回true,反之。
??????? -直接比较l两个对象的地址是否相同,完全可以用"=="代替。
??????? 所以equals存在的意义也是为了被子类继承,以便程序员可以定义自己的比较规则 、
????????
public class Student {
private String name;
private int age;
private char sex;
public Student() {
}
public Student(String name, int age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof Student){
Student stu =(Student) obj;
if(this.name == stu.getName() &&
this.age == stu.getAge() &&
this.sex == stu.getSex()
)return true;
else{
return false;
}
}
return false;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}
}
public class ObjectEqualDemo {
public static void main(String[] args) {
Student student = new Student("张三",19,'男');
Student student1 = new Student("张三",19,'男');
System.out.println(student.equals(student1));
System.out.println(student == student1);
}
}
4.Objects类
??????? Objects类和Object之间还是继承的关系,也有equals方法,下图看出,其实还是调用了Object的equal 方法在底层,但是了,这里进行了空指针判断,如果为空,那么就直接是false,这也说明了比Object类更安全。
Objects常用的两个方法,isNULL不是特别重要。: 1.public static boolean equals(){ --比较两个对象的地址 --底层进行非空判断,从而避免空指针异常,更安全 } 2.public static boolean isNuLL(Object obj){ 询问obj是否是null }
public class Demo {
public static void main(String[] args) {
Student student = null;
Student student1 = new Student();
System.out.println(Objects.equals(student1,student));//正常,更安全,推荐使用
// System.out.println(student.equals(student1));//会报空指针异常
System.out.println(Objects.isNull(student));
}
}
5.Date日期类
??????? Java是面向对象语言,会用一个类代表一个事务。
??????? Date类在Java中代表的是系统当前时刻时间对象。
??????? 包:java.util.Date
??????? 构造器(这里只说没有被淘汰的):
??????? -public Date();
??????? -public Date(long time):这里的long time是时间毫秒值,
?????? 方法:
??????? public long getTime():获取时间毫秒值。
看懂以下代码即可:
代码1:
public static void main(String[] args) {
//创建一个日期对象代表系统目前此刻信息
Date date = new Date();
System.out.println(date);
//
System.out.println(date.getTime());
}
代码2(代码性能分析):
public static void main(String[] args) {
long time1 = new Date().getTime();
for(int i=1;i<1000000;i++){
System.out.println(i);
}
long time2 = new Date().getTime();
System.out.println((double) (time2-time1)/1000+"s");
}
代码三(有参构造器的使用):
public static void main(String[] args) {
//问121s以后的时间是多少
Date date = new Date();
long l = date.getTime() + 121 * 1000;
Date date1 = new Date(l);
System.out.println(date1);
}
?
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!