前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >对象与类(Java学习-2)

对象与类(Java学习-2)

作者头像
营琪
发布2019-11-04 16:55:46
4020
发布2019-11-04 16:55:46
举报
文章被收录于专栏:营琪的小记录营琪的小记录

面向对象程序设计概述

谈到类和对象,自然而然的想到面向对象程序设计(OOP),百度百科给的解释是

面向对象程序设计(Object Oriented Programming)作为一种新方法,其本质是以建立模型体现出来的抽象思维过程和面向对象的方法。模型是用来反映现实世界中事物特征的。任何一个模型都不可能反映客观事物的一切具体特征,只能对事物特征和变化规律的一种抽象,且在它所涉及的范围内更普遍、更集中、更深刻地描述客体的特征。通过建立模型而达到的抽象是人们对客体认识的深化。

我个人的看法是,C语言是面向过程的,更多的是算法+数据结构,一个程序成百上千的“过程”,以至于特别的繁琐;某天某人推出了一个“面向对象的架构”,先在关系数据库验证了一下下,发现把显示世界抽象为机器世界蛮方便的,只要一个模版,一切都可以化身为对象, 那么这也需要我们有“上帝视角”,提前对此抽象、模型。

so,面向对象,更多的是考虑数据结构,而非算法。

  • 类(class)

类是什么,看看刚刚百度百科的定义呗。

其本质是以建立模型,体现出来的抽象思维过程和面向对象的方法。

《Java核心技术》的定义:类是构造对象的模版或者蓝图。由类构造对象的过程称为类的实例化。

  • 对象

对象,也就是现实世界的抽象化实体,对象有三个特征(不是面向对象),分别为

对象的状态:描述当前特征信息。(正常调用方法才会改变,非正常改变就是封装有问题)

对象的行为:对象里面有什么方法,可以对它施加那些操作。

对象标识 :唯一识别身份的。(数据库中的主码/操作系统中的进程控制块?)

预定义类

说完上面的概念的东西,那就看看Java语言中的类,String类用的多,那就看看这个吧!

代码语言:javascript
复制
public final class String {//删除了非关键信息
     private final char value[];
     private int hash;
     private static final long serialVersionUID = -6849794470754667710L;
     public String() {
        this.value = "".value;
    }
     public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }
     public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }
}

String类是一个很大的类,里面有很多的方法,上面删除了很多东西,切记!

  • 对象与构造器
代码语言:javascript
复制
String str = new String();//方式一:实例化对象
String str = new String(str);//方法二:实例化对象

上面是两种使用构造器生成对象的方法。

String() 称为构造器,无返回值。

new 称为操作符,开辟新堆内存,返回一个引用(一个栈,存堆地址)。

new String()是在堆中开辟一块空间,把String对象存进去,返回值是一个引用(一个栈,存堆地址)。

String str为声明String类型变量,并存储这个引用。

堆内存空间:保存真正的数据,对象的属性信息。

栈内存空间:保存的堆内存的地址,堆内存操作权,简单理解为‘对象名称’。

这样我们就生成一个对象了,这里可以看到“方法二:实例化对象”,是可以把同类型对象作为参数传入,创建新对象的,类似构造器中参

数个数和参数类型不同,这种特征叫做“重载”,后面再讲!!(有意思,构造函数的隐式参数的概念this。)

注意,如果编写一个类没有编写构造器,那么系统会提供一个无参数构造器。

  • 实例域
代码语言:javascript
复制
int hash;
private int hash;     
private final char value[];
public static final long serialVersionUID = -6849794470754667710L;

上面hash,hash,value称为实例域,默认值分别为0,0,\u0000(空格)。

private称为私有的,本类对象才可以调用,外部类不可以使用,这也就是“封装”。

final修饰符,“最终的,最后的,常量”,表示存储在value变量中的字符数组对象引用不会再指示其他(一个栈,存堆地址),由于不能改变栈,只能通过对象中的方法进行改变数组内容。

serialVersionUID,使用了static和final修饰符,称为静态常量/静态域。静态域或者静态常量都是属于类的,而不是属于任何独立对象的,它只生成一份,大家用同一个值/引用。

代码语言:javascript
复制
long num = String.serialVersionUID;//静态域,属于类,不需要对象,即可直接调用

下面介绍的修饰符,也可以使用在类名、方法名前面。(后面再讲)

访问权限

实例域的值,可以通过构造器或者方法等进行修改。

  • 方法
代码语言:javascript
复制
 public int hashCode() {}

用户自定义类

只要有构造器,那么自己的类就算是完成了,可以正常的生成对象的,构造器和类是同名的。

有属性(实例域)和函数(方法),那么就可以对现实世界进行抽象,使用构造器生成对象了。

我们可以把Java提供的String类改变一下就是用户自定义类。

代码语言:javascript
复制
public final class String2 {//删除了非关键信息
     private final char value[];
     public String2() {
        this.value = "".value;
    }
     public int hashCode() {
        ......
    }
}

这样,我们就创建了一个类。每一个类中都有一个默认的构造器(构造方法)。

这个类编译了之后,会通过Java编译器,生成一个String2.class文件。(字节码文件)

当创建这个类实例,会通过String2.class文件,使用字节码解释器,生成机器码文件,系统就可以运行。

方法(重点)

方法比较重要,特地拿出来细谈。

  • main方法
代码语言:javascript
复制
public static void main(String[] args) {
	
}

main方法是一个程序的入口,会根据方法中的语句,依此执行,每个类都可以有一个main方法(在类中直接单元测试)。

  • 静态方法

main方法前面有static修饰符,表示此方法是静态的。

Java预定义类 ,Math类中有很多静态方法,我们就拿Math类学习学习呗!

代码语言:javascript
复制
public final class Math {
    public static final double PI = 3.14159265358979323846;
    public final double PI = 3.14159265358979323846;//注意
    ......
    public static int max(int a, int b) {
        return (a >= b) ? a : b;
    }
}

根据上面的静态域,可以推出静态方法的特性。同理可得

在下面两种情况下使用静态方法

1.一个方法不需要访问对象状态(不需要对象),其所需的参数都是通过显式参数提供的。

代码语言:javascript
复制
int a = Math.max(4,8);//返回最大的数,显示参数

2.一个方法只需要访问类的静态域

代码语言:javascript
复制
double pi = Math.PI;
  • 工厂方法(静态工厂)

这个留到设计模式再说,其实就是工厂流水线的形式,生产标准的对象,带上静态工厂呢!就是类不需要访问对象状态,自己访问静态方法,方法中设置对象的生产步骤.....。

代码语言:javascript
复制
(new LocalDate).new//工厂模式
NumberFormat.getGurrencyInstance//静态工厂
  • 方法参数(重点,值传递和引用传递的介绍)

方法参数,什么是方法参数呢??

代码语言:javascript
复制
public final class Math {
    ......
    public static int max(int a, int b) {
        return (a >= b) ? a : b;
    }
}

类似Math类,调用静态方法Math.max(1,5),1和5就是参数,称为实参,实际传过去的值。

max(int a, int b)中a、b称为形参,形式上的参数,变量名可以随便,规定调用此方法需要传递的数据类型和个数。

方法参数中,有一个概念,引用传递和值传递。

  • 值传递
代码语言:javascript
复制
package com.yingqi;

public class Demo {
	int a = 1;
	int b = 3;

	public void Multiple(int a, int b) {
		a = a * 3;
		b = b * 3;
		System.out.println("a=" + a + ",b=" + b);// 输出a=3,b=9
	}

	public static void main(String[] args) {
		Demo demo = new Demo();
		demo.Multiple(demo.a, demo.b);
		System.out.println("a=" + demo.a + ",b=" + demo.b);// 输出a=1,b=3
	}
}

从main函数开始,我们调用Multiple函数,把a,b的值穿进去,并且放大3倍,第一次在Multiple中输出3倍的结果,但是第二次输出并没有放大3倍,还是原来的数字,我们从内存分析看吧。

值传递

其实,可以看到方法中的a,b是拷贝 对象中的ab值。

  • 引用传递
代码语言:javascript
复制
package com.yingqi;

public class Demo {
	String str = "hello";

	public void Quote(String str) {
		str = "word!!";
		System.out.println(str);//输出word!!!
	}

	public static void main(String[] args) {
		Demo demo = new Demo();
		demo.Quote(demo.str);
		System.out.println(demo.str);//hello
	}

}

看样子,好像和刚刚没什么区别嘛,你哄我喔!但是,我可以说引用传递绝大多数会发生改变的,那为什么这个没有改变呢?字符串

我可以明确告诉你是字符串的问题,讲个正常的再解释这个!

代码语言:javascript
复制
package com.yingqi;

public class Demo {
	
	public void Quote(StringBuilder str2) {
		str2.append(" word!!");
		System.out.println(str2);//hello word!!
	}

	public static void main(String[] args) {
		StringBuilder str1 = new StringBuilder("hello");
		Demo demo = new Demo();
		demo.Quote(str1);
		System.out.println(str1);//hello word!!
	}

}

那这个为什么输出相同的//hello word!!呢,我们也用内存介绍吧。

引用传递

这图我画的好丑啊,但也可以看。

我们的引用传递,方法中的形参也是拷贝了一份相同的值(一个栈,存堆地址值),只不过这个值是指向同一个对象的,我们是改变了对象的内容,并没有改变这个值。那么输出结果就是Hello World!!

所以,Java的参数传递,只传递的是值,不是引用,我们是习惯了这样,叫这个名称罢了。

回到上一题,字符串的问题,str="word!!"相当与str= new String();也就相当改变了传递的值(回到值传递)!

我们先从一段代码中,学习什么是包,以及怎么使用,有什么用。

代码语言:javascript
复制
package java.lang;
import java.util.Random;

import sun.misc.FloatConsts;
import sun.misc.DoubleConsts;

public final class Math {
    ......
}

package java.lang这个就是包路径,Math类的源码、.calss文件都在这个目录的文件夹下。

包有什么作用,我们知道Java语音是发展了很久的,有很多类,也就是很复杂,一般复杂的东西,我们都会想到分层概念,包呢?也可以这样理解,每个包之间都是独立的,不同包中可以有相同名称的类。

  • 导入包
代码语言:javascript
复制
import java.util.Random;

import sun.misc.FloatConsts;
import sun.misc.DoubleConsts;

使用import关键字,后面接着包路径和名称,这样的语句就是导入包了,现在大家都用ide等开发工具,一般情况下,都会自动导包的,当遇到类冲突的时,我们需要手动导包,这个过程就不说了,慢慢就熟悉。

  • 静态导入包
代码语言:javascript
复制
package com.yingqi;
import static java.lang.System.*;
public class Demo {
	public static void main(String[] args) {
		out.print("yes");//yes
	}
}

import static 包路径 这样的语句,我们称为静态导入,导入包的静态资源(静态域,静态方法),那就可以直接使用了。

  • 把一个类放入包中
代码语言:javascript
复制
package java.lang;

类似的,package 包路径 这样的语句,我们称为把这个类放入到这个lang包中,包路径我们常用反写域名的形式。com.sum.*。

  • 包的作用域
代码语言:javascript
复制
public class Math {
    ......
}

class关键字前面public修饰符,代表可以被任意的类使用。

这些修饰符也可以使用在类名、方法名、域... 前面(后面再讲)

访问权限

这后面应该还可以谈一下类路径(ClassPath),很多语言都涉及到这个,但说出来却很复杂,我也有点绕(类加载器、全局设置、打包等...),一般我们使用ide等开发工具都不会涉及到这个问题。

总结

这些是很基础的东西,绝大多是编程语言都支持,并且相差不会很大,上面说的是远远不够的,大家要看更优秀的作品,这只是自己一年前的总结(原因在这里),这些基础敲多了,就自然的熟悉了。

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 面向对象程序设计概述
  • 预定义类
  • 用户自定义类
  • 方法(重点)
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档