- 面向对象上
- 一、类
- 1.类与对象的概念和联系
- 2.类的建立
- 1.创建一个类
- 2.类的属性与方法的创建
- 3.static关键字
- 二、类的三大特性
- 1.封装
- 访问修饰符
- 访问封装后的属性
- 类的对象的创建
- this关键字
- 2.继承
- 继承概念
- 优点
- 缺点
- 继承使用要点
- 实现继承
- 用super访问被重写的父类的方法
- 3.多态
- 概念理解
- 多态的前提条件
- 多态中方法的使用特点
- 多态的转型分为向上转型和向下转型两种
- 3. instanceof关键字
- 三.包机制
- 包的作用理解
- 如何创建一个包
- import 关键字 引入包
- 举个栗子,如何引入包访问包下面的类
- 四.栈丶堆丶方法区
- 1.栈
- 栈的特点
- 2.堆
- 3.方法区
- 4.运作过程
- 五丶构造方法
- 1.构造方法的作用
- 2.如何定义
- 3.构造方法的调用
- 4.构造方法的重载
- 总结
面向对象上 一、类 1.类与对象的概念和联系
Java是面向对象的语言,这二者的关系简单来说就是:类是对象的抽象,对象是类的个例!java中认为世界上的一切实体都可以看成对象(比如一个人),而既然是人(对象)就会有人(对象)的属性和行为,对象的属性就是该种对象都有的特性,比如一个人的身高体重等,行为就是对象可以做的事,比如一个人可以去开车(原则上我们不能让一只狗去开车,但是也可以硬写),行为就是类中的方法,以下会有介绍。把行为和属性抽象出来,就是该对象属于的类,一个人(对象)属于“人”这个类,所以我们可以抽象出一个“人”类来。下面建立一个“人”类来进一步熟悉类
2.类的建立 1.创建一个类每一个Java编译单元里面只能有一个公有的public类,定义格式:public+class+类名+大括号,但是可以有很多个普通类(不加public)代码如下
package Test01;
public class People {
}
class XueZhangZhenShuai{
}
这里有几个问题折磨了我一会
1:输出语句不能在类中写,需要在类中定义一个方法块,在方法块里面输出
2:类的名字不要与java里面本身自带的类名相同,否则无法输出(可能还有其他不能办的我没有遇到)
class System{
void write(){
System.out.println();//这里的out会无法识别
}
}
2.类的属性与方法的创建
类的属性就是本类对象都有的特征,方法就是本类对象可以完成的行为
代码如下
int age;
String name;//两个属性,人都有姓名和年龄
void eat(){
}
void study(){
}//两个方法,人都可以完成吃饭和学习等行为
需要注意的是对普通类来说,我们定义的方法必须要加大括号,意思是实现这个方法,即使大括号里面可以什么也不写。
3.static关键字在类中,用static声明的成员变量为静态成员变量,也称为类变量,可以是成员也可以是方法。类变量的声明周期和类相同,在整个应用程序执行期间都有效。调用类变量的时候,不需要创建对象
格式为:static +类型 +名字+值
static int sqb=250;//在类中声明
访问的时候,如果在本类内,直接写名字就可以访问
如果是本类外,本类名+他的名字就可以访问
System.out.println(sqb);//本类内 System.out.println(People.sqb);//本类外二、类的三大特性 1.封装
封装就是将类的某些属性隐藏在类的内部,使得这些属性只能通过该类的对象中的方法来进行操作和访问,封装的好处是使对象以外的部分不能随意的访问和操作对象的内部属性,从而避免了外界对对象内部属性的修改和破坏。
访问修饰符我们可以通过设置访问修饰符来隐藏某些属性,访问修饰符有四种:public,private,protected,default,四种的区别是:
public: “公有权限”,被其修饰的类、属性以及方法可以跨类访问,跨包访问。
private: “私有权限”,被其修饰的属性以及方法只能被该类的对象访问,其子类不能访问,更不能允许跨包访问。
protected: “受保护权限”被其修饰的属性以及方法只能被类本身的方法及子类访问,要注意子类在不同的包中也可以访问。
default:不加任何访问修饰符,称为“默认访问权限,该模式下,只允许在同一个包中进行访问。
private int age;
public String name;
protected int height;
int weight;
public void eat(){
}
private void study(){
}
protected void sleep(){
}
void paly(){
}
访问封装后的属性
由于添加了访问限制符,对某些属性我们不能随便修改,我们可以通过设置set和get方法来实现对某一个属性的设置和读取,关于set get方法的使用我在类的对象的创建里面写了,这里不方便写。
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
类的对象的创建
首先我们要创建一个构造方法(构造函数),用于构造该类的一个对象,代码如下,构造方法又称为构造器吧,我们可以提前设定一些属性的值,比如设定年龄为17,这样创建出来的对象的年龄就都为17,我在写题时候用到了就写一下吧,纪念一下,虽然挺简单的。
public People(int age, String name, int height, int weight) {
this.age = age;
this.name = name;
this.height = height;
this.weight = weight;
}//构造方法设置完成!
int age=20;
String name="孙千博";
int height=187;//虚构
int weight=70;
People people1=new People(age,name,height,weight);//对象孙千博(本人)已经创建完成!
System.out.println(people1);//输出对象的信息
System.out.println(people1.getName());//使用get方法访问对象的名字并输出出来
people1.setWeight(80);//使用set方法设定孙千博的体重为80,最近吃多了啊
OK创建完成!
this关键字上面的this 意思是访问当前对象,当参数和属性同名时我们可以使用他来区分!java里面this的用法和c++大致相同,不做赘述;
2.继承 继承概念继承是指一个子类(或称为派生类)继承父类(或称为基类)的特征(属性和方法)。继承是面向对象程序设计时实现代码复用的重要手段,它允许在原有的类的基础上进行扩展,增加功能,这样新产生的类称为子类。比如说,人都有名字,年龄等属性,都会吃饭睡觉,但是人有好几种(黄人黑人白人),每种人都有自己的特点(比如肤色不同),这样我就可以在子类里面单独定义他们的肤色(即扩展),同时黑种人黄种人白种人他们都继承了人的属性和方法,这样我就不用再单独定义了,他们之间是“is-a”的关系,即黑种人黄种人白种人都是人,提高了代码的重用性,减少了创建类的工作量。
优点1.减少创建类的工作量,每个子类都拥有父类的方法和属性;
2.提高了代码的重用性
3.子类可以有自己单独的方法和属性
4.让类与类之间产生了关系,为面向对象第三个特征:多态提供了前提
1.降低代码的灵活性。子类必须拥有父类的属性和方法;
2.增强了耦合性。当父类的常量、变量和方法被修改时,需要考虑子类的修改,如果不加规范,可能会很麻烦,大量的代码需要重构;
1.父类也称作超类、基类、派生类等。
2.Java中只有单继承,没有像C++那样的多继承。多继承会引起混乱,使得继承链过于复杂,系统难
于维护。
3.Java中类没有多继承,接口有多继承。
4.子类继承父类,可以得到父类的全部属性和方法(除了父类的构造方法),但不见得可以直接访问(比如,父类私有的属性和方法)。
5.子类可以写自己特有的属性和方法,目的是实现功能的扩展,子类也可以复写父类的方法即方法的重写。重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
6.java支持单继承,不直接支持多继承,但对c++多继承机制进行了改良。单继承:一个子类只有一个直接父类,多继承:一个子类可以有多个直接父类(java中不支持,进行了改良)不直接支持是因为多个父类中有相同成员,会产生调用的不确定性。在java中是通过“多实现”来实现的。java支持多重继承。C继承B,B继承A就会出现继承体系
我们首先写一个People类,代码如下
package Test01;
import java.util.Scanner;
public class People {
private int age;
public String name;
void eat(){
System.out.println("正在吃饭");
}
void study(){
}
void sleep(){
}
void paly(){
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
然后写Person的两个子类,黄种人和黑种人,黄种人里面实现了代码的重写,黑种人里面实现了功能扩展;
package Test01;
public class People1 {
public static void main(String[] args) {
black black1=new black();
black1.setAge(10);
black1.setName("boerte");
black1.eat();//子类继承了父类的方法和属性,黑人当然也会吃饭
black1.run();
yellow yellow1=new yellow();
yellow1.setAge(19);
yellow1.setName("孙千博");
yellow1.study();
}
}
class yellow extends People{
static String color="yellow";
void study(){
System.out.println("黄种人更聪明,学得快" );//子类重写父类中的方法
}
}
class black extends People{
static String color="black";
void run(){
System.out.println("有个黑人跑到了9.58");//子类可以有自己的方法,实现了扩展
}
}
运行结果
正在吃饭
有个黑人跑到了9.58
黄种人更聪明,学得快
进程已结束,退出代码0
用super访问被重写的父类的方法super是直接父类对象的引用。可以通过super来访问父类中被子类覆盖的方法或属性以及构造器。如果父类有多个构造器,可以通过改变super的形参列表实现具体访问;
package Test01;
public class People1 {
public static void main(String[] args) {
int age=17;
String name="孙千博";
yellow yellow1=new yellow(age,name);
yellow1.study();
}
}
class yellow extends People{
static String color="yellow";
public yellow(int age, String name) {
super(age, name);//访问父类的构造器,只能放在结构体里,并且必须是第一句,只出现一次;
}
void study(){
super.study();//先调用父类中的study方法;
System.out.println("黄种人更聪明,学得快" );//子类重写父类中的方法
}
}
class black extends People{
static String color="black";
public black(int age, String name) {
super(age, name);
}
void run(){
System.out.println("有个黑人跑到了9.58");//子类可以有自己的方法,实现了扩展
}
}
执行结果
正在学习super功能测试
黄种人更聪明,学得快
进程已结束,退出代码0
3.多态 概念理解现实事物经常会体现出多种形态,如我上面写的,黑人既是一个黑人,又是一个人,此时黑人就有两种形态。Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。多态是同一个行为具有多个不同表现形式或形态的能力。简单来说, 多态就是同一个接口,使用不同的实例而执行不同操作。
多态的前提条件1.要有继承关系
2.要有方法重写
3.要有父类应用指向子类对象
4.多态只是方法的多态,不是属性的多态
5.多态的定义与使用格式 定义格式:父类类型 变量名=new 子类类型();
多态成员方法:编译看左边,运行看右边
package Test03;
public class animal {
public static void main(String[] args) {
animal animal1=new cat();//向上转型
animal1.shout();//编译看左边,运行看右边,实际执行的是cat中的方法
}
void shout(){
System.out.println("一只动物正在叫");
}
}
class cat extends animal{
void eat(){
System.out.println("一只猫正在吃鱼");
}
void shout(){
System.out.println("喵喵喵~~~");
}
}
运行结果:喵喵喵~~~
多态的转型分为向上转型和向下转型两种向上转型:多态本身就是向上转型过的过程
使用格式:父类类型 变量名=new 子类类型();
适用场景:当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作。
向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用类型转为子类引用各类型
使用格式:子类类型 变量名=(子类类型) 父类类型的变量;
适用场景:当要使用子类特有功能时。
package Test03;
public class animal {
public static void main(String[] args) {
animal animal1=new cat();//向上转型
animal1.shout();//编译看左边,运行看右边,实际类型是cat,所以实际执行的是cat中的方法
//此时animal1不能访问eat方法,我们使用向下转型将他转为cat
cat c=(cat) animal1;
c.eat();//向下转型完成
}
void shout(){
System.out.println("一只动物正在叫");
}
}
class cat extends animal{
void eat(){
System.out.println("一只猫正在吃鱼");
}
void shout(){
System.out.println("喵喵喵~~~");
}
}
执行结果
喵喵喵~~~
一只猫正在吃鱼
进程已结束,退出代码0
3. instanceof关键字作用:用来判断某个对象是否属于某种数据类型。
注意: 返回类型为布尔类型
package Test03;
public class animal {
public static void main(String[] args) {
animal animal1=new cat();//向上转型
animal1.shout();//编译看左边,运行看右边,实际类型是cat,所以实际执行的是cat中的方法
//此时animal1不能访问eat方法,我们使用向下转型将他转为cat
cat c=(cat) animal1;
c.eat();//向下转型完成
if(animal1 instanceof animal){
System.out.println("amimal1是animal类型");
}else{
System.out.println("animal1是cat类型");
}
}
执行结果:
喵喵喵~~~
一只猫正在吃鱼
amimal1是animal类型
java中一切皆对象,有这么多对象就会有对应的许多类,所以为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间
包的作用相当于我们电脑中的文件夹,(不同文件夹里面可以放相同名字的文件)
如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。
java通过包机制,实现了防止命名冲突,访问控制,提供搜索和定位类(class)、接口、枚举和注释等功能。比如,我们假设一个包的名字为:
package net.java.util;那么他里面的某个类的地址就为package net.java.util.(类名).java;一个包(package)可以定义为一组相互联系的类型(类、接口、枚举和注释),为这些类型提供访问保护和命名空间管理的功能。我们可以根据自己的需要创建包来存放我们创建的有关系的类,接口等;
右键点击idea左边的源根(src)—>新建—>软件包即可,在命名时我们要注意以下几点
1:包名要求全部小写,包名也是标识符,必须遵守标识符的命名规则。
2:有个更加正式的命名规范如下(网上搜的命名规范,感觉不太常用):
公司域名倒序+项目名oa +模块名+功能名;
采用这种方式重名的几率较低。因为公司域名具有全球唯一性。
com. bjpowernode.oa.user.service;
为了能够使用某一个包的成员,我们需要在 Java 程序中明确导入该包。使用 “import” 语句可完成此功能。
举个栗子,如何引入包访问包下面的类首先创建一个zscc类,在Download包下面创建
package Download;
public class zscc {
String name;
}
然后再创建一个sunqq类,在Sunqq包下面创建
package Sunqq;
public class sunqq {
public static void main(String[] args) {
}
int age;
}
如果我们直接在sunqq里面的main里面访问zscc类,因为他俩的包不同,所以会报错;我们可以通过以下两种方式访问zscc类;
1:import +包名.类名,代码如下
package Sunqq;
import Download.zscc;//第一:通过包名.类名引入类
public class sunqq {
public static void main(String[] args) {
zscc zscc1=new zscc();//第一种方式
}
int age;
}
2:import +包名.*
package Sunqq;
import Download.*;//第二:通过包名.*引入Download包下所有的类,当然包括zscc
public class sunqq {
public static void main(String[] args) {
zscc zscc1=new zscc();//第二种方式
}
int age;
}
结束
四.栈丶堆丶方法区java虚拟机的内存可以分为三个部分: 栈丶堆丶方法区(方法区也属于堆)
1.栈 栈的特点以下摘抄自高淇课堂
- 栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)
- JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)
- 栈属于线程私有,不能实现线程间的共享!
- 栈的存储特性是“先进后出,后进先出”
- 栈是由系统自动分配,速度快!栈是一个连续的内存空间!
堆的特点如下:
1.堆用于存储创建好的对象和数组(数组也是对象)
2.JVM只有一个堆,被所有线程共享
3.堆是一个不连续的内存空间,分配灵活,速度慢!
方法区(又叫静态区)特点如下:
1.JVM只有一个方法区,被所有线程共享!
2.方法区实际也是堆,只是用于存储类、常量相关的信息!
3.用来存放程序中永远是不变或唯一的内容。(类信息【Class对象】、静态变量、字符串常量等)
4.方法区里面存贮的信息为:代码,静态方法,静态变量,字符串常量
我这里写了一个student类,在student类里面还有别的类(phone)的成员,我画了张图来展示运作过程,先看代码再看图;
package Sunqq;
public class sqb {
public static void main(String[] args) {//程序从main方法开始执行,创建一个栈帧
student stu1=new student();//在堆区创建一个内存地址,把地址编号给栈区的stu1
stu1.setAge(17);
stu1.setName("孙千博");
phone phone1=new phone();//在堆区再创建一个内存地址,把地址编号给栈区的phone1
phone1.setPrice(100);
stu1.setPhone(phone1);//以上赋值操作过程我在图上有详细演示
stu1.study();//在栈区再创建一个栈帧
}
}
class phone{
int price;
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
class student{
int age;
String name;
phone phone;
void study(){
System.out.println(this.name+"正在努力学习java");
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Sunqq.phone getPhone() {
return phone;
}
public void setPhone(Sunqq.phone phone) {
this.phone = phone;
}
}
运行结果:
孙千博正在努力学习java
进程已结束,退出代码0
上图片展示过程
ok ,结束
构造方法是一个比较特殊的方法,通过构造方法可以完成对象的创建,以及实例变量的初始化。换句话说:构造方法是用来创建对象,并且同时给对象的属性赋值。注意:实例变量没有手动赋值的时候,系统会赋默认值。
2.如何定义格式为:
[修饰符列表] 构造方法名(形式参数列表){
构造方法体;
通常在构造方法体当中给属性赋值,完成属性的初始化。
}
注意:
1.修饰符列表写:public。不要写public static。
2.构造方法名和类名必须一致。
3.构造方法不需要指定返回值类型,也不能写void
简单上个代码展示以下:
class student{
int age;
String name;
phone phone;
public student(int age, String name, Sunqq.phone phone) {
this.age = age;
this.name = name;
this.phone = phone;
}
}
3.构造方法的调用
使用new关键字
public class sqb {
public static void main(String[] args) {
int age=17;
String name="孙千博";
phone phone1=new phone();
student student1=new student(age,name,phone1);//创建完成!
System.out.println(student1);//输出一下看看
}
}
看一下结果:
student{age=17, name=‘孙千博’, phone=Sunqq.phone@4554617c}
进程已结束,退出代码0
ok
构造方法是支持方法重载的。在一个类当中构造方法可以有多个。并且所有的构造方法名字都是一样的。
方法重载特点:在同一个类中,方法名相同,参数列表不同。
调用的时候根据参数列表区分,这里不做演示;
以上是java面向对象上篇,下周我会写下篇;
这周总结了java类和对象,类的封装继承多态,包机制,栈堆方法区,构造函数的知识点。



