java面向对象
  wDEQCMw5w7sG 2023年11月01日 61 0

java面向对象编程

面向对象思想:

  • 物以类聚,分类的思维模式。思考问题首先会解决问题需要那些分类
  • 适合处理复杂的问题,适合多人的协作问题

面向对象的本质:以类的方式组织代码,以对象的组织(封装)数据

特征:

  • 抽象
  • 三大特性:封装,继承,多态

static

  • 加了static的方法可以通过类名直接调用,否则需要实例化后调用

    但是:类里:两个static方法(两个都不是static)可以相互直接通过方法名调用。但是一个static方法不能直接调用一个非static方法

    原因:static和类一起加载,但是非static是类实例化后才存在,调用时后者不存在

  • 同理,static修饰的属性也是一样可以通过类名直接调用,且所有的对象共享一个static属性

public class Student extends Person {
  public  static  int a =10;

    public static void main(String[] args) {
        Student student = new Student();
        student.a--;
        Student student1 = new Student();
        System.out.println(student1.a);

    }
}
//out :9
  • 静态代码块

    只在第一次实例化调用

public class Student extends Person {
  public  static  int a =10;
    {
        //代码块(匿名代码块)
        System.out.println("匿名代码块");
    }
    static{
        //静态代码块
        System.out.println("静态代码块");
    }
    public Student(){
        //构造器
        System.out.println("构造器");
    }

    public static void main(String[] args) {
        Student student = new Student();
        System.out.println("--------------------");
        Student student1 = new Student();
    }
}
/*out:
静态代码块
匿名代码块
构造器
--------------------
匿名代码块
构造器
  • 静态导入包

    
    //正常情况下,Math.random
    //静态导入后
    import static java.lang.Math.random;
    public class Student extends Person {
    
        public static void main(String[] args) {
            random();
        }
    }
    

final

  • 修饰类:不能被继承
  • 修饰变量:不能被修改
  • 修饰方法:不能被子类重写

值传递和引用传递

值传递(pass by value):在调用函数时,将实际参数复制一份传递到函数中,这样在函数中对参数进行修改,就不会影响到原来的实际参数;

引用传递(pass by reference):在调用函数时,将实际参数的地址直接传递到函数中。这样在函数中对参数进行的修改,就会影响到实际参数;

java是值传递

//值传递:
public class main {

    public static void main(String[] args) {
        int a=1;
        main.change(a);
        System.out.println(a);
    }
    public static void change(int number){
        number=2;
    }
}
//out:1

//引用传递:本质还是值传递
public class main {

    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person.name);
        main.change(person);
        System.out.println(person.name);
    }
    public static void change(Person person){
        person.name="lihua";
        //本处的person指向
    }
}
class Person{
    String name;
}
// out:null
//     lihua

四种访问权限

java的访问权限有下面四种:

public--都可访问(公有)
protected--包内和子类可访问(保护)
不写(default)--包内可访问 (默认)
private--类内可访问(私有)

类和对象的关系

类是一种抽象的数据类型,它对某一种事物整体描述

对象是抽象概念的具体实例

public class main {
 public static void main(String[] args) {
    Person lihua = new Person();//实例化,lihua就是对象,person是类
    }

}
class Person{
    String name;
}

构造器

初始化对象值

new的本质是在调用构造器

public class main {

    public static void main(String[] args) {
        Person lihua = new Person("李华");
        System.out.println(lihua.name);
    }
//李华

}
class Person{
    String name;
    //无参构造器
    public Person(){
        name="人";
    }
    //有参构造器
    public Person(String name){
        this.name=name;
    }

}

构造器:快捷键alt+insert

创建对象内存分析

对象是通过引用来操作的:栈-->堆

默认值:数字: 0.0 0

​ char:\u0000(空)

​ boolean:false

​ other:null

封装

封装就是数据的隐藏:禁止直接访问数据,而应该通过操作接口来访问,这就是数据隐藏

程序设计追求:高内聚,低耦合。

  • 高内聚是指类的内部数据操作细节自己完成,不干涉。
  • 低耦合:仅仅暴露少量的方法给外部使用
public class Student {
    //    属性私有
    private String name;
    private int id;
    //设置get,set
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

get:获得数据

set:修改数据

快捷键alt+insert

封装的作用

  • 提高程序安全性,保护数据
  • 隐藏代码实现细节
  • 统一接口
  • 提高了系统可维护性

继承

  • 继承的本质是某一批类的抽象
  • extends:拓展。子类是父类的拓展
  • java只有单继承没有多继承
  • 子类(派生类)继承父类(基类),使用关键词extends
  • 子类可以继承父类除了(private或default同时不在同一个包内)的属性和方法
//父类
class Person{
    char name;
    public void say(){}
}
//子类
public class Student extends Person {

    public static void main(String[] args) {
        Student student = new Student();
        student.say();
    }
}

快捷键ctrl+H可以看到继承树

java所有类都直接或间接继承object

super

指父类

//父类
class Person{
    protected String name="person";
    public  void say(){}
}
//子类
public class Student extends Person {
   String name="Student";
    public static void main(String[] args) {
        Student student = new Student();
        student.printName("main");
    }
    public void printName(String name){
        System.out.println(name);
        System.out.println(this.name);
        System.out.println(super.name);
    }
}
//out:main
//    Studnet
//    person

另外:static方法是没有this和super的

//父类
public Person() {
    System.out.println("父类构造方法被调用了");
}
//子类
public Student() {
    //结果证明:此处隐藏代码super(),且只能在开头,否则报错,调用this()也必须在第一行,所以两者不能同时调用
        System.out.println("子类构造方法被调用了");
    }
//实例化后
/* out:父类构造方法被调用了
子类构造方法被调用了

默认调用父类的无参构造函数,否则手动调用有参super("name")

方法的重写

//方法的调用只和左边定义数据类型有关,要么是右边重写的左边方法
Person person = new Person();
//父类引用指向子类
Person person1 = new Student();
/*
当调用前面两者的同名静态方法,都是调用左边的静态方法

非静态方法,同名必须要重写,且后者调用的是student的重写方法
@Override //注解:有功能的注释
public void say() {
    super.say();
}
//重写父类的say()方法

重写:

  • 需要继承关系,
  • 子类重写父类方法,方法名必须相同,参数列表必须相同,
  • 修饰符:范围可以扩大,不能缩小(相对于父类,public>protect>default>private),但是父类如果是private的话不能算重写,是一个子类新增方法
  • 抛出的异常:范围可以缩小,不能扩大(相对于父类)

idea快捷键alt+insert:override

总而言之,重写是对于一些父类的功能子类不需要或是需要一定的修改

多态

同一个方法可以发送对象不同采用多种不同的行为方式

一个对象的实际类型是确定的(new 类),但可以指向对象的引用类型很多(父类或者有关系的类)

//方法的调用只和左边定义数据类型有关,要么是右边重写的左边方法
Person person = new Person();
//父类引用指向子类
Person person1 = new Student();

简而言之,有没有方法看左边,怎么实现方法看右边(非静态)。左边有就代表该方法存在可以调用,具体实现方法就看右边重写的

  1. 多态是方法的多态,属性没有多态

  2. 父类和子类有联系,否则类型转换异常ClassCastException!

  3. 存在条件:继承,方法需要重写,父类引用指向子类对象

  4. 无法重写的:static :不属于实例

    ​ final:常量

    ​ private方法

快捷键alt+回车 (new Student()==》补充选择引用)

instanceof

判断对象是什么类型

//Person 父类 ,teacher和student 子类
		Person student = new Student();
        if (student instanceof Student) {
            System.out.println("Student");
        }
        if (student instanceof Teacher) {
            System.out.println("Teacher");
        }
        if (student instanceof Person) {
            System.out.println("Person");
        }
        if (student instanceof Object) {
            System.out.println("Object");
        }
/* out :Student
Person
Object

类型转换

//go是子类student方法
Person student = new Student();
//父类转子类向下转型(高转低)
((Student) student).go();
Student student1 =new Student();
//子类转父类向上转型(低转高),丢失go方法
Person person = student1;
person.go(); //error

一个有趣的现象

Person person = new Person();
//父类引用指向子类
Person person1 = new Student();
System.out.println(person.getClass());
System.out.println(person1.getClass());
/*class com.xxx.Person
class com.xxx.Student

尽管编译时识别为左边的父类对象,但是使用getclass或者getname方法时依旧删除的右边的子类对象。这个原因跟调方法调的是子类的方法一样,就是因为编译器编译时,载入的是父类, 但是编译时会把 子类独有的 属性和方法屏蔽掉,然后才会 按照子类的模板生成对象。所以 getClass getName是子类的,而作为参数会被认为是父类的。
总结:编译看左,实现看右。父类的引用对象指向了子类的实例对象。当调用person1时是在调用父类的引用对象,而父类的正在运行的引用对象有指向了子类的实例对象。getClass()返回的是对象运行时的类型即实例对象,另外super,this的getClass实际上也是运行的getClass,等同于无前缀的getClass

class Student extends Person
{
    public void printTest()
    {
        System.out.println(super.getClass());
    }

    public void printTest2()
    {
        System.out.println(this.getClass());
    }

    public void printTest3()
    {
        System.out.println(getClass().getSuperclass());
    }
}
// out :class Student
//class Student
//class Person

//如果只得到类名:getClass().getName()

抽象类

用abstract修饰的类

用abstract修饰的方法:抽象方法,只有名字,没有实现,抽象方法子类必须重写实现,除非子类是抽象类

抽象类:

  • 不能被new,只是一个约束
  • 只要有抽象方法必须是抽象类,但是抽象类不一定全是抽象方法
  • 提高开发效率
  • 存在构造器

局限:单继承,接口实现多继承

public abstract class Student {
    public abstract void go();
}

接口

只有规范,自己不能写方法(抽象类具体实现和规范都有)

定义一组规则

关键词interface

接口不能被实例化,没有构造方法

接口的所有定义都是抽象的:

​ 定义的方法默认默认public abstract

定义的属性是默认public static final,final必须有具体值

public interface UserService {
    //默认public static final
    int a=0;
    //默认public abstract
    void add(String name);
}

实现接口关键词:implements

实现接口必须重写接口的所有方法

接口可以多实现

public class Student implements UserService ,OtherService{

    @Override
    public void add(String name) {
        
    }
}

内部类

在类的内部再定义一个类

  1. 成员内部类

    public class Student  {
        class Inner{
            public  void in(){
    
            }
        }
    
        public static void main(String[] args) {
            Student student = new Student();
    //        实例内部类
            Student.Inner inner = student.new Inner();
            inner.in();
        }
    }
    //内部类可以获得外部类的私有属性,其他的也可以
    
  2. 静态内部类

    
    public class Student  {
       public static class Inner{
            public  void in(){
    
            }
        }
        }
    //不能访问外部类的私有属性
    
  3. 局部内部类

    public class Student  {
        public  void in(){
               class Inner{
            }
        }
    
  4. 匿名内部类

//匿名内部类实例
public class  Student  {
   public void in(){
       //这是一个匿名对象
       new App().a();
       //匿名内部类
       new App(){
           @Override
           public void a() {

           }
       }
   }
}
class App{
   public void a(){}
}

另外可以通过getclass.getName方法打印匿名内部类的对象名,会发现是当前外部类名+$+数字(数字是第几个内部类)
除去上面以外:

一个Java文件可以有多个类但是只能有一个public 类

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  2Vtxr3XfwhHq   2024年05月17日   55   0   0 Java
  Tnh5bgG19sRf   2024年05月20日   110   0   0 Java
  8s1LUHPryisj   2024年05月17日   46   0   0 Java
  aRSRdgycpgWt   2024年05月17日   47   0   0 Java
wDEQCMw5w7sG