Java 入门(三)——面向对象

总结
对象说白了也是一种数据结构(对数据的管理模式),将数据和数据的行为放到了一起。
在内存上,对象就是一个内存块,存放了相关的数据集合!
对象的本质就一种数据的组织方式!

类方法即静态方法,实例方法即普通非静态方法,静态方法中调用非静态方法需要创建对象

对于一个类来说,一般有三种常见的成员:属性field、方法method、构造器constructor。

1. 对象和类的概念

总结抽象,便于认识未知事物!总结的过程就是抽象的过程。
对象是具体的事物,类就是对象的抽象。描述对象的特征和行为。
类可以看成一类对象的模板,对象可以看成该类的一个具体实例。
类是用于描述同一类型的对象的一个抽象概念,类中定义了这一类对象所应具有的共同的属性、方法。

2. 类的定义,属性,方法
属性:

属性用于定义该类或该类对象包含的数据或者说是静态特征
属性作用域是整个类体。

方法:

方法用于定义该类或者该类实例的行为特征或者功能实现。
方法是类和对象行为特征的抽象。
面向对象中,整个程序的基本单位是类,方法是从属于类和对象的。

public class SxtStu {
    //属性(成员变量)
    int id;
    String sname;
    int age;  
    //方法
    void study(){
        System.out.println("我正在学习!");
    }  
    //构造方法
   SxtStu(){
   }
}
/**
 * 
 * @author 孔阳
 *
 */

class Computer{
	String brand;//电脑品牌
}

public class ZkyStu{
	//属性field
	int id;
	String sname;
	int age;
	Computer comp;
	
	//方法
	void study() {
		System.out.println("正在玩电脑:"+comp.brand);
	}
	
	//构造方法, 用于创建这个类的对象,无参的构造方法可以由系统自动创建
	ZkyStu(){
		
	}
	
	public static void main(String[] args) {
		ZkyStu stu = new ZkyStu();//创建一个对象
		stu.id = 1001;
		stu.sname = "孔阳";
		stu.age = 24;
		
		Computer c1 = new Computer();
		c1.brand = "联想";
		
		stu.comp = c1;
		
		stu.study();
	}
	
}
3. 内存分析

Java虚拟机的内存可以分为三个区域:栈stack、堆heap、方法区method area(其实也在堆上,比较特殊单独说)。

  1. 栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)

  2. JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)

  3. 栈属于线程私有,不能实现线程间的共享!

  4. 栈的存储特性是“先进后出,后进先出”

  5. 栈是由系统自动分配,速度快!栈是一个连续的内存空间!

  1. 堆用于存储创建好的对象和数组(数组也是对象)

  2. JVM只有一个堆,被所有线程共享

  3. 堆是一个不连续的内存空间,分配灵活,速度慢!

方法区(又叫静态区)
  1. JVM只有一个方法区,被所有线程共享!

  2. 方法区实际也是堆,只是用于存储类、常量相关的信息

  3. 用来存放程序中永远是不变或唯一的内容。(类信息【Class对象】、静态变量、字符串常量等)

在这里插入图片描述

3. 构造方法与构造方法的重载
  1. 构造器也叫构造方法(constructor),用于对象的初始化。

  2. 构造器的名称应与类的名称一致。

  3. Java通过new关键字来调用构造器,从而返回该类的实例,是一种特殊的方法。

  4. 不能在构造器里使用return返回某个值,不能定义返回值类型(返回值的类型肯定是本类)。

  5. 如果我们没有定义构造器,则编译器会自动定义一个无参的构造函数。如果已定义则编译器不会自动添加!

构造方法的重载

构造方法的重载;多种初始化方法,但是同名,自适应
如果方法构造中形参名与属性名相同时,需要使用this关键字区分属性与形参。
this.id 表示属性id;id表示形参id

//构造方法的重载
class User {
	//属性
	int id;
	String name;
	String pwd;
	
	public User() {
		
	}
	
	public User(int id, String name) {
		super();
		this.id = id;//this关键字表示创建好的变量,this.id表成员变量,id表方法内的局部变量
		this.name = name;//this区分成员变量与局部变量
	}
	
	public User(int id, String name, String pwd) {
		this.id = id;
		this.name = name;
		this.pwd = pwd;
	}
	
	
}
/**
		User u1 = new User();
        User u2 = new User(101, "孔阳");
        User u3 = new User(101, "孔阳", "1234567s");
        */
4. 垃圾回收机制(Garbage Collection)

内存管理全部交给Java的垃圾回收,不用程序员考虑内存管理,内存释放问题;

内存管理

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

对象空间的分配:使用new关键字创建对象即可

对象空间的释放:将对象赋值null即可。垃圾回收器将负责回收所有”不可达”对象的内存空间。

垃圾回收过程

1. 发现无用的对象

2. 回收无用对象占用的内存空间。
Java的垃圾回收器通过相关算法发现无用对象,并进行清除和整理。

  1. 引用计数法
  2. 引用可达法(根搜索算法)
分代垃圾回收机制

分代垃圾回收机制,是基于这样一个事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的回收算法,以便提高回收效率。我们将对象分为三种状态:年轻代、年老代、持久代JVM将堆内存划分为 Eden、Survivor 和 Tenured/Old 空间。

**1 年轻代:**年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象,对应的是Minor GC

**2 年老代:**在年轻代中经历了N(默认15)次垃圾回收后仍然存活的对象,就会被放到年老代中。

**3 持久代:**用于存放静态文件,如Java类、方法等。持久代对垃圾回收没有显著影响。

通用的分代垃圾回收机制

JVM调优和Full GC(全量垃圾回收)

在对JVM调优的过程中,很大一部分工作就是对于Full GC的调节。有如下原因可能导致Full GC:

1.年老代(Tenured)被写满

2.持久代(Perm)被写满

3.System.gc()被显式调用(程序建议GC启动,不是调用GC)

4.上一次GC之后Heap的各域分配策略动态变化

开发中容易造成内存泄露的操作

1 创建大量无用对象

2 静态集合类的使用
像HashMap、Vector、List等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,所有的对象Object也不能被释放。

3 各种连接对象(IO流对象、数据库连接对象、网络连接对象)未关闭

4 监听器的使用

finalize方法,是Java提供给程序员用来释放对象或资源的方法,但是尽量少用。

4. this关键字

this的本质就是“创建好的对象的地址”,由于在构造方法调用前,对象已经创建。因此,在构造方法中也可以使用this代表“当前对象” 。

创建一个对象分为如下四步:
  1. 分配对象空间,并将对象成员变量初始化为0或空

  2. 执行属性值的显式初始化

  3. 执行构造方法

  4. 返回对象的地址给相关的变量

this最常的用法:
  1. 在程序中产生二义性之处,应使用this来指明当前对象;**普通方法中,this总是指向调用该方法的对象。**构造方法中,this总是指向正要初始化的对象。

  2. 使用this关键字调用重载的构造方法,避免相同的初始化代码。但只能在构造方法中用,并且必须位于构造方法的第一句。

  3. this不能用于static方法中。
    因为this指的是当前对象,所有静态变量和对象都在类信息里(方法区)从属于类,在这里this找不到对象,这里只有类信息,没有对象????


public class TestThis1 {
	
	int a,b,c;
	
	TestThis1(){
		System.out.println("正要初始化一个对象:");
	}

	TestThis1(int a, int b){
		this();//调用无参的构造方法,且必须在第一行
		this.a = a;
		this.b = b;
	}
	
	TestThis1(int a, int b, int c){
		this(a,b);//调用带参的构造方法,必须在第一行
		this.c = c;
	}
	
	void sing() {
		System.out.println("唱歌了。");
	}
	
	void eat() {
		this.sing();
		System.out.println("回家吃饭了。");
	}
	
	public static void main(String[] args) {
		TestThis1 hi = new TestThis1(2, 3);//调用无参构造器与双参构造器初始化对象
		hi.eat();//调用了sing()和eat()方法
		System.out.println(hi.a+" "+hi.b);//输出对象的属性
	}
}

/**
正要初始化一个对象:
唱歌了。
回家吃饭了。
2 3
*/
5. static关键字

静态变量,静态方法从属于类(成员变量的)or 对象(普通变量的)
在类中,**用static声明的成员变量为静态成员变量,也称为类变量。**类变量的生命周期和类相同,在整个应用程序执行期间都有效。在static方法中不可直接访问非static的成员。

public class TestStatic {
	//属性
    int id; // id
    String name; // 账户名
    String pwd; // 密码
     
    static String company = "北京尚学堂"; // 公司名称
    
    // 方法
    //构造方法
    public TestStatic(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) {
    	TestStatic u = new TestStatic(101, "高小七");
    	TestStatic.printCompany();//输出北京尚学堂
    	u.company = "阿里";
    	u.printCompany();//输出阿里
    	u.login();//输出2次公司名与用户名

    }
}
/**
北京尚学堂
阿里
阿里
公司名: 阿里
登录: 高小七
*/

6. 静态初始化块:类的初始化操作

构造方法用于对象的初始化!静态初始化块,用于类的初始化操作!
在静态初始化块中不能直接访问非static成员

静态初始化块执行顺序(学完继承再看这里):

1. 上溯到Object类,先执行Object的静态初始化块,再向下执行子类的静态初始化块,直到我们的类的静态初始化块为止。

2. 构造方法执行顺序和上面顺序一样!!

/**
 * 静态初始化块:给类初始化
 * @author 孔阳
 *
 */
public class TestStatic1 {
	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) {
		TestStatic1 u = new TestStatic1();
		//创建一个对象,就会调用静态初始化块
	}
}
/**
执行类的初始化工作....
公司名: 中国银行
*/
7. 参数传值机制

Java中,方法中所有参数都是“值传递”,也就是“传递的是值的副本”。

基本数据类型参数的传值

传递的是值的副本。 副本改变不会影响原件。

引用类型参数的传值

传递的是值的副本。但是引用类型指的是“对象的地址”。因此,副本和原参数都指向了同一个“地址”,改变“副本指向地址对象的值,也意味着原参数指向对象的值也发生了改变”。

8. 包 package

在自己创建的包里产生新的类:

package cn.zky.oo;

public class MyHi {
	public static void main(String[] args) {
	        System.out.println("helloworld");
	    }
}
9. JDK中的主要包
java.lang: 包含一些Java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能。
java.io:包含能提供多种输入/输出功能的类。
java.util:包含一些实用工具类,如定义系统特性、使用与日期日历相关的函数。
java.net:包含执行与网络相关的操作的类。
java.awt:包含了构成抽象窗口工具集(abstract window toolkits)的多个类
10. 导入类import
11. 静态导入

作用是用于导入指定类的静态属性,这样我们可以直接使用静态属性。

//普通import用法
import java.sql.Date;
import java.util.*;//导入该包下所有的类。会降低编译速度,但不会降低运行速度。
 
//以下两种静态导入的方式二选一即可
import static java.lang.Math.*;//导入Math类的所有静态属性
import static java.lang.Math.PI;//导入Math类的PI属性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值