类:类是对现实生活中的 一类具有共同属性和行为的事物的抽象
类的特点:类是对象的数据类型
类是具有相同属性和行为的对象的集合。
属性:对象具有的各种特征,每个对象的属性都拥有特定的值。
对象的行为:对象能够执行的操作。
类与对象的关系:
简单来说,类是对象的抽象,对象是类的实体。
类的定义:类是一组成员变量和成员方法的集合,可以把类看作一个抽象的概念
类的重要性:是Java程序的基本组成单位
类的组成:属性和行为,即成员变量与成员方法 。
属性:在类中通过成员变量(类中方法外的变量)来体现;行为:在类中通过成员方法(与方法相比,去掉关键字static)来体现。
类的定义:
类的格式与成员方法的格式:
/*
类的格式:
public class 类名{
变量1的数据类型 变量1;
变量2的数据类型 变量2;
成员方法1;(暂时没有static)
格式:
修饰符 返回值类型 方法名(参数){
方法体;
}
*/
对象的定义:是该类的具体的表现,具体到一个个体。
对象的使用:
创建对象格式:类名 对象名 =new 类名();例:Data p=new Phone();
通过对象访问成员变量:对象名.变量名 例:p.sum;
通过对象访问成员方法:格式:对象名.方法名() 例:p.call()
成员变量与局部变量
成员变量是指在定义在类中方法外的变量,局部变量指的是方法中或者方法上的变量。
成员变量与局部变量的区别:
1、类中的位置不同:成员变量在类中方法外,局部变量在方法中或者方法上的变量。
2、内存的位置不同:成员变量在堆内存中,局部变量在栈内存中。
3、生命周期不同:成员变量在堆内存,随着对象的存在而存在,随着对象的消失而消失;局部变量在栈内存中,随着方法的调用而存在,随着方法的调用完毕而消失。
4、初始化值不同:成员变量在堆内存中,堆内存的数据都有默认值;而局部变在栈内存中,栈内存没有初始化值,必须先定义然后赋值最后再使用。
注意:同一文件下只能有一个类被public修饰,被修饰的那个类是要与Java文件名一致。
举例说明访问类中的成员变量与成员方法:
class Phone{
// 定义成员变量
String brand;
int price;
String color;
// 定义成员方法
public void call(String c){
System.out.println("打电话给"+c);
}
public void sendMessage(){
Syatem.out.println("发信息");
}
public void listenMusic(){
System.out.println("听音乐");
}
}
public class PhoneTest{
public static void main(String[] args){
// 根据手机类创建一个手机对象
Phone p1 = new Phone();
//未赋值的对象的成员变量的默认值
System.out.println(p1.brand); //null
System.out.println(p1.price); //0
System.out.println(p1.color); //null
// 给对象的成员变量赋值
p1.brand = "华为";
p1.price = 4999;
p1.color = "曜石黑";
System.out.println("手机的品牌是:"+p1.brand);
System.out.println("手机的价格是:"+p1.price);
System.out.println("手机的颜色是:"+p1.color);
// 通过对象调用成员方法
p1.call("雷老板"); //注意,调用对象的成员方法的时候,需要注意是否要传参!
p1.sendMessage();
p1.listenMusic();
}
}
创建两个对象,其中第二个对象指向第一个对象:
//同一个包下,类名不可重复
class Phone2{
String brand;
int price;
String color;
public void call(String s){
System.out.println("打电话给"+s);
}
public void sendMessage(){
System.out.println("发信息");
}
public void listenMusic(){
System.out.println("听音乐");
}
}
// 测试类:
public Phone2Test{
public static void main(String[] args){
// 定义第一个对象
Phone2 p2 = new Phone2();
p2.brand = "苹果";
p2.price = 4999;
p2.color = "黑色";
System.out.println(p2.brand+"---"+p2.price+"---"+p2.color);
p2.call("乔布斯");
p2.sendMessage();
p2.listenMusic();
// 定义第二个对象
Phone2 p3 = p2;
p3.brand = "华为";
p3.price = 2799;
p3.color = "白色";
System.out.println(p2.brand+"---"+p2.price+"---"+p2.color);
}
}
先创建第一个对象并对该对象的成员变量进行赋值,再创建第二个对象将第一个对象赋值给他,并且也进行赋值操作,操作完毕后,最后一行输出结果为:华为---2799---白色
原因:p2与p3指向了堆内存中同一个地址,都可以对该地址中的值进行更改。
匿名对象:没有名字的对象
匿名对象的使用场景:
1、调用方法的时候,仅仅调用一次的时候,可以使用匿名对象。
注意:当多次调用时,不适合,每次new的时候都是一个新的匿名对象。会频繁的在堆内存中开辟空间。当匿名对象使用完毕之后,无法在使用第二次,就变成了一个垃圾(当栈中没有变量引用它的时候,判定是一个垃圾),等待被垃圾回收器回收。
2、当方法的参数类型是一个类时,可以使用匿名对象调用方法。
public class Student{
private String name;
private int age;
public show(){
System.out.println("你好");
}
}
class Function(){
public void Fun(Student s){//定义一个方法,类型为引用数据类型
s,show();
}
}
class StudentTest{
public static void main(String[] args) {
/* 原来的写法为:
Function f = new Function();
Student a = new Student();
f.Fun(a);
*/
//匿名对象的格式就是将两个创建对象的表达式右边部分直接用
new Function.Fun(new Student());
}
}
面向对象的概述:
面向对象是基于面向过程的编程思想
面向对象的特点:1、是一种更符合我们思想习惯的思想;2、可以将复杂的事情简单化;3、将我们从执行者变成了指挥者,角色发生了转换。
面向对象的三大特征:封装,继承,多态
封装:隐藏类的属性及相关描述信息,仅提供公共get()和set()方法
例:定义一个手机类,手机类中的成员变量为品牌,价格与颜色,通过get方法和set方法进行访问:
public class Phone{
//定义成员变量
String brand;
int price;
String color;
//定义get方法和set方法
public void setBrand(String b){
brand = b;
}
public String getBrand(){
return brand;
}
public void setPrince(int price){
price = p;
}
public int getPrice(){
return price;
}
public void setColor(String color){
color = c;
}
public String getColor(){
return color;
}
}
//定义测试类
class PhoneTest{
public ststic void main(){
Phone p1 = new Phone();
// 调用set()方法给对象赋值,调用get()方法给对象输出
p1.setBrand("红米K20pro至尊版");
String br = p1.getBrand();
System.out.println(br);
p1.setPrice(2799);
int pr = p1.getPrice();
System.out.println(pr);
p1.setColor("陶瓷白");
String co = p1.getColor();
System.out.println(co);
}
}
输出结果为:
上述代码中我们定义了get()方法和set()方法,若是不使用这两种方法,直接对对象中的成员变量进行赋值,一样可以进行赋值操作,但这样方法的定义意义就不大了,因此为了让在定义一个方法后必须调用方法才可以访问对象的成员变量,Java就提供了一个关键字:private
private:私有的,它可以修饰成员(成员变量与成员方法)。被private修饰的成员只能在本类中访问使用,其他类无法访问使用。这就使得想要访问对象的成员就必须通过公共的方法进行访问。
例如:
class Person{
private String name;
private int age;
public void setName(String s){
name = s;
}
public String getName(){
return name;
}
public void setAge(int a){
age = a;
}
public int getAge(){
return age;
}
// 定义一个私有的方法
private void show() {
System.out.println("姓名:" + name + ",年龄:" + age);
}
public void show2() {
show();
}
}
//测试类
public class PrivateDemo {
public static void main(String[] args) {
Person p = new Person();
p.setName("小王");
p.setAge(18);
p.show2();//调用公共方法访问私有方法
String p2= p.getName();
int p3=p.getAge();
System.out.println(p2);
System.out.println(p3);
}
}
该访问方式就可以成功访问被private修饰过的变量了,方法也是同理。输出结果为:
至此,一个基本完整的类就写好了。
标准类的写法(1.0版本):
成员变量:被private修饰 成员方法:含有getXxx(),setXxx()和show()(这里泛指方法)
为了使代码做到见名知意,又要使得在方法中对成员变量进行赋值时不会被就近原则所干扰而导致赋值失败,Java提供了一个关键字解决这一问题:this
就近原则:在方法中定义的形参如果和变量名相同的话,在进行赋值操作如:name=name;时,该name在没有其他更改形参的操作下,代表离它最近的那个变量。因此这两个name中没有一个是代表在方法中定义的形参,从而导致赋值失败。
this关键字:this代表的是将来调用该方法的对象,因此得到标准类2.0版本:
public class Phone {
private String brand;
private int price;
private String color;
public void setBrand(String brand) {
this.brand = brand;
}
public String getBrand() {
return brand;
}
public void setPrice(int price) {
this.price = price;
}
public int getPrice() {
return price;
}
public void setColor(String color) {
this.color = color;
}
public String getColor() {
return color;
}
public void Function() {
System.out.println("品牌为:" + brand + ",价格为:" + price + ",颜色为:" + color);
}
}
class PhoneTest {
public static void main(String[] args) {
Phone p1 = new Phone();
p1.setBrand("红米K20pro至尊版");
String br = p1.getBrand();
System.out.println(br);
p1.setPrice(2799);
int pr = p1.getPrice();
System.out.println(pr);
p1.setColor("陶瓷白");
String co = p1.getColor();
System.out.println(co);
System.out.println("===========");
p1.Function();
}
}
形式参数的问题:
1、当形式参数是基本数据类型的时候,将来调用方法的时候传入的是常量值,或者是该类型的变量
2、当形式参数是引用数据类型的时候,将来调用方法的时候传入的是该类对象的地址值
3、当形式参数是基本数据类型的时候,在方法中对变量做修改,不会影响到外部实际的栈内存中的值。
4、当形式参数是引用数据类型的时候,在方法中对变量做修改,会影响到外部实际的堆内存中的值。
class Demo2 {
public int getSum(int a,int b) {
a=100;
b=200;
return a + b;
}//由于是基本数据类型,所以在方法内部的修改不会影响在栈中定义的变量的值
}
class Student2{
String name;
public void speak(){
System.out.println("我热爱学习");
}
}
class StudentTest2{
/**
* 如果将来你看到一个方法的形式参数是一个类的类型,说明他是一个引用数据类型
* 这里其实需要的是该类的对象
* 调用的时候,把main方法中创建好的对象名传过来,实际上传的就是对象的地址值
* @param s
*/
public void function(Student2 s){ //Student2 s = new Student2();
s.name = "小王";
s.speak();
}
}
public class XingShiCanShuDemo {
public static void main(String[] args) {
Demo2 d = new Demo2();
int a = 10;
int b = 20;
System.out.println(d.getSum(a,b));
System.out.println("a:"+a+",b:"+b);
//要想调用function(),就必须创建StudentTest2对象
StudentTest2 st2 = new StudentTest2();
Student2 student2 = new Student2();
System.out.println(student2.name);
st2.function(student2);
System.out.println(student2.name);
// 这里是以引用数据类型为参数,传递的是地址值,
// 调用function方法对堆内存中对应值进行修改
}
}
输出结果: