Java学习记录(60~86)

官方笔记入口:http://www.sxt.cn/Java_jQuery_in_action/History_Direction.html

60 面向对象和面向过程

面向过程指按步骤实现,适用于简单任务,比如如何开车,比如如何把大象装冰箱,适合简单、不需要协作的事务,按步骤即可实现。
面向对象,应用于复杂任务,需要协作完成,比如如何造一辆车,先造每个部分,再组装。

总结:

  • 都是解决问题的思维方式,都是代码组织的方式。
  • 解决简单问题使用面向过程
  • 解决复杂问题:宏观上使用面向对象把握,微观上仍然是面向过程。
61 对象和数据管理

对象可以理解为在内存中的一个内存块,包含一个数据集。

科学、企业管理、 程序开发都遵循一个原则:量变引起质变。
企业大了,就需要变更管理方式;程序中数据多了,就需要变更对程序的管理方式。

分为三个阶段:

1.数据无管理时代:数据少,基本不需要刻意管理。企业创业阶段,人数少,也无需管理。
2.数组管理和企业部门制:同类型数据类型增多,如存储一个班每个人的年龄,采用数组来进行管理。企业人数多了,分成不同部门,每个部门类似一个数组,负责执行某种职能。
3.对象和企业项目制
企业继续发展,一个项目可能需要多个部门协同来完成,如果继续采用部门制来完成,管理会混乱。以项目为单位进行管理是更好的方式,一个完整的项目组,类似一个小型创业公司,各个部门都有,包括行政后勤人员、财务核算人员、开发、售前、售后、测试人员、设计人员等。大型公司往往采用这种项目制的方式进行管理。
同理,编程开发继续发展,各种类型的变量增多,数组管理已经难以满足要求。方法(对数据操作的管理)也变得复杂。于是面向对象来开发。

为了便于协作和管理,我们“将相关数据和相关方法封装到一个独立的实体”,于是对象产生了。
比如将一个学生作为一个对象
包括:属性(静态特征):年龄:18,姓名:李四,学号:123
方法(动态行为):学习,吃饭,考试

62 对象和类的概念

比如给我们很多天使的图片,我们根据图片抽象出天使的特征,归纳出一个天使类:带翅膀;女孩;善良;头上有光环。通过这个过程,得到了类,即类就是对象的抽象。

类可以看做是一个模板,或者图纸,系统根据类的定义来造出对象。比如造汽车,类就是图纸,里面规定了汽车的详细参数信息,我们根据图纸造出一辆汽车,得到汽车这个对象。

类叫做class;对象叫做Object,instance(实例)。某个类的对象就是某各类的实例。
·
类包括属性和方法。

属性(filed或成员变量) 用于定义该类或该类对象包含的数据或者说静态特征,作用范围是整个类体。定义成员变量要对其初始化,否则系统初始为默认值。

方法用于定义该类或该类实例的行为特征和功能实现。方法是类和对象行为特征的抽象,类似于面向过程中的函数。 面向过程中,函数是最基本单位,整个程序是由一个个函数调用组成的。面向对象中,整个程序的基本单位是类,方法是从属于类和对象的。

//定义一个学生类  认识类
public class Student {

	//定义属性
	int id;
	String name;
	int age;
 //只有属性没有方法,在C语言中叫结构体。
	
	//方法
	
	void study() {
		System.out.println("我在认真学习!");
	}
	
	void play() {
		System.out.println("我在玩游戏!王者荣耀!");
	}
	
		//构造方法。  用于创建这个类的对象。无参的构造方法可以由系统自动创建。
	Student(){	
	}
	//上面是无参的构造方法,可以省略不写
	
	
	//调用  程序执行的入口,必须要有main方法。
	public static void main(String[] args) {
		Student stu = new Student();  //在Student类下new一个对象命名为stu
		stu.play();  //对象的方法调用
		
	}

}


63 一个典型类的写法和调用_类的UML图入门
//定义一个学生类  认识类
public class Student {

	//定义属性
	int id;
	String name;
	int age;
	
	Computer comp; //引用自别的类 ,表示每个学生都有对应的电脑类。属性可以是一个别的类的对象。
	
 //只有属性没有方法,在C语言中叫结构体。
	
	//方法
	
	void study() {
		System.out.println("我在认真学习!编程用的电脑品牌是" + comp.brand + "。");
	}
	
	void play() {
		System.out.println("我在玩游戏!王者荣耀!");
	}
	
	//构造方法。  用于创建这个类的对象。无参的构造方法可以由系统自动创建。
	
	Student(){
		
	}
	//上面是无参的构造方法,可以省略不写
	
	
	//调用  程序执行的入口,必须要有main方法。
	public static void main(String[] args) {
		Student stu = new Student();  //在Student类下new一个对象命名为stu
		
		stu.id = 1001;
		stu.name =  "李四";
		stu.age =18;
		
		Computer c1 = new Computer();
		c1.brand  = "ASUS华硕A550j";
		//上面建好了一个电脑类的对象,并赋予了初值
		
		//把这个对象给Student的comp属性
		
		stu.comp = c1;
		
		stu.study();
		stu.play();  //对象的方法调用
		
	}
	
}

//创建一个新的类  Computer  模拟学生使用某品牌电脑学习
class Computer{
	String brand; //品牌
} //上面是一个新建的类,类和类之间也可以引用

类的互相引用容易造成混乱,因此采用UML图来理清头绪。UML图包括类名、属性、方法。可以用对应的工具软件来绘制。上面程序UML图如下:

在这里插入图片描述

64 面向对象的内存分析*

Java虚拟机的内存可以分为三个区域:栈stake、堆heap、方法区method area

  • 为每个线程创建一个帧栈,每个栈包含多个方法,每个方法由一个元素表示,一个元素是一个栈帧,存储局部变量、操作数、方法出口等。先进后出。
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

//定义一个学生类  认识类
public class SxtStu {

	//定义属性
	int id;
	String name;
	int age;
	
	Computer comp; //引用自别的类 ,表示每个学生都有对应的电脑类。属性可以是一个别的类的对象。
	
 //只有属性没有方法,在C语言中叫结构体。
	
	//方法
	
	void study() {
		System.out.println("我在认真学习!使用电脑:" + comp.brand );
	}
	
	void play() {
		System.out.println("我在玩游戏!王者荣耀!");
	}
	
	//构造方法。  用于创建这个类的对象。无参的构造方法可以由系统自动创建。
	
	SxtStu(){
		
	}
	//上面是无参的构造方法,可以省略不写
	
	
	//用命令行加载类的命令:  javac Student.java  ,java Student  开始启动虚拟机,加载数据到方法区
	
	
	
	
	//调用  程序执行的入口,必须要有main方法。
	public static void main(String[] args) {
		SxtStu stu = new SxtStu();  //在Student类下new一个对象命名为stu
		
		stu.id = 1001;
		stu.name =  "高淇";
		stu.age =18;
		
		Computer c1 = new Computer();
		c1.brand  = "联想";
		//上面建好了一个电脑类的对象,并赋予了初值
		
		//把这个对象给Student的comp属性
		
		stu.comp = c1;
		
		stu.study();
		stu.play();  //对象的方法调用
		
	}
	
}

//创建一个新的类  Computer  模拟学生使用某品牌电脑学习
class Computer{
	String brand; //品牌
} //上面是一个新建的类,类和类之间也可以引用

上面程序关于堆、栈、方法区的内存分配见下图:

在这里插入图片描述

65 构造方法详解_构造方法重载

构造器也叫构造方法(constructor),用于对象的初始化。

在这里插入图片描述


class Point{
	double x,y;
	
	//构造方法名称必须和类名保持一致
	public Point(double _x,double _y) {
		x = _x;
		y = _y;
	}
	
	public double getDistance(Point p) { //求距离
		return Math.sqrt((x - p.x)*(x - p.x) + (y - p.y) * (y - p.y));
		
	}
}
public class TestConstructor {

	public static void main(String[] args) {
		
		Point p = new Point(3.0,4.0);
		Point origin = new Point(0.0,0.0);
		
		System.out.println(p.getDistance(origin));
		
	}

}

构造方法重载:

public class User {
    int id; // id
    String name; // 账户名
    String pwd; // 密码
    
    public User() {
 
    }
    public User(int id, String name) {
//        super();					//构造方法的第一句总是super(),不写系统也会默认加上
        this.id = id;				//this表示创建好的对象。
        this.name = name;
    }
    public User(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
//        System.gc();
    }
    
    public static void main(String[] args) {
        User u1 = new User();
        User u2 = new User(101, "高小七");
        User u3 = new User(100, "高淇", "123456");     
    }
}
66 垃圾回收机制介绍_垃圾回收算法

Java 引入了垃圾回收机制(Garbage Collection),令C++程序员最头疼的内存管理问题迎刃而解。Java程序员可以将更多的精力放到业务逻辑上而不是内存管理工作上,大大的提高了开发效率。

Java的内存管理很大程度指的就是对象的管理,其中包括对象空间的分配和释放。

对象空间的分配:使用new关键字创建对象即可。
对象空间的释放:将对象赋值null即可。

垃圾回收器将负责回收所有“不可达”对象的内存空间。

任何一种垃圾回收算法一般要做两件基本事情:
1.发现无用的对象
2.回收无用对象占用的内存空间

无用的对象就是指没有任何变量引用该对象。Java的垃圾回收器通过相关算法发现无用对象,并进行清除和整理。

垃圾回收相关算法:

1.引用计数法

在这里插入图片描述
2.引用可达法(根搜索算法)
在这里插入图片描述

67 通用分代垃圾回收机制

分代垃圾回收基于这样的事实:不同的对象生命周期是不一样的。因此不同生命周期的对象可以采取 不同的回收算法,以便提高回收效率。将对象分为年轻代、年老代、持久代。JVM将堆内存(放对象的地方)划分为Eden(放置年轻代对象)、Survivor和Tenured/Old空间区。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述在这里插入图片描述

68 对象创建过程和this的本质

在这里插入图片描述

public class TestThis {
    int a, b, c;  //属性
 
    TestThis(int a, int b) {  //类的对象
    	this.a = a;
    	this.b = b;
    }
    
    TestThis(int a, int b, int c) {  //类的对象
    	this(a,b);
        this.c = c;
    }
 
    void sing() {  //方法
    }
    
    void eat() {  //方法
        this.sing(); // 调用本类中的sing();  这里this可以省略,不会造成歧义
        System.out.println("你妈妈喊你回家吃饭!");
    }
 
    //this不能用于static方法中
    public static void main(String[] args) {  //调用
        TestThis hi = new TestThis(2, 3);
        hi.eat();
        
    }
}
69 static关键字_内存分析静态变量和静态方法

在类中,用static生命的成员变量为静态成员变量,也称为类变量。类变量的生命周期和类相同,在整个应用程序直行期间都有效。

static修饰的成员变量和方法,从属于类。普通变量和方法从属于对象。



/**
 * 测试static关键字的用法
 * @author 高淇
 *
 */
public class User2 {
    int id; // id
    String name; // 账户名
    String pwd; // 密码
    
    static String company = "北京尚学堂"; // 公司名称
    
    
    public User2(int id, String name) {
        this.id = id;
        this.name = name;
    }
    
    public void login() {
    	printCompany();
    	System.out.println(company); 
        System.out.println("登录:" + name);
    }
    
    public static void printCompany() { //静态方法 从属于类
//         login();//调用非静态成员,编译就会报错 ,编译就会报错  可以看内存分析图
        System.out.println(company);
    }
    
    public static void main(String[] args) {
        User2 u = new User2(101, "高小七");
        User2.printCompany();
        User2.company = "北京阿里爷爷";
        User2.printCompany();
    }
}

方法区里面装的是类的信息,包括类的代码,静态变量,静态方法,常量(一般只包括字符串)。相当于图纸或模板。
堆里面装的是一个个对象的信息,包括一般变量和一般方法(非静态方法)。

静态方法中不能调用非静态成员。非静态方法中可以调用静态变量或静态方法。
如下图:

在这里插入图片描述

70 静态初始化块_继承树的追溯

在这里插入图片描述
上面的注意事项讲到继承再回头看。


/**
 * 测试静态初始化块的使用
 * @author 高淇
 *
 */
public class User3 {
    int id;        //id
    String name;   //账户名
    String pwd;   //密码
    static String company; //公司名称
    
    //静态初始化块,用于类的初始化操作。在静态初始化块中不能直接访问非static成员
    static {  //静态块 注意这里不是方法,仅仅是个语句块,用static修饰了
        System.out.println("执行类的初始化工作");
        company = "北京尚学堂";  //只能访问静态成员
        printCompany();//执行对象
    }  //这里是对类的初始化,还没有对象,因此是不能访问普通变量的
    
    
    //方法
    public static void printCompany(){  //静态方法,用于上面静态块进行调用
        System.out.println(company); //打印
    }  
    public static void main(String[] args) {  //main方法,这里什么都没做,并没有调用对象
        User3  u3 = null;
    }
}

/*
 * 最后结果:执行类的初始化工作
 * 			北京尚学堂
 * 这个结果并不是main方法调用得到的,而是执行静态初始化块对类进行初始化得到的。
 * 上述代码中静态初始化块进行了打印和执行后面建立的静态方法printCompany(),
 */
71 JAVA的 参数传值机制_值传递

在这里插入图片描述

/**
 * 测试参数传值机制
 * @author 高淇
 *
 */
public class User4 {
    int id;        //id
    String name;   //账户名
    String pwd;   //密码
      
    public User4(int id, String name) {
        this.id = id;
        this.name = name;
    }
     
    public   void   testParameterTransfer01(User4  u){
        u.name="高小八";
    }
    
    public   void   testParameterTransfer02(User4  u){
        u  =  new  User4(200,"高三");
    }
     
    public static void main(String[] args) {
        User4   u1  =  new User4(100, "高小七");
        
        u1.testParameterTransfer01(u1); 
        System.out.println(u1.name); //结果是高小八,传递的u1是指针型(引用型)

        u1.testParameterTransfer02(u1);
        System.out.println(u1.name); //结果仍然是高小八
      
    }
}
72 Java包机制_package的使用_jdk提供的常见包的作用

包机制是Java中管理类的重要手段。开发中,我们会遇到大量同名的类,通过包我们很容易解决类同名的问题,也可以实现对类的有效管理。包对于类,相当于文件夹对文件的作用。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

以后写类一定要先写包名,且包名在类代码中是非注释语句中的第一句。

package  cn.sxt.oo;		//一定是非注释性语句的第一句

public class User {
	public static void main(String[] args) {
		String  str;
	}
}

查看包的属性:右键-选择properties-resorce-location(查看所在工作空间)

在这里插入图片描述

java.lang中所有的类不用导入可以直接使用,如string,system都是其中的类。

73 import详解_静态导入详解

import主要用于调用其他包的类,如果没有import导入其他包的类,默认调用本包的类。
在这里插入图片描述

注:按Ctrl+点击某个类名可以查看源代码。

注:如果精确导入一个包下面的类,同时也导入一个包下面所有的类,引用的时候引用的是精确导入的那个类。精确导入的类优先级是最高的,未导入的本包的类是最低的。
遇到多个同名类不好分辨,引用时直接写出导入路径:包名+类名

package cn.sxt.oo;

//import cn.sxt.oo2.Human; //调用其他包的类要通过import

public class TestEncapsulation2   {
	public static void main(String[] args) {
		cn.sxt.oo2.Human  h = new cn.sxt.oo2.Human();  //Human类本类是默认的,出了包不能用
		//然后新建了个公开类Human,就可以在整个项目引用了
//		h.age = 13;
//		h.name = "高淇";		//name为default属性,不能被不同包的类访问
		
		h.sayAge(); //访问其他包的公开方法
		
	}
}

class  Girl   extends  cn.sxt.oo2.Human  {
	//girl是human的子类,继承之后可以继承其protected属性,即使不在一个包也可以
	void  sayGood(){
		System.out.println(height); 
	}
}

在这里插入图片描述

74 继承_instanceOf的使用

本章重点针对面向对象的三大特征:继承、封装、多态进行详细的讲解。另外还包括抽象类、接口、内部类等概念。

注意:本章主要是进行语法性质的了解,不要期望直接学习就搞透面向对象。本章只是起点,之后学的都是面向对象的应用。

继承让我们更加容易实现类的扩展。 比如,我们定义了人类,再定义Boy类就只需要扩展人类即可。实现了代码的重用,不用再重新发明轮子(don’t reinvent wheels)。

从英文字面意思理解,extends的意思是“扩展”。子类是父类的扩展。现实世界中的继承无处不在。比如:

在这里插入图片描述
图5-1 现实世界中的继承.png

上图中,哺乳动物继承了动物。意味着,动物的特性,哺乳动物都有;在我们编程中,如果新定义一个Student类,发现已经有Person类包含了我们需要的属性和方法,那么Student类只需要继承Person类即可拥有Person类的属性和方法。

 选中类,单击右键,选中Open type hierarchy,则能看到此类的继承关系。
 或者指向类之后,按Ctrl+t,也能直接看到此类的继承关系。

1.父类也称作超类、基类、派生类等。
2.Java中只有单继承,没有像C++那样的多继承。多继承会引起混乱,使得继承链过于复杂,系统难于维护。
3.Java中类没有多继承,接口有多继承。
4.子类继承父类,可以得到父类的全部属性和方法 (除了父类的构造方法),但不见得可以直接访问(比如,父类私有的属性和方法)。
5.如果定义一个类时,没有调用extends,则它的父类是:java.lang.Object。

instanceof是二元运算符,左边是对象,右边是类;当对象是右面类或子类所创建对象时,返回true;否则,返回false。即检验左边是不是右边类的对象。或是不是右边类的子类的对象。

	Student  stu2 = new Student("希希",6,"挖掘机专业");//利用构造方法新建对象并初始化
		
		System.out.println(stu2   instanceof  Student);
		System.out.println(stu2   instanceof   Person ); 
		System.out.println(stu2   instanceof   Object ); 
//结果都是true

75 方法的重写override_返回值类型问题

指的是子类通过重写父类的方法,可以用自身的行为替换父类的行为。方法的重写是实现多态的必要条件。重写也称为覆盖。

方法的重写需要符合下面的三个要点:

  1.“==”: 方法名、形参列表相同。

  2.“≤”:返回值类型和声明异常类型,子类小于等于父类。

  3.“≥”: 访问权限,子类大于等于父类。(见封装那节)
package cn.sxt.oo2;

public class TestOverride {
		public static void main(String[] args) {
			Horse   h   =  new Horse();
			h.run();
		}
}


class  Vehicle { //交通工具
	public  void  run(){
		System.out.println("跑....");
	}
	
	public   void stop(){
		System.out.println("停止!");
	}
	
	public  Person   whoIsPsg(){
		return  new Person();
	}
	
}

class    Horse   extends  Vehicle {
	public  void  run(){
		System.out.println("四蹄翻飞,嘚嘚的。。。");
	}
	
	public  Student   whoIsPsg(){//返回值类型小于等于父类的类型
		return  new Student();
	}
	
}



76 Object类的用法_重写toString方法

在这里插入图片描述

package cn.sxt.oo2;

public class TestObject {
	public static void main(String[] args) {
//		Object obj;
		
		TestObject   to = new TestObject();
		System.out.println(to);//System.out.println(to.toString)
		
		Person2  p2 = new Person2("希希", 6);
		System.out.println(p2.toString()); 
		
	}
	
	//toString的重写
	public String toString(){
		return  "测试Object对象";
	}
	
}


class Person2 {
    String name;
    int age;
    
    @Override
    public String toString() {
        return name+",年龄:"+age;
    }
    
    public Person2(String  name, int age) {
    	this.name = name;
    	this.age = age;
	}
    
    
}

77 equals方法的重写_阅读Object和toString源码

“==”代表比较双方是否相同。如果是基本类型则表示值相等,如果是引用类型则表示地址相等即是同一个对象。

Object类中定义有:public boolean equals(Object obj)方法,提供定义“对象内容相等”的逻辑。比如,我们在公安系统中认为id相同的人就是同一个人、学籍系统中认为学号相同的人就是同一个人。

Object 的 equals 方法默认就是比较两个对象的hashcode,是同一个对象的引用时返回 true 否则返回 false。但是,我们可以根据我们自己的要求重写equals方法。

JDK提供的一些类,如String、Date、包装类等,重写了Object的equals方法,调用这些类的equals方法, x.equals (y) ,当x和y所引用的对象是同一类对象且属性内容相等时(并不一定是相同对象),返回 true 否则返回 false。

78 super父类对象引用_继承树追溯问题

super是直接父类对象的引用。可以通过super来访问父类中被子类覆盖的方法或属性。

使用super调用普通方法,语句没有位置限制,可以在子类中随便调用。

若是构造方法的第一行代码没有显式的调用super(…)或者this(…);那么Java默认都会调用super(),含义是调用父类的无参数构造方法。这里的super()可以省略。

package cn.sxt.oo2;

public class TestSuper01 { 
    public static void main(String[] args) {
        new ChildClass().f();  //调用子类的f方法
    }
}
class FatherClass {
    public int value;
    
    public void f(){
        value = 100;
        System.out.println ("FatherClass.value="+value);
    }
}

class ChildClass extends FatherClass {
    public int value;
    
    public void f() {  //重新父类的方法 
        super.f();  //调用父类对象的普通方法
        value = 200;
        System.out.println("ChildClass.value="+value);
        System.out.println(value);
        System.out.println(super.value); //调用父类对象的成员变量
    }
}

构造方法调用顺序:

构造方法第一句总是,默认:super(…)来调用父类对应的构造方法。所以,流程就是:先向上追溯到Object,然后再依次向下执行类的初始化块和构造方法,直到当前子类为止。这就是继承树追溯。

注:静态初始化块调用顺序,与构造方法调用顺序一样,不再重复。见本文70小节

package cn.sxt.oo2;
public class TestSuper02 { 
    public static void main(String[] args) {
        System.out.println("开始创建一个ChildClass对象......");
        new ChildClass2();  //新建对象,相当于调用这个类
    }
}
class FatherClass2 {
    public FatherClass2() {
    	super();这行是默认的,不写的话系统也会默认执行这一句,这里追溯到object类
        System.out.println("创建FatherClass");
    }
}
class ChildClass2 extends FatherClass2 {
    public ChildClass2() {
    	super();  //这行是默认的,不写的话系统也会默认执行这一句,这里追溯到father类
        System.out.println("创建ChildClass");
    }
}

·属性/方法查找顺序也是按照追溯来进行:(比如:查找变量h)

  1. 查找当前类中有没有属性h

  2. 依次上溯每个父类,查看每个父类中是否有h,直到Object

  3. 如果没找到,则出现编译错误。

  4. 上面步骤,只要找到h变量,则这个过程终止。
79 封装的使用_访问控制符

我要看电视,只需要按一下开关和换台就可以了。有必要了解电视机内部的结构吗?有必要碰碰显像管吗?制造厂家为了方便我们使用电视,把复杂的内部细节全部封装起来,只给我们暴露简单的接口,比如:电源开关。具体内部是怎么实现的,我们不需要操心。

需要让用户知道的才暴露出来,不需要让用户知道的全部隐藏起来,这就是封装。说的专业一点,封装就是把对象属性和操作结合为一个独立的整体,并尽可能隐藏对象的内部实现细节

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

编程中封装的具体优点:

 1. 提高代码的安全性。

 2. 提高代码的复用性。

 3. “高内聚”:封装细节,便于修改内部代码,提高可维护性。

 4. “低耦合”:简化外部调用,便于调用者使用,便于扩展和协作。

Java是使用“访问控制符”来控制哪些细节需要封装,哪些细节需要暴露的。 Java中4种“访问控制符”分别为private、default、protected、public,它们说明了面向对象的封装性,所以我们要利用它们尽可能的让访问权限降到最低,从而提高安全性。

下面详细讲述它们的访问权限问题。其访问权限范围如表5-1所示
在这里插入图片描述

   1. private 表示私有,只有自己类能访问

  2. default表示没有修饰符修饰,只有同一个包的类能访问

  3. protected表示可以被同一个包的类以及其他包中的子类访问

  4. public表示可以被该项目的所有包中的所有类访问
  
   子类:扩展引用过这个类的类

利用上述不同权限的访问控制符来对类或属性、方法进行封装,相当于造电视机时加上外壳,使其变得不透明,保证了使用的安全性。

利用下面分别属于俩包的三组代码来理解

package cn.sxt.oo2;

public  class  Human {
	private  int age = 2;
	String  name;			//可以被本包下面的类访问
	protected   int  height ;   
	
	
	public  void   sayAge(){
		System.out.println(age);
	}
}
package cn.sxt.oo2;



/**
 * 测试封装
 * @author 高淇
 *
 */

public class TestEncapsulation{
	public static void main(String[] args) {
		Human h = new Human();
		//h.age = 13;
		h.name = "高琪"; //本包其他默认属性
		h.height = 230; //protected属性 同一个包中可访问
	}
	
}

class Boy extends Human{
	void sayHello(){
		//System.out.println(age);
		//子类无法使用父类的私有属性和方法
	}
}
package cn.sxt.oo;

import cn.sxt.oo2.Human;

public class TestEncapsulation2   {
	public static void main(String[] args) {
		Human  h = new Human();  //Human类本类是默认的,出了包不能用
		//然后新建了个公开类Human,就可以在整个项目引用了
//		h.age = 13;
//		h.name = "高淇";		//name为default属性,不能被不同包的类访问
		
		h.sayAge(); //访问其他包的公开方法
		
	}
}

class  Girl   extends  Human  {
	//girl是human的子类,继承之后可以继承其protected属性,即使不在一个包也可以
	void  sayGood(){
		System.out.println(height); 
	}
}
80 封装的使用细节_javabean的规则

类的属性的处理:

  1. 一般使用private访问权限。私有就完事儿了,安全。 
  外部向更改的话,调用那个类下面设置的公开的setName方法。即通过公开的方法来对私有属性改动。返回那个熟属性,用getName方法

  2.  提供相应的get/set方法来访问相关属性,这些方法通常是public修饰的,以提供对属性的赋值与读取操作(注意:boolean变量的get方法是is开头!)。

  3. 一些只用于本类的辅助性方法可以用private修饰,希望其他类调用的方法用public修饰(一般只把特别不希望别的类访问的方法设为private,其他大部分用public即可,即让项目下所有类均可访问)

将属性私有之后将控制权暴露于方法,可以利用方法对属性的特性加以灵活控制。

set/get方法的自动生成:右键-source-generate getters and setters

package cn.sxt.oo2;

/**
 * 仍然测试封装
 * @author 高淇
 *
 */
public class Person4 {
		private  int id;  //一般类的属性设置为私有
		private String  name;
		private  int  age;
		private  boolean  man;  
		
		public   void  setName(String  name){ 
			//通过公开的方法来对私有属性改动
			 this.name = name;
		}
		
		public  String  getName(){ //返回这个类的name属性 
			return  this.name;
		}
		
		public  void setAge(int age) {
			if(age>=1&&age<=130){  //利用if对属性值的更改加以限制
				this.age = age;
			}else{
				System.out.println("请输入正常的年龄!");
			}
		}
		
	
		public  int  getAge(){
			return this.age;
		}

		public int getId() {
			return id;
		}

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

		public boolean isMan() {
			return man;
		}

		public void setMan(boolean man) {
			this.man = man;
		}
		
		//快捷操作 右键-source-generate getters and setters
		
		
		
}
81 多态_多态的三个必要条件

多态指的是同一个方法调用,由于对象不同可能会有不同的行为。现实生活中,同一个方法,具体实现会完全不同。 比如:同样是调用人的“休息”方法,张三是睡觉,李四是旅游,高淇老师是敲代码,数学教授是做数学题; 同样是调用人“吃饭”的方法,中国人用筷子吃饭,英国人用刀叉吃饭,印度人用手吃饭。

  多态的要点:

  1. 多态是方法的多态,不是属性的多态(多态与属性无关)。

  2. 多态的存在要有3个必要条件:继承,方法重写,父类引用指向子类对象。

  3. 父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了。
package cn.sxt.oo2;

/**
 * 测试多态
 * @author 高淇
 *
 */
public class TestPolym {
	public static void main(String[] args) {
		Animal   a = new Animal();
		animalCry(a); 
		
		Animal  d = new Dog();			//自动向上转型
		animalCry(d);
		Animal   c = new Cat();
		animalCry(new Cat());
		
		Dog  d2 = (Dog) d;			//强制向下转型
		d2.seeDoor();
//		Dog   d3 = (Dog) c;
//		d3.seeDoor();
		
		
	}
	
	static  void  animalCry(Animal  a){  //静态方法
		a.shout();
	}
	
	/*static  void  animalCry(Dog  a){
		a.shout();
	}
	static  void  animalCry(Cat  a){
		a.shout();
	}*/
	
}

  class  Animal {
	
    public    void shout() {
        System.out.println("叫了一声!");
    }
}
class Dog extends Animal {  //条件:1:继承
    public void shout() {   //条件2:方法重写
        System.out.println("旺旺旺!");
    }
    
    public  void   seeDoor(){
    	System.out.println("看门!!!");   
    }
    
}
class Cat extends Animal {
    public void shout() {
        System.out.println("喵喵喵喵!");
    }
}
82 对象的转型_ClassCastException处理

对象转型原则:向上自动转型、向下强制转型。

ClassCastException:类型转化异常,属于常见异常的一种。

	
		Animal  d = new Dog();			//自动向上转型
		animalCry(d);
		Animal   c = new Cat();
		animalCry(new Cat());
		
		Dog  d2 = (Dog) d;			//强制向下转型
		d2.seeDoor();
		
	  Dog   d3 = (Dog) c; 
	   //未报错,但这里c本质上还是个Cat,系统默认为animal进行了强制转型
	  d3.seeDoor();
	  //依然未报错,但不能正确执行

上面这种情况编译正确但运行错误,是异常的一种:ClassCastException。如下图:
在这里插入图片描述
知道了这种异常的原因,就要注意避免这种异常。

83 final修饰变量、方法和类

在这里插入图片描述

84 数组的使用

数组是相同类型数据的有序集合。数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。其中,每一个数据称作一个元素,每个元素可以通过一个索引(下标)来访问它们。数组的三个基本特点:

  1. 长度是确定的。数组一旦被创建,它的大小就是不可以改变的。

  2. 其元素必须是相同类型,不允许出现混合类型。

  3. 数组类型可以是任何数据类型,包括基本类型和引用类型。

数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中存储的。

在这里插入图片描述

注意事项

  1. 声明的时候并没有实例化任何对象,只有在实例化数组对象时,JVM才分配空间,这时才与长度有关。

  2. 声明一个数组的时候并没有数组真正被创建。

  3. 构造一个数组,必须指定长度。
package cn.sxt.arrays;

public class Test01 {
	public static void main(String[] args) {
		int[]  arr01 = new int[10] ;			//索引下标[0, length-1]:0,1,2,3,4,5,6,7,8,9 
		String   arr02[] = new  String[5];

		arr01[0] = 13;
		arr01[1] = 15;
		arr01[2]  = 20;
//		arr01[10] = 100;    // java.lang.ArrayIndexOutOfBoundsException
		
		//通过循环初始化数组
		for(int i=0;i<arr01.length;i++){
			 arr01[i] = 10*i;
		}
		//通过循环读取数组里面元素的值
		for(int i=0;i<arr01.length;i++){
			 System.out.println(arr01[i]);
		}
		
		User[]   arr03 = new User[3];
		arr03[0] = new User(1001,"高淇");  //对象数组里面存的是引用类型,即每个对象的地址,而非直接存储对象
		arr03[1] = new User(1002,"高二淇");
		arr03[2] = new User(1003,"高三淇");
		
		for(int i=0;i<arr03.length;i++){
			System.out.println(arr03[i].getName());
		}
		
	}
	class  User {
		private  int  id;
		private  String   name;
	
	
		public User(int id, String name) {
			super();
			this.id = id;
			this.name = name;
		}	
	
	
		public int getId() {
		return id;
		}
		public void setId(int id) {
			this.id = id;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
	
	}
		
}
85 数组的初始化

数组的初始化方式总共有三种:静态初始化、动态初始化、默认初始化。

在这里插入图片描述

在这里插入图片描述

86 数组的遍历_for each循环

在这里插入图片描述

for each是用来循环读取数组元素值的一种用法。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值