面向过程和面向对象的区别
OOA:面向对象分析
OOD:面向对象设计
对象是什么_对象和数据管理
对象在内存中是一个内存块,用来表示一堆相关联的数据(属性和方法)
- 数据无管理时代
- 数组管理和企业部门制
- 对象和企业项目制
对象和类的关系_属性_成员变量_方法
类:对象的模板,或者称为图纸
类:我们叫做class。对象:我们叫做object,instance(实例),以后我们说某个类的对象,某个类的实例,是一样的意思。
/**
* 简单的学生类编写
* @author PengHao
*
*/
public class Student {
//属性field,或者叫成员变量
int id;
String name;
int age;
Computer comp;
//方法
void study() {
System.out.println("我在认真学习,使用的电脑是:"+comp.brand);
}
void play() {
System.out.println("我正在玩游戏");
}
//构造方法:用于创建这个类的对象,无参的构造方法可以由系统自动创建。
Student(){
}
//main方法是程序执行的入口,必须要有
public static void main(String[] args) {
Student st = new Student();
st.id = 1001;
st.name = "penghao";
st.age = 23;
Computer c1 = new Computer();
c1.brand = "联想";
st.comp = c1;
st.study();
st.play();
}
}
class Computer{
String brand;
}
内存分析
Java虚拟机的内存可以分为三个区域:栈Stack、堆heap、方法区method area.
栈的特点
- 栈描述的是方法执行的内存模型,每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)。
- JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)。
- 栈属于线程私有,不能实现线程间共享。
- 栈的存储特性是“先进后出,后进先出”。
- 栈是有系统自动分配,速度快!栈是一个连续的存储空间。
堆的特点
- 堆用于存储创建好的对象和数组(数组也是对象)。
- JVM只有一个堆,被所有线程共享。
- 堆是一个不连续的内存空间,分配灵活,速度慢。
方法区(又叫静态区)特点如下:
- JVM只有一个方法区,被所有线程所共享。
- 方法区实际上也是堆,只是用于存储类、常量相关的信息!
- 用来存放程序中永远不变或唯一的内容。(类信息【Class对象】、静态变量、字符串常量等)。
构造方法
构造器也叫构造方法(constructor),用于对象的初始化
要点
- 通过new关键字调用。
- 构造器虽然有返回值,但是不能定义返回值类型(返回值的类型肯定是本类),不能在构造器里使用return返回某个值。
- 如果我们没有定义构造器,则编译器会自动定义一个无参的构造函数,如果已定义,则编译器不会自动添加。
- 构造器方法名必须和类名一致。
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;
String name;
String pwd;
public User() {
}
public User(int id,String name) {
super(); //构造方法的第一句总是super();
this.id = id;
this.name = name;
}
public User(int id,String name,String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public static void main(String[] args) {
User u1 = new User();
User u2 = new User(101,"小张");
User u3 = new User(102,"小李","123456");
}
}
垃圾回收机制
内存管理
- Java的内存管理很大程度指的就是对象的管理,其中包括对象空间的分配和释放。
- 对象空间的分配:使用new关键字创建对象即可。
- 对象空间的释放:讲对象赋值null即可。垃圾回收器将负责回收所有“不可达”对象的内存空间。
任何一种垃圾回收算法一般要做两件事情:
- 发现无用的对象。
- 回收无用对象占用的内存空间
相关算法:
3. 引用计数法
4. 引用可达法(根搜索算法)
通用的分代垃圾回收机制
JVM调优和FULL
开发中容易造成内存泄漏的操作
This的本质_对象创建过程的四步
创建一个对象分为四步:
- 分配对象空间,并将对象成员变量初始化为0或空
- 执行属性值的显示初始化
- 执行构造方法
- 返回对象的地址给相关变量
This的本质
- this的本质就是“创建好的对象的地址!”
- 由于在构造方法调用前,对象已经创建,因此,在构造方法中也可以使用this代表当前对象
This的使用
- this可以调用重载的构造器,必须位于构造方法第一句
- this不能用于static方法中
static关键字
/**
* 测试static关键字的用法
* @author PengHao
*
*/
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,"Penghao");
User2.printCompany();
User2.company = "阿里巴巴";
User2.printCompany();
}
}
内存分析
有汽车一定有图纸,有图纸不一定有汽车
静态初始化块
构造方法用于对象的初始化,静态初始化块,用于类的初始化,在静态初始化块中不能直接访问非static成员
注意事项
静态初始化块执行顺序
- 上溯到Object类,先执行Object的静态初始化块,再向下执行子类的静态初始化块,直到我们的类的静态初始化块为止。
- 构造方法执行顺序和上面顺序一样。
/**
* 测试静态初始化块的使用
* @author PengHao
*
*/
public class User3 {
int id;
String name;
String pwd;
static String company;
static {
System.out.println("执行类的初始化工作!");
company = "京东";
printCompany();
}
public static void printCompany() {
System.out.println(company);
}
public static void main(String[] args) {
User3 u3 = null;
}
}
参数传值机制
Java中,方法中所有参数都是“值传递”,也就是“传递的是值的副本”
public class User4 {
int 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.testParameterTransfer02(u1);
System.out.println(u1.name);//高小八
}
}
包
我们通过package实现对类的管理,package的使用有两个要点:
- 通常是类的第一句非注释性语句。
- 包名:域名倒着写即可,再加上模块名,便于内部管理类。
JDK中的主要包
Java中的常用包 | 说明 |
---|---|
java.lang | 包含一些Java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能。 |
java.awt | 包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。 |
java.net | 包含执行与网络相关的操作的类。 |
java.io | 包含能提供多种输入/输出功能的类。 |
java.util | 包含一些实用工具类,如定义系统特性、使用与日期日历相关的函数。 |
导入类import
要点:
- Java会默认导入java.lang包下所有的类,因此这些类我们可以直接使用。
- 如果导入两个同名的类,只能用包名+类名来显示调用相关类
静态导入
静态导入(static import)是在JDK1.5新增加的功能,其作用是用于导入指定类的静态属性,这样我们可以直接使用静态属性
package cn.sxt;
//以下两种静态导入的方式二选一即可
import static java.lang.Math.*;//导入Math类的所有静态属性
import static java.lang.Math.PI;//导入Math类的PI属性
public class Test2{
public static void main(String [] args){
System.out.println(PI);
System.out.println(random());
}
}
继承的实现extends
子类是父类的扩展
instanceof是二元运算符,左边是对象,右边是类;当对象是右面类或子类所创建对象时,返回true;否则,返回false。
- 父类也称作超类、基类、派生类等。
- Java中只有单继承,没有像C++那样的多继承。多继承会引起混乱,使得继承链过于复杂,系统难于维护。
- Java中类没有多继承,接口有多继承。
- 子类继承父类,可以得到父类的全部属性和方法 (除了父类的构造方法),但不见得可以直接访问(比如,父类私有的属性和方法)。
- 如果定义一个类时,没有调用extends,则它的父类是:java.lang.Object。
package cn.java.oo2;
public class TestExtends {
public static void main(String[] args) {
Student stu = new Student();
stu.name = "penghao";
stu.height = 173;
stu.rest();
Student stu2 = new Student("penghao",173,"计算机");
System.out.println(stu2 instanceof Student);
System.out.println(stu2 instanceof Person);
System.out.println(stu2 instanceof Object);
System.out.println(new Person() instanceof Student);
}
}
class Person{
String name;
int height;
public void rest() {
System.out.println("休息一会");
}
}
class Student extends Person{
String major;
public void study() {
System.out.println("学习两小时");
}
public Student() {
}
public Student(String name,int height,String major) {
this.name = name;
this.height = height;
this.major = major;
}
}
继承方法的重写
要点:
- “==”: 方法名、形参列表相同。
- “≤”:返回值类型和声明异常类型,子类小于等于父类。
- “≥”: 访问权限,子类大于等于父类。
package cn.java.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();
}
}
重写toString方法
package cn.java.oo2;
public class TestObject {
public static void main(String[] args) {
Person2 p = new Person2("penghao",23);
System.out.println(p);
}
}
class Person2{
String name;
int age;
public String toString(){
return name + "年龄: " + age;
}
public Person2(String name,int age) {
this.name = name;
this.age = age;
}
}
==和equals方法
==”代表比较双方是否相同。如果是基本类型则表示值相等,如果是引用类型则表示地址相等即是同一个对象。
JDK提供的一些类,如String、Date、包装类等,重写了Object的equals方法,调用这些类的equals方法, x.equals (y) ,当x和y所引用的对象是同一类对象且属性内容相等时(并不一定是相同对象),返回 true 否则返回 false。
package cn.java.oo2;
public class TestEquals {
public static void main(String[] args) {
User u1 = new User(1000,"xiaozhang",123456);
User u2 = new User(1000,"xiaoli",123456);
System.out.println(u1==u2);
System.out.println(u1.equals(u2));
String s1 = new String("penghao");
String s2 = new String("penghao");
System.out.println(s1==s2);
System.out.println(s1.equals(s2));
}
}
class User{
int id;
String name;
int pwd;
public User(int id, String name, int pwd) {
super();
this.id = id;
this.name = name;
this.pwd = pwd;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (id != other.id)
return false;
return true;
}
}
super关键字
若是构造方法的第一行代码没有显式的调用super(…)或者this(…);那么Java默认都会调用super(),含义是调用父类的无参数构造方法。这里的super()可以省略。
package cn.java.oo2;
public class TestSuper {
public static void main(String[] args) {
new ChildClass().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,然后再依次向下执行类的初始化块和构造方法,直到当前子类为止。
注:静态初始化块调用顺序,与构造方法调用顺序一样,不再重复。
package cn.java.oo2;
public class TestSuper02 {
public static void main(String[] args) {
System.out.println("开始创建一个ChildClass对象……");
new ChildClass2();
}
}
class FatherClass2{
public FatherClass2() {
System.out.println("创建FatherClass");
}
}
class ChildClass2 extends FatherClass2{
public ChildClass2() {
System.out.println("创建ChildClass");
}
}
封装的实现
- private 表示私有,只有自己类能访问
- default表示没有修饰符修饰,只有同一个包的类能访问
- protected表示可以被同一个包的类以及其他包中的子类访问
- public表示可以被该项目的所有包中的所有类访问
类的属性的处理
- 一般使用private访问权限
- 提供相应的get/set方法来访问相关属性,这些方法通常是public修饰的,以提供对属性的赋值与读取操作(注意:boolean变量的get方法是is开头!)。
- 一些只用于本类的辅助性方法可以用private修饰,希望其他类调用的方法用public修饰。.
package cn.java.oo2;
public class Person4 {
private int age;
private String name;
private boolean man;
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 boolean isMan() {
return man;
}
public void setMan(boolean man) {
this.man = man;
}
}
多态_对象的转型
要点:
- 多态是方法的多态,不是属性的多态(多态与属性无关)。
- 多态的存在要有3个必要条件:继承,方法重写,父类引用指向子类对象。
- 父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了。
package cn.java.oo2;
public class TestPolym {
public static void main(String[] args) {
Animal a1 = new Animal();
Animal d1 = new Dog(); //自动向上转型
Animal c1 = new Cat();
a1.shout();
d1.shout();
c1.shout();
Dog d = (Dog)d1;
d.seeDoor();
/*//异常
Dog c = (Dog)c1;
c.seeDoor();
*/
Dog d2 = (Dog)d1; //强制向下转型
}
static void animalCry(Animal a) {
a.shout();
}
}
class Animal{
public void shout() {
System.out.println("叫了一声");
}
}
class Dog extends Animal{
public void shout() {
System.out.println("汪汪汪");
}
public void seeDoor() {
System.out.println("看门");
}
}
class Cat extends Animal{
public void shout() {
System.out.println("喵喵喵");
}
}
final关键字的作用
- 修饰变量: 被他修饰的变量不可改变。一旦赋了初值,就不能被重新赋值。
- 修饰方法:该方法不可被子类重写。但是可以被重载!
- 修饰类: 修饰的类不能被继承。比如:Math、String等。