前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >这些java面向对象的知识,你都知道吗?

这些java面向对象的知识,你都知道吗?

作者头像
yifei_
发布2022-11-14 14:04:25
1910
发布2022-11-14 14:04:25
举报
文章被收录于专栏:yifei的专栏

  我发现自己真的没学过java…… o(╯□╰)o   这篇总结可以帮助新手复习,或者查缺补漏(虽然还不太全面),也欢迎老手给指正错误。

面向对象特征

  • 封装(encapsulation)
  • 继承(inheritance)
  • 多态(polymorphism)

成员变量与局部变量

  • 成员变量 局部变量
  • 类中位置不同:类中方法外 方法内或者方法声明上
  • 内存位置不同:堆内存 栈内存
  • 生命周期不同:随对象存在或消失 随方法调用存在或消失
  • 初始值不同: 有默认的初始化值 必须先定义,赋值,才能使用

封装

  • 隐藏对象的属性和实现细节,仅提供对外公共访问方式
  • 将变化隔离、便于使用、提供代码复用性、提高安全性

四种权限修饰符

访问权限

本类

本包

子类

其他包

public

protect

default

private

如果不写为默认,即default。

构造方法

  • 函数名与类名相同
  • 不用定义返回值类型,不用写return
  • 作用:给对象初始化
  • 多个构造方法以重载形式存在
  • 不写会默认一个空的构造方法

Student s = new Student();在内存做了哪些事情?

  • 加载Student.class文件进内存
  • 在栈内存为s开辟空间
  • 在堆内存为s对象开辟空间
  • 对s的成员变量进行默认初始化
  • 对s的成员变量进行显示初始化
  • 通过构造方法对学生对象的成员变量赋值
  • 学生对象初始化完毕,把对象地址赋值给s变量

第四点:局部变量定义之后必须赋值才能用,而类中的成员变量不赋值便可以用,这时候 执行的是默认初始化。如下程序输出 0 ;

代码语言:javascript
复制
import java.util.*;

class Student{
	int age;
}

class Test1{
	public static void main(String [] args){
		Student s=new Student();
		System.out.print(s.age);
	}
}

第五点:显式初始化,如下程序输出5;

代码语言:javascript
复制
import java.util.*;

class Student{
	int age=5;
}

class Test1{
	public static void main(String [] args){
		Student s=new Student();
		System.out.print(s.age);
	}
}

static关键字

  可以用来修饰成员变量和成员方法

修饰成员变量

随着类的加载而加载

优先于对象而存在

被类的所有对象共享(最明显的特点),如下程序:

代码语言:javascript
复制
import java.util.*;

class Student{
	static int a=333;
	int b=333;
}

class Test1{
	public static void main(String [] args){
		Student s1=new Student();
		Student s2=new Student();
		System.out.println(s2.a+" "+s2.b);
		s1.a=666;
		s1.b=666;
		System.out.println(s2.a+" "+s2.b);
	}
}
//输出结果:
//333 333
//666 333

可以通过类名调用

代码语言:javascript
复制
import java.util.*;

class Student{
	static int a=333;
	int b=333;
}

class Test1{
	public static void main(String [] args){
		System.out.println(Student.a);
		//System.out.println(Student.b);
		//类名直接调用a可以,调用b不可以。
	}
}

修饰成员函数

  • 不能使用this或super关键字
  • 只能访问静态的成员变量和成员方法

静态变量与成员变量区别

  • 静态变量       成员变量
  • 属于类       属于对象
  • 存在于静态区       存在于堆内存
  • 随着类加载而加载       随着对象创建而存在
  • 可以类名调用,可以对象调用       只能对象调用

Java修饰符关键字的顺序

  顺序交换不会报错,但是这些约定俗成的东西还是有必要的。

代码语言:javascript
复制
import java.util.*;
class Test1{
public static final int a=1;
static final public int b=1;
final public static int c=1;
static public final int d=1;
final static public int e=1;

public static void main(String [] args){
	System.out.print(a);
	System.out.print(b);
	System.out.print(c);
	System.out.print(d);
	System.out.print(e);
}
}
// 输出结果:11111

保留字

  保留字是为java预留的关键字,他们虽然现在没有作为关键字,但在以后的升级版本中有可能作为关键字。

  • goto 跳转
  • const 静态,是一个类型修饰,与final有些类似
  • native 本地

transient

  待定。。。

继承

  多个类中存在相同属性和行为时,将这些内容抽取到单独的一个类中,其他类只要继承到那个类即可。

用法:

代码语言:javascript
复制
class student extends person{}

好处:

  • 提高了代码复用性
  • 提高了代码可维护性
  • 类之间产生了关系,是多态的前提,但也是一个弊端,增强了类的耦合性

notice:

  • 只能单继承,不支持多继承
  • 但是可以多层继承
  • 子类只能继承父类所有非私有的成员,私有成员不会被继承
  • 不能继承父类的构造方法,但是可以通过super去访问父类构造方法

super关键字

  • this代表本类对应的引用
  • super代表父类存储空间的标识

继承中构造方法的关系

  子类中所有构造方法默认都会访问父类空参数构造方法:   因为子类会继承父类中的数据,所以子类初始化之前,要先完成父类数据初始化。   

方法重写

  • 子类中出现和父类中一样的方法声明,称为方法覆盖或方法重写。
  • 父类中私有方法不能被重写
  • 重写父类方法,访问权限不能更低
  • 父类静态方法,子类也得通过静态方法重写

final关键字

  • “最终”的意思
  • 修饰类,类不能被继承
  • 修饰变量,变量就成了常量,只能被赋值一次
  • 修饰方法,方法不能被重写

多态

  同一事物,在不同时刻表现出来不同状态

代码语言:javascript
复制
猫 m = new 猫();
动物 d = new 猫();
//猫可以是一只猫,也可以是动物

多态前提和体现

  • 有继承关系
  • 有方法重写
  • 有父类引用指向子类对象

好处

  • 提高了程序的维护性(修改代码的话只修改父类即可,利于维护)
  • 提高了程序的扩展性(若想扩展功能,在子类扩展即可)

弊端

  • 不能访问子类特有功能

向上转型

从子到父,父类引用指向子类对象。我的理解就是本来new了一个Student对象,然后把他(向上)转为父类的Person类型。 用法:

代码语言:javascript
复制
Person p=new Student();

举个栗子:

代码语言:javascript
复制
import java.util.*;

class Person{
	int per;
	void show1(){
		System.out.println("this is class of person.");
	}
}

class Student extends Person{
	int stu;
	void show1(){
		System.out.println("this is class of Student1.");
	}
	void show2(){
		System.out.println("this is class of Student2.");
	}
}

class Test1{
	public static void main(String [] args){
		Person p=new Student();
		p.show1();
		//p.show2();//p无法访问子类Student的方法
		System.out.println(p.per);
		//System.out.println(p.stu);//p无法访问子类Student的成员变量
	}
}
// 输出结果:
// this is class of Student1.
// 0
  • 向上转型会失去子类的中的某些成员(成员变量和成员方法),”某些”是指父类中没有的那些成员。即p只能访问父类中有的成员,并且由于子类Student类已经重写show1,所以p实际调用的是重写之后的show1。

向下转型

从父到子,父类引用转为子类对象。即把Person类型的p(向下)转为Student类型。 用法:

代码语言:javascript
复制
Student s=(Student)p;

举个栗子:

代码语言:javascript
复制
import java.util.*;

class Person{
	void show1(){
		System.out.println("this is class of person.");
	}
}

class Student extends Person{
	void show2(){
		System.out.println("this is class of Student2.");
	}
}

class Test1{
	public static void main(String [] args){
		Person p=new Student();//方法一正确
		//Person p=new Person();//方法二会有强制类型转换异常
		//Exception in thread "main" java.lang.ClassCastException: 
		//Person cannot be cast to Student at Test1.main(Test1.java:24)
		Student s=(Student)p;
		s.show1();
		s.show2();
	}
}
// 输出结果:
// this is class of person.
// this is class of Student2.
  • 经过尝试,向下转型之前必须先向上转型,采用方法一可以。采用方法二会报错。

多态练习①

代码语言:javascript
复制
class Human {  
    public void sleep() {  
        System.out.println("Human sleep..");  
    }  
}  
class Male extends Human {  
    public void sleep() {  
        System.out.println("Male sleep..");  
    }  
}  
class Female extends Human {   
    public void sleep() {  
        System.out.println("Female sleep..");  
    }  
} 
class MaleStudent extends Male {  
    public void sleep() {  
        System.out.println("MaleStudent sleep..");  
    }  
}  
class Test1{    
    public static void main(String[] args) {    
        dosleep(new Male());
        dosleep(new Female());    
		dosleep(new MaleStudent());
    }    
    
    public static void dosleep(Human h) {
        h.sleep();    
    }    
}    
// 输出结果:
// Male sleep..
// Female sleep..
// MaleStudent sleep.

当new Male()传入dosleep()时,执行的是Human h=new Male();即向上转型。无论传入的是Male,Female,还是MaleStudent,都只用一个dosleep接收就可以,也不用重载dosleep函数,提高了代码的复用性。

  • 当new Male()传入dosleep()时,执行的是Human h=new Male();即向上转型。无论传入的是Male,Female,还是MaleStudent,都只用一个dosleep接收就可以,也不用重载dosleep函数,提高了代码的复用性。

多态练习②

这个栗子有点恶心,但是对理解多态会有帮助的。

代码语言:javascript
复制
class A {    
    public String show(D obj) { 
        return ("A and D");    
    }    
    public String show(A obj) {    
        return ("A and A");    
    }     
}

class B extends A{    
    public String show(B obj){    
        return ("B and B");    
    }    
    public String show(A obj){    
        return ("B and A");    
    }     
}    
    
class C extends B{}    
    
class D extends B{}    
    
class Test1{    
    public static void main(String[] args) {    
        A a1 = new A();    
        A a2 = new B();    
        B b = new B();    
        C c = new C();    
        D d = new D();    
            
        System.out.println("1--" + a1.show(b));    
        System.out.println("2--" + a1.show(c));    
        System.out.println("3--" + a1.show(d));    
        
        System.out.println("4--" + a2.show(b));    
        System.out.println("5--" + a2.show(c));    
        System.out.println("6--" + a2.show(d)); 
        
        System.out.println("7--" + b.show(b));    
        System.out.println("8--" + b.show(c));    
        System.out.println("9--" + b.show(d));          
    }    
}    
/*  输出结果:
	1--A and A
	2--A and A
	3--A and D
	4--B and A
	5--B and A
	6--A and D
	7--B and B
	8--B and B
	9--A and D 
*/

对于前三个,a1有接收A类型和D类型的两个方法,所以第三个a1.show(d)就会调用show(D obj)来接收,而对于1,2的b和c,c继承b,b继承a,所以b,c都向上转型,调用的是show(A obj)。 对于4,5,6,A a2 = new B(); B向上转型成了A类型,就损失了show(B obj),而B中将show(A obj)重写了,所以a2中有以下两个方法:

代码语言:javascript
复制
public String show(D obj) {    
    return ("A and D");    
} 
public String show(A obj){    
    return ("B and A");    
}

当a2.show()传入的是b或c时,b,c都向上转型成A类型的,调用的是a2中的show(A obj)方法,当传入d时,调用a2中的show(D obj)方法。 对于7,8,9,B b = new B(); 由于B继承A,所以B中有以下三个方法:

代码语言:javascript
复制
public String show(D obj) {    
    return ("A and D");    
}
public String show(A obj){    
    return ("B and A");    
}
public String show(B obj){    
    return ("B and B");    
}

当b.show()传入b,c时,b和c都向上转型,然后调用的是show(B obj),传入d时,直接调用show(D obj)。

抽象类

在java中一个没有方法体的方法应该定义为抽象方法,在类中如果有抽象方法,该类必须定义为抽象类。

代码语言:javascript
复制
没有方法体:public abstract void noMethodBody();
空方法体:  public void empertyBody(){}

格式

代码语言:javascript
复制
abstract class className{}
public abstract void method();

抽象类不能实例化,可以由具体的子类实例化

接口

  • 比如猫狗是继承动物类,但是有些猫狗被训练有了钻火圈,跳高的功能,这些能力本来不属于猫狗,是经过训练得到的,或是说经过扩展得到的,java就是通过接口来定义这些额外扩展的功能。
  • 定义格式:interface interfaceName{}
  • 实现格式:class className implements interfaceName{}
  • 接口不能实例化,由具体的子类实例化。
  • 成员变量默认修饰符: public static final
  • 没有构造方法,接口主要用来扩展功能,没有具体存在
  • 只能有抽象方法,默认修饰符 public abstract

类与类,类与接口,接口与接口 的关系

  • 类与类:继承关系,只能单继承,可以多层继承
  • 类与接口:实现关系,可以单实现,可以多实现,可以继承一个类的同时实现多个接口
  • 接口与接口:可以单继承,可以多继承

抽象类与接口的区别

成员区别

  • 抽象类:变量、常量、抽象方法、非抽象方法
  • 接口:常量、抽象方法

设计理念区别

  • 抽象类:共性功能
  • 接口: 扩展功能

如有错误,还请指正。

欢迎与我分享你的看法。 转载请注明出处:http://taowusheng.cn/ 微博:寒枫–0-0– 知乎:https://www.zhihu.com/people/tao-wu-sheng 豆瓣:YIFEI

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-01-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 面向对象特征
  • 成员变量与局部变量
  • 封装
  • 四种权限修饰符
  • 构造方法
  • Student s = new Student();在内存做了哪些事情?
  • static关键字
    • 修饰成员变量
      • 修饰成员函数
        • 静态变量与成员变量区别
        • Java修饰符关键字的顺序
        • 保留字
        • transient
        • 继承
          • 用法:
            • 好处:
              • notice:
                • super关键字
                  • 继承中构造方法的关系
                    • 方法重写
                    • final关键字
                    • 多态
                      • 多态前提和体现
                        • 好处
                          • 弊端
                            • 向上转型
                              • 向下转型
                                • 多态练习①
                                  • 多态练习②
                                  • 抽象类
                                  • 接口
                                  • 类与类,类与接口,接口与接口 的关系
                                  • 抽象类与接口的区别
                                    • 成员区别
                                      • 设计理念区别
                                      领券
                                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档