C语言相信大家应该都不陌生,它是一门面向过程的语言,关注的是过程,通过分析求解问题的过程,再通过函数逐步调用,最后解决问题。
而Java是基于面向对象的,关注的是对象,将一件事拆分为多个对象,通过对象之间的交互解决问题。
所以在用面向对象的思想去解决问题时就可以分为:找对象,建对象,用对象,并维护对象之间的关系。
类就是一类对象的统称。对象就是这一类具体化的一个实例。
举个例子:盖房子的时候我们会有设计图纸,设计图纸就是一个类,而通过这个图纸我们就可以盖出房子,那么在这个例子当中,类就是那个图纸,而房子就是那个对象,所以房子就是一个实体。一个图纸可以实例化无数个对象(当然,正常情况下一个图纸建一个房子就好了,家里有矿的无所谓,你可以认为是在建别墅群)。
总的来说:类相当于一个模板,对象是由模板产生的样本。一个类,可以产生无数的对象。
声明一个类就是创建一个新的数据类型,而类在 Java 中属于引用类型, Java 使用关键字 class 来声明类。在一个类中有属性和方法,实例化通过new 关键字就可以创建一个对象,使用 .
来访问对象中的属性和方法。
static关键字的作用
1.修饰属性
静态属性和类相关,和对象无关。就是说一个用static修饰的属性,它只是依赖于当前类,只能通过
类名 . 属性
访问可以改变属性值。通过当前类实例化后产生的对象无法访问,所以和对象无关。
class TestDemo{
public int a;
public static int count;
}
public class Java20210531 {
public static void main(String[] args) {
TestDemo s1 = new TestDemo();
s1.a++;
TestDemo.count++;
System.out.println(s1.a); //1
System.out.println(TestDemo.count); //1
System.out.println("============");
TestDemo s2 = new TestDemo();
s2.a++;
TestDemo.count++;
System.out.println(s2.a); //1
System.out.println(TestDemo.count); //2
}
}
2.修饰方法
如果在任何方法上应用 static 关键字,此方法称为静态方法
1.一样的,静态方法属于类,而不属于类的对象。
2.可以直接调用静态方法,而无需创建类的实例(对象)。
3.静态方法可以访问静态数据成员,并可以更改静态数据成员的值
class TestDemo{
public int a ;
public static int count;
public static void change() {
count = 20;
//a = 10; error 不可以访问非静态数据成员
}
}
public class Java20210531 {
public static void main(String[] args) {
TestDemo.change();//无需创建实例对象 就可以调用
System.out.println(TestDemo.count); //20
}
}
注意事项: 静态方法和对象无关, 而是和类相关
. 因此这导致了两个情况(重点,选择题易错):
软件开发本就是一个复杂的过程,如果代码程度复杂都过高,就不好维护,所以就引入一种管理代码的方式——封装。
在写代码的时候会涉及到两种角色:类的实现者和类的调用者
Java 中对于字段和方法共有四种访问权限 。
权限大小:private < default < protected < public
当我们使用 private 来修饰字段的时候, 就无法直接使用这个字段了.
此时如果需要获取或者修改这个 private 属性, 就需要使用 getter / setter 方法
class Person {
private String name;//实例成员变量
private int age;
public void setName(String name){
//name = name;//不能这样写
this.name = name;//this引用,表示调用该方法的对象
}
public String getName(){
return name;
}
public void show(){
System.out.println("name: "+name+" age: "+age);
}
}
public static void main(String[] args) {
Person person = new Person();
person.setName("tao");
String name = person.getName();
System.out.println(name);
person.show();
// 运行结果
//tao
//name: tao age: 0
}
注意事项
在创建类的过程本身就是为了抽象现实中的一些事物(包含属性和方法),有时候现实中的事物会有一些特定的关系,比如实现三个类,Animal类,cat类,dog类,我们会发现cat类和dog类都同属于Animal类,这种关系称之为继承 ,is a
表示关系
继承:使用extends关键字 ,A extends B
A:表示子类,派生类
B:表示父类,超类,基类
注意事项
另外final关键字的功能是限制类被继承,如下:
面试问题:this和super的区别?
1.this表示当前对象的引用 ————————super表示父类对象的引用
2.this():调用当前对象的构造方法 ———— super():显示调用父类的构造方法(必须都放在第一行)
3.this.data:调用当前对象的属性 —————super.data:调用父类对象的成员属性
4.this.fun():调用当前对象的方法 ————— super.fun() :调用父类对象的方法
在了解多态之前,我们需要先了解这几个概念:向上转型、方法重写、动态绑定。
例如:
Animal cat= new Cat("小花");
在上面的代码中,我知道Cat是子类,Animal是父类,而子类继承了父类,cat就是一个被实例化出来的对象,也可以称之为是父类(Animal)的引用。
所以这行代码的意思:
此时 cat 是一个父类 (Animal) 的引用, 指向一个子类 (Bird) 的实例(产生的对象). 这种写法称为 向上转型
class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public void eat(String food) {
System.out.println("我是一只小动物");
System.out.println(this.name + "正在吃" + food);
}
}
// Bird.java
class Bird extends Animal {
public Bird(String name) {
super(name);
}
public void eat(String food) {
System.out.println("我是一只小鸟");
System.out.println(this.name + "正在吃" + food);
}
public void fly1() {
System.out.println("飞");
}
}
// Test.java
class Test {
public static void main(String[] args) {
Animal animal1 = new Animal("圆圆");
animal1.eat("谷子");
Animal animal2 = new Bird("扁扁");
animal2.eat("谷子");
}
}
向上转型在Java中非常的常见,但这里需要注意的通过实例化产生的对象只能访问父类的方法和属性(子类的方法可能大于父类的方法数量)
子类实现父类的同名方法, 并且参数的类型和个数完全相同, 这种情况称为 覆写/重写/覆盖(Override)
注意事项
重载和重写的区别?(面试问题)
重载要求方法名相同,参数类型和个数不同,返回值不做要求
重写要求方法名相同,参数类型和个数必须相同,放回值也要相同(注:构成协变类型
可以不相同),final修饰的方法不能被重写
当子类和父类中出现同名方法的时候, 再去调用会出现什么情况呢?
其实这样就会打印出来子类的方法,这个时候就会很奇怪,不应该是调用父类,打印父类的方法嘛,在这个过程当中就发生动态绑定,又叫运行时绑定。
概念1(太官方):在 Java 中, 调用某个类的方法, 究竟执行了哪段代码 (是父类方法的代码还是子类方法的代码) , 要看究竟这个引用指向的是父类对象还是子类对象. 这个过程是程序运行时决定的, 因此称为 动态绑定.
概念2(太口水话):在Java中,如果满足父类和子类中都存在一个相同的方法,通过父类的引用在调用这个方法的时候,程序编译的是父类方法,在运行时绑定到了子类的方法,最后打印出来子类方法,这个过程称为 动态绑定
注意:另外在构造方法中也可以发生动态绑定
动态绑定发生的前提
有了对上面这些知识的了解后,我们就可以理解什么是多态,总的来说,多态是一种思想,是对同一个行为表现多种不同的表现形式…(这是啥???完全没懂,先上代码)
class Animal {
public void shout() {
//啥也不干
}
}
class Cat extends Animal {
@Override
public void shout() {
System.out.println("喵喵喵");
}
}
class Dog extends Animal {
@Override
public void shout() {
System.out.println("汪汪汪");
}
}
/我是分割线//
public class Java20210531 {
public static void main(String[] args) {
Animal animal1 = new Cat();
Animal animal2 = new Dog();
animalShout(animal1);
animalShout(animal2);
//喵喵喵
//汪汪汪
}
public static void animalShout(Animal animal) {
animal.shout();
}
}
这个代码够简单了(捂脸),很容易理解,分割线上面是类的实现者编写,下面是类的调用者编写,当类的调用者在编写 animalShout
这个方法的时候, 参数类型为 Animal
(父类), 此时在该方法内部并不知道, 也不关注当前的 animal
引用指向的是哪个类型(哪个子类)的实例. 此时 animal
这个引用调用 shout()
方法可能会有多种不同的表现(和 animal对应的实例相关), 这种行为就称为 多态.
简单来说,多态就是在多个子类同时继承一个父类的情况下,并且每个子类都重写了父类的某个方法,再通过父类引用不同的子类对象,调用同一个方法时,就会根据你引用的子类对象动态绑定到子类的方法中。(表述如果有误,请指正)
总结
无论是哪种编程语言, 多态的核心都是让调用者不必关注对象的具体类型. 这是降低用户使用成本的一种重要方式