Java类与对象(知识点+练习+扩展)
面向对象是一种符合人类思维习惯的编程思想。现实生活中存在各种形态不同的事物,这些事物之间存在着各种各样的联系。在程序中使用对象来映射现实中的事物,使用对象的关系来描述事物之间的联系,这种思想就是面向对象。
面向过程
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一一实现,使用的时候依次调用就可以了。
面向对象
面向对象则是把构成问题的事务按照一定规则划分为多个独立的对象,然后通过调用对象的方法来解决问题。
对于解决复杂的项目,为了从宏观上把握,从整体上理性分析,我们需要使用面向对象的思路来分析整个项目;但是具体到微观操作,仍然需要面向过程的思路去解决.
面向对象编程的本质就是:以类的方式组织代码,以对象的方式组织(封装) 数据
封装
封装是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体实现细节。
继承
继承主要描述的就是类与类之间的关系,通过继承,可以在无需重新编写原有类的情况下,对原有类的功能进行扩展。
多态
多态指的是在一个类中定义的属性和功能被其他类继承后,当把子类对象直接赋值给父类引用变量时,相同引用类型的变量调用同一个方法所呈现出的多种不同行为特性。
基础知识点请参考Java方法(知识点+练习+扩展)文章
- 修饰符
- 返回值类型
- break和return的区别
- 方法名:注意规范,见名知意
- 参数列表
- 异常抛出
public class Demo01 {
//main方法,程序一般只有一个main方法
public static void main(String[] args) {
}
public String sayHello(){
return \”hello,world\”;
}
//返回空 return用来结束方法
public void hello(){
return;
}
public int max(int a,int b){
return a>b?a:b;//三元运算符
}
//初识异常抛出 后面会详细讲解
public void readFile(String file) throws IOException{
}
}
- 静态方法
public class Demo01 {
//main方法,一个项目一般只有一个main方法
public static void main(String[] args) {
//静态方法直接可以调用
String hello = sayHello();
System.out.println(hello);
}
public static String sayHello(){
return \”hello,world\”;
}
}
- 非静态方法
public class Demo01 {
//main方法,程序一般只有一个main方法
public static void main(String[] args) {
//非静态方法需要先实例一个对象,然后在调用
Demo01 demo01 = new Demo01();
String hello = demo01.sayHello();
System.out.println(hello);
}
public String sayHello(){
return \”hello,world\”;
}
}
- 形参和实参
形式参数和实际参数要对应
- 值传递和引用传递
值传递
基本类型参数的传递,是调用方值的复制.双方各自的修改,互不影响.
简单的来说,方法内部对参数变量的任何操作,都不会影响到方法外部的变量.
public class Demo02 {
public static void main(String[] args) {
int a = 1;
System.out.println(a);//1
//值传递 把1传递给了形式参数,没有返回值,a还是1
change(a);
System.out.println(a);//1
}
public static void change(int a){
a=10;
}
}
引用传递
引用类型的传递,调用方的变量和接收方的参数变量,地址指向的是同一个对象.双方任意一方对这个变量的修改,都会影响对方.
public class Demo03 {
public static void main(String[] args) {
//引用传递
Person person = new Person();
//默认为null
System.out.println(person.name);
//调用方法改变person对象name属性
change(person);
System.out.println(person.name);
}
public static void change(Person person){
person.name = \”小火车\”;
}
}
class Person{
String name;
}
- 面向对象的编程思想,力图让程序中对事物的描述与该事物在现实中的形态保持一致。为了做到这一点,面向对象的思想中提出了两个概念——类和对象。
- 类是对某一类事物的抽象描述,而对象用于表示现实中该类事物的个体。
- 类用于描述多个对象的共同特征,它是对象的模板,而对象用于描述现实中的个体,它是类的实例。对象是类的具体化,并且一个类可以对应多个对象。
- 在面向对象的思想中,最核心的就是对象。
- 为了在程序中创建对象,首先需要定义一个类。
- 类是对象的抽象,它用于描述一组对象的共同特征和行为,例如人都有姓名、年龄、性别等特征,还有学习、工作、购物等行为。
- 以面向对象的编程思想,就可以将某一类同的特征和行为封装起来,把共同特征作为类的属性(也叫成员变量),把共同行为作为类的方法(也叫成员方法)。
类的定义格式
[修饰符] class 类名 [extends 父类名] [implements 接口名]{
// 类体,包括类的成员变量和成员方法
}
声明(定义)成员变量
[修饰符] 数据类型 变量名 [ = 值];
某一个方法中定义的局部变量与成员变量同名,这种情况是允许的,此时方法中通过变量名访问到的是局部变量,而并非成员变量。
声明(定义)成员方法
[修饰符] [返回值类型] 方法名([参数类型 参数名1,参数类型 参数名2,…]){
//方法体 …
return 返回值; //当方法的返回值类型为void时,return及其返回值可以省略
}
package oop.demo02;
//Students类
public class Students {
String name;
int age;
public void study(){
System.out.println(this.name+\”正在学习.\”);
}
}
- 使用new关键字创建对象
- 使用new关键字创建的时候,除了分配内存空间外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用.
对象创建的语法格式:
类名 对象名称 = new 类名();
package oop.demo02;
//Students类
public class Students {
String name;
int age;
public void study(){
System.out.println(this.name+\”正在学习.\”);
}
}
package oop.demo02;
public class Application {
//一个项目应该只存一个main方法
public static void main(String[] args) {
//类实例化后会返回一个自己的对象
Students xm = new Students();
Students xh = new Students();
//对象在创建的时候会初始化 name默认值为null age默认值为0
System.out.println(xm.name);
System.out.println(xm.age);
//
xm.name=\”小明\”;
xm.age=17;
xh.name=\”小红\”;
xh.age=18;
System.out.println(xm.name);
System.out.println(xm.age);
System.out.println(xh.name);
System.out.println(xh.age);
}
}
对象成员的调用:
①通过对象的引用来访问对象所有的成员.
对象引用.对象成员
②直接使用创建的对象本身来引用对象成员.
new 类名().对象成员
对比说明:
第2种方式,创建实例对象的同时就访问了对象成员,并且在创建后只能访问其中某一个成员,而不能像第1种方式那样可以访问多个对象成员。
同时,由于没有对象引用的存在,在完成某一个对象成员的访问后,该对象就会变成垃圾对象。
所以,在实际开发中,创建实例对象时多数会使用对象引用。
成员变量的初始值
在Java中,针对类、成员方法和属性提供了四种访问级别,分别是private、default、protected和public。
四种访问控制级别说明:
- private(当前类访问级别):如果类的成员被private访问控制符来修饰,则这个成员只能被该类的其他成员访问,其他类无法直接访问。类的良好封装就是通过private关键字来实现的。
- default(包访问级别):如果一个类或者类的成员不使用任何访问控制符修饰,则称它为默认访问控制级别,这个类或者类的成员只能被本包中的其他类访问。
- protected(子类访问级别):如果一个类的成员被protected访问控制符修饰,那么这个成员既能被同一包下的其他类访问,也能被不同包下该类的子类访问。
- public(公共访问级别):这是一个最宽松的访问控制级别,如果一个类或者类的成员被public访问控制符修饰,那么这个类或者类的成员能被所有的类访问,不管访问类与被访问类是否在同一个包中。
- 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。
- 是类的一个特殊成员,它会在类实例化对象时被自动调用。
- 如果需要在实例化对象的同时就为这个对象的属性进行赋值,可以通过构造方法来实现。
并且构造器有以下两个特点:
- 必须与类的名字相同。
- 在方法名的前面没有返回值类型的声明。
- 在方法中不能使用return语句返回一个值,但是可以单独写return语句来作为方法的结束。
定义构造方法的语法格式:
[修饰符] 方法名 ([参数列表]){
// 方法体
}
package oop.demo03;
public class Application {
public static void main(String[] args) {
//new 实例化了一个对象
//使用new关键字 本质是在调用构造器
Person person = new Person();
System.out.println(person.name);
}
}
//Person类
package oop.demo03;
public class Person {
String name;
public Person(){
this.name = \”小火车\”;
}
}
默认的无参构造方法
在Java中的每个类都至少有一个构造方法,如果在一个类中没有显示地定义构造方法,系统会自动为这个类创建一个默认的无参构造方法。
class Person {
public Person() {
}
}
有参构造
package oop.demo03;
public class Application {
public static void main(String[] args) {
//new 实例化了一个对象
//使用new关键字 本质是在调用构造器
Person person = new Person(\”嘟嘟嘟的小火车\”);
System.out.println(person.name);
}
}
//Person类
package oop.demo03;
public class Person {
String name;
public Person(){
this.name = \”小火车\”;
}
public Person(String name){
this.name = name;
}
}
当使用有参构造后,必须把无参构造也打出来,否则没有参数创建对象会报错
对象创建的内存分配:
- Java将内存分为两种,即栈内存和堆内存。
- 其中栈内存用于存放基本类型的变量和对象的引用变量(如Person p),堆内存用于存放由new创建的对象和数组。
- 在创建对象时,程序会占用两块内存区域,分别是栈内存和堆内存。
- 其中Person类型的变量p被存放在栈内存中,它是一个引用,会指向真正的对象;通过new Person()创建的对象则放在堆内存中,这才是真正的对象。
Java类和对象
类和对象是OP语言的一个重要的知识点,抽象性很高,我们学习起来可能会有一些疑惑,今天我们好好谈谈这个知识点,若有错误,还请诸位斧正。
在初阶里面我们需要理解什么是类,如何实例化一个对象。
类(英语:class)在面向对象编程中是一种面向对象计算机编程语言的构造,是创建对象的蓝图,描述了所创建的对象共同的特性和方法。 支持类的编程语言在支持与类相关的各种特性方面都多多少少有一些微妙的差异。大多数都持不同形式的类继承。许多语言还支持提供封装性的特性,比如访问修饰符。类的出现,为面向对象编程的三个最重要的特性( 封装性、继承性、多态性 ),提供了实现的手段。 来源:(维基百科)
在计算机科学中,对象(英语:object),台湾译作 \” 物件 \”,是一个存储器地址,其中拥有值,这个地址可能有标识符指向此处。对象可以是一个变量,一个数据结构,或是一个函数。是面向对象(Object Oriented)中的术语,既表示客观世界问题空间(Namespace)中的某个具体的事物,又表示软件系统解空间中的基本元素。 在软件系统中,对象具有唯一的标识符,对象包括属性(Properties)和方法(Methods),属性就是需要记忆的信息,方法就是对象能够提供的服务。在面向对象(Object Oriented)的软件中,对象(Object)是某一个类(Class)的实例(Instance)。 来源:维基百科
- 类就是一个模子 我们根据这个模子来造东西
- 对象就是一个实体,我们通过模子构造出的实体
我们来看看类的组成。
我们以一个例子来具体看看类的组成
字段 又称 “成员变量”,像下面的 name、 age、size 就是字段,这里的的字段又分为两种
- 实例成员变量 未用static修饰
- 静态成员变量 用static修饰
这些不同留在下面说
方法又称行为。类中的方法也分为两种,和字段一样看static是否修饰
- 实例成员方法
- 静态成员方法
至于这两者的不同,我后面会重点谈到,先放一放
一个类可以实例化多个对象,在堆上开辟相应的空间
static修饰与否会产生天差地别的不同
- 实例成员变量在 堆 上开辟
- 静态成员变量在方法区去开辟
由于静态成员变量开辟在方法区,所以可以说不在对象里面,可以这样说我们可以开辟多个对象,但这些对象“ 共用 ”静态成员变量
某种意义上,静态成员方法的的要求更为严格,限制更多,这里我就不截图的
- 静态成员方法只能调用静态成员方法,而实例成员方法不做要求
- 静态成员方法里面不能出现实例成员变量,而而实例成员方法不做要求
我们刚才谈了很多,不过有一个词没有谈到,就是public。public是一个访问修饰限定符,让我们看看这些内容都有什么。这里我们重点谈的是private,也就不得不提到 封装
- public: 共有的
- private: 私有的
- protected 受保护的
- default : 默认权限 -> 包访问权限(后面会说)
在面向对象编程方法中, 封装 (英语:Encapsulation)是指,一种将抽象性函数接口的实现细节部分包装、隐藏起来的方法。同时,它也是一种防止外界调用端,去访问对象内部实现细节的手段,这个手段是由编程语言本身来提供的 。 来源:维基百科
我们通过private将自己的写的方法封装起来,避免用户随意修改我们的代码,另外提供一个接口,方便用户使用。
this关键字我们这里现在是不谈,后面我会再写一篇博客将关键字好好的的谈一谈,在这里我们就需要知道this.data 代表对象里的字段就可以了
构造方法也是一种方法,不给他比较特殊
- 构造方法的类名和方法名相同
- 没有返回值,注意 是没有,而不是返回值是void
一个对象的产生分为几步 两步
- 为对象分配内存
- 调用合适的构造方法
也就是说 构造方法一定参与对象的实例化
上面的 Person() 就是一个构造方法。
- 问:之前我们也没有写过构造方法啊,为什么还可以实例化对象? 答:因为编译器自动帮我们写了一个不带参数的构造方法,我们就不需要构造了
- 问:构造方法是如何调用的? 答: Person per = new Person();中的Person(),就是调用
- 为什么会报错 答:当我们自己写构造方法时,编译器便不再为我们自动生成了,我们实例化对象时调用的构造方法参数不对
- 问:可以存在多个构造方法吗 答:可以 构造方法也是遵从函数重载的
- 问:构造方法可以互相调用吗 答: 可以,不过this()调用时只能在第一行,也就是说一个构造方法只能调用一次另一个
代码块这个知识点我们不太常用,不过为了知识的完整性,我们还是把这个模块说一下吧.代码块分为以下几种
- 普通代码块 定义在方法中的代码块
- 构造块 定义在类中的代码块(不加修饰符)。也叫: 实例代码块 。构造代码块一般用于初始化实例成员变量
- 静态块 使用static定义的代码块。 一般用于初始化静态成员属性
- 同步代码块 这个不说
这里我们重点说一下构造快和静态块,下面一个代码就可以搞定
==从下面我们可以看出,静态块先执行,接着是实例代码块,后面才是构造方法.==这个顺序大家先记住.
看完上面的内容,想来你已经对类和对象有一定的了解了。下面的知识是关于一些常见问题的解答。我们一起来看看.
来看看这些问题把
下面代码是否可以编译通过
很抱歉,this关键字是对当前对象的引用,static修饰的成员变量和成员方法不在 对象 里面,所以编译不通过
下面的代码是不是报错.
class Test { public static int age = 18; } public class TestDemo { public static void main(String[] args) { Test test = null; System.out.println(test.age); System.out.println(Test.age); } }
不会报错,static修饰的变是不属于对象的,即使我们没有new对象,也会得到结果
那我们再看看下面的代码
这个更简单,由static修饰的变量 定义 在方法区中,无论是静态方法还是普通成员方法
看看下面的代码块静态代码块只能出现一次
class Test { public int age; { System.out.println(\”这是一个 实例代码块 !!!\”); } static { System.out.println(\”这是一个静态代码块 !!!!\”); } public Test() { System.out.println(\”这是一个构造方法!!\”); } } public class TestDemo { public static void main(String[] args) { Test test1 = new Test(); System.out.println(\”================\”); Test test2 = new Test(); } }
总结一点
- 静态的成员是不能在方法中定义的
- this关键字无法引用static修饰的方法或者变量
- 静态代码块只能出现一次,即使不用实例化对象也可以执行,具体需要到JVM才可以.
原文链接:https://blog.51cto.com/u_15132397/5624290?utm_source=tuicool&utm_medium=referral
Java 类和对象
上 Java 语言的第一课,相信很多老师都会解释一句话就是 Java 是一个纯面向对象的语言。
然后再加上一堆 Java 的历史,再加上一个经典的动物的例子。
比如说,我们要描述动物,不同品种的狗的例子,我们在这个基础上抽象出来一个 Class,这个就是我们说的类了。
这个很多人可能都没有想过吧,其实 Class 这个单词在英语里面有分类的意思。在英语世界里面,会用 Class 来表示很多东西。
比如说 Class A Felony,这个在英语法典里面就是表示的是刑事重罪的 A 分类。
在计算机语言中,我们就使用了 Class 来表示一个类了。
对象在我们定义 Class 后,我们就可以得到了。
还是用这个经典狗的例子,我们在定义了狗这一类动物后,我们需要将这个定义的动物映射到一条具体的狗上面。这条狗可能你的,也可能是隔壁老王的。
在现实中,肯定是不可能有 2 条一模一样重复的狗,但是在计算机数据上是可以存在的。
将类映射到具体的对象上的过程就是叫做实例化。这个应该比较好理解吧,因为 Class 是抽象,现在我们不讨论抽象的狗了,我们讨论隔壁老王家的狗。
如果把 Class 的狗直接拿过来用是肯定不行的,因为我们不知道我们现在要讨论的狗是谁的狗。
因此我们需要使用关键字 new 一下我们定义的 Class 的这个对象。然后我们就知道我们需要讨论隔壁老王家的狗了。
这个过程就叫做类的实例化。
因此,总结来说,对象就是实例化后的类。
对象是根据类创建的。在Java中,使用关键字 new 来创建一个新的对象。创建一个对象需要以下三步:
- 声明:声明一个对象,包括有对象类型和对象的名称
- 实例化:使用关键字 new 来创建一个对象。
- 初始化:使用 new 创建对象时,会调用构造方法初始化对象。
实际上我们可能并不是完全按照上面的 3 步来写代码。
实际上,你可以写出下面的代码是没有问题,也是可以编译通过的,你的 IDE 工具可能会提示你说下面的代码是重复的,你可以使用其他方法来避免重复。
但是实际上,没有人这样写,绝大部分你看到的代码都是:
这是因为 String 这个类在 JDK 中比较特殊,是字符串的对象,通常也是我们用得最多的有关的字符串的操作,因此 String 的对象是可以直接赋值的。
当你直接赋值后,其实 JDK 已经为你完成了上面的 3 步操作了。
有时候,你在定义好对象后,可能还暂时不知道要干什么,你可能就非常粗暴的直接 = null 到给定的对象上面了。
或者就先定义好,在使用的时候再初始化。
例如,你可以使用下面的代码来定义一个对象,但是不对这个对象进行任何操作。但是,随后你就马上要对这个对象进行操作了。
通常你的 IDE 工具会在这里提示要求你初始化这个变量。
这个时候你可以直接 new 一个 String,在你 new 一个 String 的时候,Java 就已经帮你完成了上面说的实例化了。
上面的代码,在 IDE 中会提示错误的,在构建的时候也会提示定义的变量没有初始化错误。
当然,你也可以直接将 null 赋值给你的变量,这样的结果得到的就是空对象异常。
在 Java 中,我们可以先定义一个对象,然后将 null 赋值给定义的对象。
考察下面的代码:
在上面的代码中,我们将 null 赋值给了一个字符串对象 testStr ,但是我们并没有对这个对象进行任何后续的赋值。
因此这个对象是 null 的,如果这个时候你有代码尝试获得字符串的长度,但是字符串为 null,第二条语句肯定会出现空对象异常。
这在 Java 中非常常见。
本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com
文章为作者独立观点不代本网立场,未经允许不得转载。