Java学习
关于面向对象
面向对象:可以想象成,一类功能(方法)的一个象征,这个象征叫做对象,面向对象则是针对这个象征进行一系列操作。举个例子:功能要求是冷冻冷藏,冰箱就是对象,对冰箱的使用,叫做面向对象。
java面向对象学习的三条主线:
- 1.java类及类的成员:属性、方法、构造器;代码块、多态性
- 2.面向对象的三大特性:封装性、继承性、多态性、(抽象性)
- 3.其他关键字:this、super、static、final、abstract、interface、package、import
创建类的对象,就是类的实例化,又叫做实例化类。
格式://创建类的对象:类名 + 对象名 = new + 构造器
Person p1 = new Person();
编程思想就是:创建类,设计好类的成员(属性、构造器、方法)然后创建类的对象,通过“对象 · 属性”和“对象 · 方法”去调用类中写好的功能结构
一个类我们可以创建多个对象,而每个对象都独立拥有一套类的属性,一般情况下对象之间的属性值互不影响。
main方法{
对象 · 属性
对象 · 方法
}
class 类名{
//属性
//构造器
//方法
}
属性:分为成员变量和局部变量
* 成员变量(属性):直接定义在类中
* 局部变量:定义在方法内、方法形参、构造器内、构造器形参、代码块中等等。
* 属性有默认初始值,但是局部变量没有,所以像局部变量调用前需要显式赋值。
class User{
//属性(成员变量)
String name;
int age;
boolean isMale;
public void talk(String language) {//language:形参、也是局部变量
System.out.println("我们使用" + language);
}
public void eat() {
String food = "烙饼";//food:局部变量
System.out.println("北方人喜欢吃:" + food);
}
}
构造器:用来创建对象,初始化对象的信息。
说明:
- 1.如果没有显式的定义类的构造器的话,则系统默认提供一个空参的构造器
- 2.定义构造器的格式:权限修饰符 类名(形参列表){}
- 3.一个类中定义的多个构造器,彼此构成重载
- 4.一旦我们显式的定义了类的构造器之后,系统就不再提供默认的空参构造器
- 5.一个类中,至少有一个构造器
public class PersonTest {
public static void main(String[] args) {
//创建类的对象:new + 构造器
Person p1 = new Person();
p1.eat();
Person p2 = new Person("Tom");
System.out.println(p2.name);
}
}
class Person{
//属性
String name;
int age;
//构造器
public Person() {
System.out.println("Person()....");
}
public Person(String n) {
name = n;
}
public Person(String n,int a){
name = n;
age = a;
}
//方法
public void eat() {
System.out.println("吃");
}
public void study() {
System.out.println("学");
}
}
匿名对象:创建的对象,但是没有显式的赋给它一个变量名
特点(好处):只能使用一次,用后就被回收,节省内存空间
//定义一个学生类
public class Student{
//创建一个学习方法
public void study(){
System.out.println("好好学习,天天向上");
}
}
//测试类
public class Demo{
public static void main(String[] args){
//创建有名字的学生对象,对象名s
Student s = new Student();
s.study();
//注意,匿名对象只能使用一次,以下方式即为创建了两个匿名对象
new Student();//创建匿名对象但是并未进行任何操作
new Student().study();//创建匿名对象并调用study()方法
}
}
在这里插入代码片
方法的重载:在同一个类中,名字相同,但是参数个数或者参数类型不同。
-
方法重载的主要好处就是不用为了对不同的参数类型或参数个数,而写多个函数。多个函数用同一个名字,但参数表,即参数的个数或(和)数据类型可以不同,调用的时候,虽然方法名字相同,但根据参数表可以自动调用对应的函数。
-
重载的最直接作用是方便了程序员可以根据不同的参数个数,顺序,类型,自动匹配方法,减少写过个函数名或方法名的重复步骤
方法的重写:子类继承父类以后,可以对父类中同名参数的方法,进行覆盖操作
1.重写以后,当创建子类对象以后,通过子类对象调用子父类中的同名同参数的方法时,实际执行的是子类重写父类的方法
2.重写的规定
方法的声明:权限修饰符 返回值类型 方法名(形参列表) throws 异常的类型{
方法体
}
约定俗成:子类中的叫重写的方法,父类中的叫被重写的方法
① 子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表形同
② 子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符
特殊情况,子类不能重写父类中声明为private权限的方法
③ 返回值类型:
父类被重写的方法的返回值是void,则子类重写的方法的返回值类型只能是void
父类被重写的方法的返回值类型是A类型,则子类重写的返回值类型可以是A类或者A类的子类
父类被重写的方法的返回值类型是基本数据类型(比如:double),
则子类重写的返回值类型必须是相同的基本数据类型(必须也是double)
④ 子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型(具体放到异常处理的时候讲)
面试题:区分方法的重载与重写
答:方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。
面向对象的特征之一
封装性:
一、当我们创建一个类的对象后,我们可以通过“对象·属性”的方式,对对象的属性进行赋值。这里,赋值操作要受到属性的数据类型和存储范围的制约。除此之外,没有其他约束条件。但是,在实际问题中,我们往往需要给属性加入额外的限制条件。这个条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加。(比如:setLegs())–>此时,针对于属性就体现了封装性
二、封装性的体现
我们将类的属性私有化(private),同时,提供公共的(public)方法来获取(getxxx)和设置(setxxx)此属性的值
三、封装性的体现,需要权限修饰符来配合
1.java规定的4种权限:(从小到大):private、缺protected、public
2.4种权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类。修饰类的话:只能使用:缺省、public
3.具体的:4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类
四、总结
java提供了4种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构在被调用时的可见性的大小。
面向对象的特征之二
继承性:
一、继承性的好处:
①减少了代码的冗余,提高了代码的复用性
②便于功能的扩展
③为之后多态性的使用,提供了前提
二、继承性的格式:class A extends B{}
A:子类、派生类、subclass
B:父类、超类、基类、superclass
2.1体现:一旦子类A继承父类B以后,子类A中就获取了父类B中声明的结构:属性、方法
特别的,父类中声明为private的属性或方法,子类继承父类以后,仍然获取了父类中私有的结构。
只因为封装性的影响,使得子类不能直接调用父类的结构而已
2.2子类继承父类以后,还可以声明自己特有的属性或者方法,实现功能的扩展子类和父类的关系,不同于子集和集合的关系。
extends:延展、扩展
三、Java中关于继承性的规定:
1.一个类可以被多个子类继承
2.Java中类的单继承性:一个类只能有一个父类
3.子父类是相对的概念。
4.子类直接继承的父类,称为:直接父类。间接继承的父类称为:间接父类
5.子类继承父类以后,就获取了直接父类以及所有间接父类中声明的属性和方法
四、1.如果我们没有显式的声明一个类的父类的话,则此类继承与java.lang.Object类
2.所有的java类(除java.lang.Object类之外)都直接或者间接继承于java.lang.Object类
3.意味着,所有的java类具有java.lang.Object类声明的功能
面向对象特征之三
多态性:
1.理解多态性:一个事物的多重形态
2.何为多态性:对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
3.多态的使用:虚拟方法调用有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法;但在运行期,我们实际执行的是子类中重写的父类的方法
-
总结:编译,看左边;执行,看右边。
-
例如:Person p2 = new Man(); p2.eat(); 编译方法的时候,看的是左边Person p2;左边有eat方法结构,可以调用不报错 p2.walk(); 运行方法时,看的是右边new Man();执行Man中重写的方法
4.多态性的使用前提:① 类的继承关系 ② 方法的重写
5.对象的多态性:只适用于方法,不适用于属性(编译和运行都看左边)
public class PersonTest {
public static void main(String[] args) {
Person p1 = new Person();
p1.eat();
Man man = new Man();
man.eat();
man.age = 25;
man.earnMoney();
//******************************
//对象的多态性:父类的引用指向子类的对象
Person p2 = new Man();
//多态的使用:当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法-----虚拟方法调用
p2.eat();
p2.walk();
// p2.earnMoney();
System.out.println(p2.id);//1001
}
}
正常的方法调用
Person e = new Person();
e.getInfo();
Student e = new Student();
e.getInfo();
虚拟方法调用(多态情况下) 子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父
类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法
确定的。
Person e = new Student();
e.getInfo(); //调用Student类的getInfo()方法