Java 面向对象

Java 面向对象

回顾方法的定义

  • 修饰符

  • 返回类型

  • break和 return的区別

    break:用来结束循环。 return:方法结束,返回一个结果。

  • 方法名:注意命名规范 , 见名知意

  • 参数列表

  • 异常抛出

回顾方法的调用

  • 静态方法
  • 非静态方法:需要构造实例化对象,进行调用。
  • 形参和实参
  • 值传递和引用传递
    • 值传递:在方法被调用时,实参通过形参把它的内容副本传入方法内部,此时形参接收到的内容是实参值的一个拷贝,因此在方法内对形参的任何操作,都仅仅是对这个副本的操作,不影响原始值的内容。
    • 引用传递:”引用”也就是指向真实内容的地址值,在方法调用时,实参的地址通过方法调用被传递给相应的形参,在方法体内,形参和实参指向同一块内存地址,对形参的操作会影响的真实内容。
  • this关键字
    • this指向自己的引用,即当前方法所在的对象。它的一个主要作用是要将自己这个对象当作参数,传送给别的对象中的方法。

类与对象的创建

类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。

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

语法:

[类的修饰符] class 类名称 [extends 父类名称][implements 接口名称列表]
{
    
	变量定义及初始化;
	方法定义及方法体;
}

什么是面向对象

  • 面向对象编程( Object- Oriented Programming,OOP)

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

  • 抽象

  • 三大特性

    • 封装
    • 继承
    • 多态
  • 从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象。

  • 从代码运行角度考虑是先有类后有对象。类是对象的模板。

创建与初始化对象

  • 使用new关键字创建对象。

  • 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。

  • 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下俩个特点:

    • 必须和类的名字相同。
    • 必须没有返回类型,也不能写void。
  • 构造器必须要掌握。

例子:

public class Person {
   

    private String name;
    private int age;

	//无参构造器
    public Person() {
   
    }
	//有参构造器:一旦定义了有参构造,无参就必须显示定义
    public Person(String name, int age) {
   
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
   
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }


    public static void main(String[] args) {
   
        Person[] people = new Person[4];
        people[0] = new Person("yt", 20);
        people[1] = new Person("wx", 21);
        people[2] = new Person("wx", 20);
        people[3] = new Person("wx", 23);
        Person persons = new Person();
        System.out.println(Arrays.toString(people));
    }
}

创建对象的内存分析

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

例子:

public class Pet {
   
    String name;
    int age;
    
    public void shout(){
   
        System.out.println("叫了一声");
    }
}
public class Application {
   
    public static void main(String[] args) {
   
        Pet dog = new Pet();
        dog.name = "旺财";
        dog.age = 3;
        dog.shout();
        System.out.println(dog.name);
        System.out.println(dog.age);
        Pet cat = new Pet();
    }
}

Java 面向对象

封装

该露的露,该藏的藏

  • 我们程序设计要追求 “高内聚,低耦合” 。高内緊就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。

封装(数据的隐藏)

  • 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。

记住这句话就够了: 属性私有,get/set

例子:

public class Person {
   

    private String name;
    private int age;


    public Person() {
   
    }

    public Person(String name, int age) {
   
        this.name = name;
        this.age = age;
    }

    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;
    }
}

继承

继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。

extands的意思是“”扩展”。子类是父类的扩展。

Java中类只有单继承,没有多继承!(接口可以多继承)

继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。

继承关系的俩个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字 extends来表示。

子类和父类之间,从意义上讲应该具有”isa”的关系。

final修饰的类无法继承。

例子:

public class Person {
   

    private String name;
    private int age;


    public Person() {
   
    }

    public Person(String name, int age) {
   
        this.name = name;
        this.age = age;
    }

}
public class Student extends Person {
   
    public Student(){
   
        //隐藏代码:调用父类的无参构造 super();
        //调用父类的构造器,必须要在子类构造器的第一行
        //如果父类没有无参构造器,子类无法调用父类的无参构造器,但是可以调用父类的有参构造器,实现无参构造器
    }

}
public class Teacher extends Person{
   

}

子类继承了父类,就会拥有父类的全部方法。

稀有的属性和方法无法被继承。

object类

  • 在Java中,所有的类都默认直接或间接继承Object类。

super

  • super调用父类的构造方法,必须在构造方法的第一行。
  • super必须只能出现在子类的方法或者构造方法中。
  • super和this不能同时调用构造方法。

方法重写

  • 重写都是方法的重写,和属性无关。
  • 子类重写父类的方法
    • 方法名必须相同。
    • 参数列表必须相同。
    • 修饰符:范围可以扩大,不可以缩小, public>protected>default>private。
    • 抛出异常范围:可以缩小,不可以扩大。
  • 静态方法:方法的调用只和左边,定义的数据类型有关。
  • 非静态方法:重写。
  • 为什么要重写?
    • 父类功能,子类不一定需要,或者不一定满足。

例子:

public class B {
   
    public  void test(){
   
        System.out.println("B=>test");
    }
}
public class A extends B{
   
    @Override
    public  void test(){
   
        System.out.println("A=>test");
    }
}
public class Application {
   
    public static void main(String[] args) {
   
       A a=new A();
       a.test();
       //父类的引用指向了子类
        B b=new A();//子类重写了父类的方法
        b.test();
    }
}

A=>test
A=>test

多态

即同一方法可以根据发送对象的不同而采用多种不同的行为方式。

一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多。

动态编译: 类型可扩展。

多态存在的条件

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

例子:

public class Student extends Person {
   

}
public class Application {
   
    public static void main(String[] args) {
   
        //一个对象的实际类型是确定的
        //new Student();
        //new Person();
        //可以指向的引用类型就不确定了:父类的引用指向子类
        
        //Student 能调用的方法都是自己的或者继承父类的
        Student s1 = new Student();
        //Person 父类型,可以指向子类,但是不能调用子类独有的方法
        Person s2 = new Student();
        Object s3 = new Student();
        //对象能执行那些方法,主要看对象左边的数据类型,和右边的new关系不大
    }
}

注意:

  • 多态是方法的多态,属性没有多态性。
  • 父类和子类,有联系,类型转换异常!ClassCastException!

instanceof (类型转换) 引用类型

例子:

public class Application {
   
    public static void main(String[] args) {
   
        //Object string
        //Object Person Teacher
        //Object Person Student
        Object object = new Student();
        System.out.println(object instanceof Student); //true
        System.out.println(object instanceof Person);//true
        System.out.println(object instanceof Object); //true
        System.out.println(object instanceof Teacher); //false
        System.out.println(object instanceof String); //false
       	Person person = new Student();
        System.out.println(person instanceof Student); //true
        System.out.println(person instanceof Person); //true
        System.out.println(person instanceof Object); //true
        System.out.println(person instanceof Teacher); //false
        //System.out.println(person instanceof String);//编译错误
    }
}

类型之间的转换: 父 —–> 子

高—>低 强制转换

低—>高 自动转换

子类转父类 会损失自己本来的一些方法。

方便方法的调用,减少重复的代码!

static关键字

static修饰属性,需要通过类名去调用。

静态变量多用于多线程。

静态方法无法之间调用非静态方法,需要通过实例化对象进行调用,可以直接调用当前类的静态方法,或者通过类名调用其他类的静态方法。

非静态方法可以直接调用当前类的静态方法。

{
   
    //匿名代码块,创建对象的时候执行,在构造器前面
}
static{
   
    //静态代码块,类加载的时候,永久执行一次
}

静态导入包

import static java.lang.Math.PI;
import static java.lang.Math.random;
public class Application {
   
    public static void main(String[] args) {
   
        System.out.println(random());
        System.out.println(PI);
    }
}

抽象类

abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。

抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。

抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。

抽象方法,只有方法的声明没有方法的实现,它是用来让子类实现的。

子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。

例子:

public  abstract class B {
   
    public  void test(){
   
    }
}

public class A extends B{
   
    @Override
    public  void test(){
   
        System.out.println("A=>test");
    }
}

接口

普通类: 只有具体实现

抽象类: 具体实现和规范(抽象方法)都有!

接口: 只有规范!自己无法写方法!约束和实现分离:面向接口编程

OO的精髓,是对对象的抽象,最能体现这一点的就是接口。 为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如c++、java、c#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象

声明类的关键字是 class,声明接口的关键字是 interface

例子:

public interface UserServiceDao {
   
    /** * @param user * 登录 * @return boolean */
    public boolean login(User user);

    /** * @param user * 注册 * @return boolean */
    public boolean register(User user);

    /** * @param user * 更新 * @return */
    public void update(User user);
}

方法修饰 public abstract

属性修饰 public static final

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

implements可以实现多个接口。

内部类

内部类就是在一个类的内部在定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。

  1. 成员内部类
  2. 静态内部类
  3. 局部內部类
  4. 匿名内部类
  5. Lambda表达式

成员内部类

例子:

public class Outer {
   
    private int id=10;
    public void out(){
   
        System.out.println("这是外部类方法");
    }
    class Inner{
   
        public void in(){
   
            System.out.println("这是内部类方法");
        }
        //获得外部类的私有属性
        public void getID(){
   
            System.out.println(id);
        }
    }
}

public class Application {
   
    public static void main(String[] args) {
   
        Outer outer = new Outer();
        //通过外部类来实现内部类
        Outer.Inner inner = outer.new Inner();
        inner.in();
        inner.getID();
    }
}

静态内部类

例子:

public  class Outer {
   
    private int id=10;
    public void out(){
   
        System.out.println("这是外部类方法");
    }
    static class Inner{
   
        public void in(){
   
            System.out.println("这是内部类方法");
        }

    }
}

局部内部类

例子:

public  class Outer {
   
    private int id=10;
    public void out(){
   
        System.out.println("这是外部类方法");
    }
    public void method(){
   
        class Inner{
   
            public void in(){
   
                System.out.println("这是内部类方法");
            }

        }
    }
}

匿名内部类

例子:

public class Application {
   
    public static void main(String[] args) {
   
      	//没有名字初始化类,不用将实例保存到变量中
        new Apple().eat();
    }
}
class Apple{
   
    public void eat(){
   
        System.out.println("1");
    }
}

Lambda表达式

Lambda表达式(也称为闭包),Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中),或者把代码看成数据。一个Lambda可以由用逗号分隔的参数列表、–>符号与函数体三部分表示。

使用 Lambda 表达式可以使代码变的更加简洁紧凑。

语法:

(parameters) -> expression
或
(parameters) ->{
    statements; }

以下是lambda表达式的重要特征:

  • 可选类型声明: 不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号: 一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • 可选的大括号: 如果主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字: 如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

Lambda 表达式实例

// 1. 不需要参数,返回值为 5 
() -> 5  
  
// 2. 接收一个参数(数字类型),返回其2倍的值 
x -> 2 * x  
  
// 3. 接受2个参数(数字),并返回他们的差值 
(x, y) -> x – y  
  
// 4. 接收2个int型整数,返回他们的和 
(int x, int y) -> x + y  
  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void) 
(String s) -> System.out.print(s)

例子:

public class Java8Tester {

public static void main(String args[]){

Java8Tester tester = new Java8Tester();
// 类型声明
MathOperation addition = (int a, int b) -> a + b;
// 不用类型声明
MathOperation subtraction = (a, b) -> a - b;
// 大括号中的返回语句
MathOperation multiplication = (int a, int b) -> {
 return a * b; };
// 没有大括号及返回语句
MathOperation division = (int a, int b) -> a / b;
System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
System.out.println("10 / 5 = " + tester.operate(10, 5, division));
// 不用括号
GreetingService greetService1 = message ->
System.out.println("Hello " + message);
// 用括号
GreetingService greetService2 = (message) ->
System.out.println("Hello " + message);
greetService1.sayMessage("Runoob");
greetService2.sayMessage("Google");
}
interface MathOperation {

int operation(int a, int b);
}
interface GreetingService {

void sayMessage(String message);
}
private int operate(int a, int b, MathOperation mathOperation){

return mathOperation.operation(a, b);
}
}

输出结果为:

10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
Hello Runoob
Hello Google

使用 Lambda 表达式需要注意以下两点:

  • Lambda 表达式主要用来定义行内执行的方法类型接口,例如,一个简单方法接口。在上面例子中,我们使用各种类型的Lambda表达式来定义MathOperation接口的方法。然后我们定义了sayMessage的执行。
  • Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力。

变量作用域

lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。

例子:

public class Java8Tester {

final static String salutation = "Hello! ";
public static void main(String args[]){

GreetingService greetService1 = message -> 
System.out.println(salutation + message);
greetService1.sayMessage("Runoob");
}
interface GreetingService {

void sayMessage(String message);
}
}

输出结果为:

Hello! Runoob

我们也可以直接在 lambda 表达式中访问外层的局部变量:

例子:

public class Java8Tester {

public static void main(String args[]) {

final int num = 1;
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
s.convert(2);  // 输出结果为 3
}
public interface Converter<T1, T2> {

void convert(int i);
}
}

lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)

int num = 1;  
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
s.convert(2);
num = 5;  
//报错信息:Local variable num defined in an enclosing scope must be final or effectively 
final

在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。

String first = "";  
Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length());  //编译会出错 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/114432.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号