一.设计对象并使用
1.类和对象
类:是对象共同特征的描述,抽象的 对象:是真实存在的具体的东西,具体的 比如:学生和小明 在Java中必须先设计类,才能获得对象
定义类:public class 类名 {1.成员变量(属性)2.成员方法(行为)3.构造器 4.代码块 5.内部类}
完整的格式: [public] [abstract] [final] class ClassName [extends SuperName] [implements InterfaceNameList]
类的成员:成员变量和成员方法,构造方法不是类的方法,所以不称为类的成员;类的成员变量可以是基本类型的数据或者数组,也可以是一个类的实例。
对象:类名 对象名 = new 类名(); 访问对象的属性:对象名.成员变量 访问行为:对象名.方法名()
public class phone{
//属性
String brand;
double price;
//方法
public void call(){
System.out.println("打电话");
}
public void playgame(){
System.out.println("玩游戏");
}
}
public class phonetest {
public static void main(String[] args){
//创建手机对象
phone p = new phone();
//给手机赋值
p.brand = "小米";
p.price = 3999.95;
//获取手机对象的值
System.out.println(p.brand);
System.out.println(p.price);
//调用手机中的方法
p.call();
p.playgame();
}
}
创建一个对象分为两个步骤:声明对象变量和对象的实例化;
声明对象:变量并没有创建对象,系统只是为其分配一个引用空间;
对象的实例化:通过new关键字进行对象的实例化 实例化过程:为对象分配空间 执行构造方法完成初始化 返回对象的引用
a.为对象分配内存空间,并对成员变量进行初始化,数值型类型初值为0,逻辑型为false
b.执行显示初始化 执行类成员声明时带有的简单赋值表达式
c.执行构造方法,进行对象的初始化
注意事项:a.类的首字母建议大写,类名需要见名知意,驼峰模式;
b.一个Java文件中可以定义多个class类,且只能有一个类是public修饰的,而且public修饰的类名必须是代码文件,实际开发中还是一个文件定义一个类;
c.成员变量的完整定义格式:修饰符 数据类型 变量名称 = 初始化值,一般无需指定初始化值,存在默认值(基本数据类型默认值是0/0.0/false,引用数据类型的默认值是null)
2.成员方法
方法调用中参数传递的方式:
Java中方法调用的参数传递的方式是传值,即方法调用不会改变调用程序中作为方法参数的变量的值。但是,当方法的参数类型是对象或者数组时候,在方法调用中传递给该参数的仍然是调用程序中对应变量的值,但是如果对该参数进行了修改(如修改成员变量的值),这种修改时永久的
p77-p79
可变参数列表:
定义格式一般为:类型...参数名 int...nums 表示存放在nums中的类型为int的一组参数
可变参数类型只能做为方法参数列表中的最后一个参数
二.封装——对象代表什么,就得封装对应的数据,并且提供数据对应的行为
封装告诉我们拿到一个需求之后,如何正确设计对象的属性和方法
1.private 权限修饰符——保证数据的安全性
a.可以修饰类的成员变量和成员方法,被private修饰的成员只能在本类中才能被访问;
b.用private实现对非法数据的过滤:针对每一个私有化的变量成员,都为其提供一个get和set的方法,set方法给成员变量赋值(不需要返回值,需要形参),get方法对外提供成员变量的值(需要返回值,返回值类型与成员类型一致,不需要形参)
public class phone{
private String brand;
private double price;
public void setBrand(String b){
brand=b;
}//给外界的对象进行赋值的,所以需要形参,不需要返回值
public String getBrand(){
return brand;
}//对外提供brand属性的
public void setPrice(double p){
if (p >=1000 && p<=3000){
price = p;
}else{
System.out.println("非法参数");
}
}
//只有满足在1000-3000的范围内,才会被赋值
public double getPrice(){
return price;
}
public void call(){
System.out.println("打电话");
}
public void playgame(){
System.out.println("玩游戏");
}
}
public class phonetest {
public static void main(String[] args){
//创建手机对象
phone p = new phone();
//给手机赋值
// p.brand = "小米";
// p.price = 3999.95;
p.setBrand("红米");
p.setPrice(3000000); //输出 非法参数
//获取手机对象的值
System.out.println(p.getBrand());//输出 红米
System.out.println(p.getPrice());//输出 0.0
System.out.println("__________________");
//调用手机中的方法
p.call();
p.playgame();
}
}
三.this关键字——作用是区分成员变量和局部变量
1.成员变量和局部变量(方法里面的变量)
当成员变量和局部变量同名的时候,采用就近原则;在方法中,如果想用成员变量就用this.变量名;
public class phone{
private String brand;
private double price;
public void setBrand(String brand){
//等号的右边 局部原则 表示的是测试类中调用方法传递过来的数据 "红米"
//等号的左边 表示成员位置的name
this.brand=brand;
}
public String getBrand(){
return brand;
}
public void setPrice(double price){
if (price >=1000 && price<=3000){
this.price = price;
}else{
System.out.println("非法参数");
}
}
public double getPrice(){
return price;
}
}
四.构造方法
对象都有构造方法 如果没有,编译器加一个构造方法(如果有系统就不会添加无参构造) 抽象类(不能new创建实例 但是也有构造方法)
构造方法也叫构造器,构造函数,作用是在创建对象的时候给成员变量进行赋值的,初始化
1.构造方法的格式
修饰符 类名(参数){方法体}
权限修饰符为public:表示任何类都能创建这个类的实例对象
protected:表示只有这个类的子类或者在同一个包中的类能够创建实例对象
default:只有与该类在同一个包中的类可以创建这个类的实例对象
private:没有其他类可以实例化该类
在构造方法里面可以调用本类或者父类的构造方法,this调用本类的其他构造方法;super调用直接父类的构造方法(this和super要放在第一条语句 而且只能有一条)
2.注意事项
a.方法名与类名相同,大小写也要一致
b.没有返回值类型,连void也没有
c.没有具体的返回值(不能由return带回结果数据)
d.创建对象的时候由虚拟机调用,不能手动调用构造方法;每创建一次对象,就会调用一次构造方法
3.无参构造和带参构造
如果在类中没有定义构造方法,系统将给出一个默认的无参构造方法;如果定义了构造方法,系统将不再提供默认的构造方法,在实际开发中,最好写上无参构造和带全部参数的构造方法
a.无参构造:初始化对象的时候,成员变量的数据均采用默认值; 给成员赋值的话,就用set方法 数值型: 0 | boolen型:false | char:'\0' |对象:null
b.带参构造:初始化对象的时候,同时可以为对象进行赋值
public class phone{
private String brand;
private double price;
//空参构造
public phone(){
System.out.println("执行");
}
//带参数的构造
public phone(String brand,double price){
this.brand = brand;
this.price = price;
}
public void setBrand(String brand){
this.brand=brand;
}
public String getBrand(){
return brand;
}
public void setPrice(double price){
if (price >=1000 && price<=3000){
this.price = price;
}else{
System.out.println("非法参数");
}
}
public double getPrice(){
return price;
}
}
public class phonetest {
public static void main(String[] args){
//创建手机对象
//调用的空参构造
phone p = new phone();
//调用空参构造,如果想要赋值的话,就用setBrand,setPrice
p.setBrand("红米");
p.setPrice(2400);
//带参构造
phone p1 = new phone("小米",2300);
//获取
System.out.println(p.getBrand());//输出红米
System.out.println(p.getPrice());//输出2400
System.out.println(p1.getBrand());//输出小米
System.out.println(p1.getPrice());//输出2300
}
}
4.重载构造方法
为了使用方便,可以对一个类定义多个构造方法,这些构造方法都有相同名称(类名),方法的参数不同(参数类型或参数个数不一样),称之为构造方法的重载
一个构造方法可以通过this关键字调用另外一个重载的构造方法
实例化时传入的参数不同,使用不同的构造方法
p85 重载构造方法的目的是使类对象有不同的初始值,为类对象的初始化提供方便
package jichuTest;
class Person
{
String name;
int age;
Person(){}
Person( String name, int age ){
this.name=name; this.age=age;
System.out.println("In Person(String,int)");
}
}
class Student extends Person
{
String school;
Student(){
this( null, 0, null );
System.out.println("In Student()");
}
Student( String name, int age, String school ){
super( name, age );
this.school = school;
System.out.println("In Student(String,int,String)");
}
}
class Graduate extends Student
{
String teacher="";
Graduate(){
//super(); 不写这句话 会自动调用父类的无参构造
System.out.println("In Graduate()");
}
}
//一层一层调用 最终会调用到object
//In Person(String,int)
//In Student(String,int,String)
//In Student()
//In Graduate()
6.构造方法的执行过程
先调用本类或父类的构造方法,直到最高一层object;再按声明顺序执行字段初始化赋值;执行构造函数中的各语句 尽量在构造器中不要调用任何方法,可能还没有赋值 唯一能够安全调用的就是带有final属性的方法
package jichuTest;
class ConstructSequence {
public static void main(String[] args) {
Student p = new Student("2222", 18, "信息工程");
}
}
class Person {
String name = "111"; //step 2
int age = 1;
Person(String name, int age) {
// Java中Object类是所有类的父类,调用super()在这里是隐式的,指向Object的构造器
super(); // 这行可以省略,因为Object()是默认调用的 //step 1
//step 3
// 输出调用Person构造器前的状态
System.out.println("调用Person构造器前,此时this.name=" + this.name + ", this.age=" + this.age);
// 调用构造器后重新赋值
this.name = name;
this.age = age;
// 输出调用Person构造器后的状态
System.out.println("Person构造器调用后,此时this.name=" + this.name + ", this.age=" + this.age);
}
}
class Student extends Person {
String school = "未知学校"; //step2
Student(String name, int age, String school) {
// 调用父类Person的构造器
super(name, age);//step 1
//step3
// 输出调用Student构造器前的状态
System.out.println("调用Student构造器前,此时this.name=" + this.name + ", this.age=" + this.age + ", this.school=" + this.school);
// 调用构造器后重新赋值school
this.school = school;
// 输出调用Student构造器后的状态
System.out.println("Student构造器调用后,此时this.name=" + this.name + ", this.age=" + this.age + ", this.school=" + this.school);
}
}
//调用Person构造器前,此时this.name=111, this.age=1
//Person构造器调用后,此时this.name=2222, this.age=18
//调用Student构造器前,此时this.name=2222, this.age=18, this.school=未知学校
//Student构造器调用后,此时this.name=2222, this.age=18, this.school=信息工程
五.标准的javaBean类
要求:1.类名需要见名知意 2.成员变量使用private修饰 3.至少提供两个构造方法(无参构造,带全部参数的构造) 4.成员方法(提供每一个成员变量对应的set()/get())
安装插件ptg一键生成
六.对象内存图
1.方法区:字节码文件加载时进入的内存;栈:方法运行时所进入的内存,变量也是在这里; 堆:new出来的东西会在这块内存中开辟空间并且产生新的地址;
2.一个对象的内存图
student s = new student();
a.加载class文件到方法区 b.声明局部变量 c.在堆内存中开辟一个空间 4.默认初始化 5.显示初始化 6.构造方法初始化
3.两个引用指向同一个对象
4.this的内存原理
this的本质:代表方法调用者的地址值
七.对象清除与垃圾回收
对象的自动清除叫做垃圾回收 对象是由Java虚拟机的垃圾回收线程来完成的
垃圾收集器的对象是被确认不存在任何引用的对象,一个变量保存的引用在改变量的作用域内有效,在变量的作用域外,引用将不存在,也可以显示的删除一个对象的引用,方法是将该引用型变量的值赋为null;
对象的最终化处理:
只有经过最终化处理的对象,才意味着被废弃
t ry-with-resources: