Java类和对象的使用

发布于:2023-01-15 ⋅ 阅读:(577) ⋅ 点赞:(0)

目录

成员变量

成员方法

 局部变量

 作用域

构造方法

不定参数

对象

对象的创建

对象的比较

==

equlas()


命名规范(这些不是必须的,但是为了代码的可阅读性,建议遵守)

包名一般是公司域名然后跟着功能层名以区分,以划分。在以后的学习中会接触到Mapper,Service,Controller层等等的,这些都是自己取,能区分什么功能层区就行。 

比如 Mapper层

org.example.mapper

类名遵循帕斯卡命名法,即每个单词的首字母大写

字段及方法名采用驼峰式命名法,即第一个单词的的首字母小写,后面的每个单词的首字母大写

常量名采用下划线命名方式,每个单词全部都大写,单词之间用下划线来分割

public class Person{
        public static final String TWO_HANDS = "正常"
            
        String personName;

        int personAge;

        public void eatFood(){

                //doAnything

        }

}

定义一个Person类

public class Person{
	private String name;    //定义一个成员变量
    
    private Person(){        //私有化构造方法,不允许外部实例化本类
        
    }
    

	public String getName() {    //定义一个成员方法来获取成员变量的值
		int age = 18;            //定义一个局部变量
		setName(age + "的"+ this.name);    //调用方法并传入参数
		return name;                        //返回成员变量
	}

	public void setName(String name) {    //定义一个成员方法来设置成员变量的值
		this.name = name;                 //将参数值赋值给成员变量
	}
    public Person getPerson(){            //定义一个方法来获取Person类的实例对象
        return new Person();              //返回一个实例对象
    }    
}

成员变量

对应的就是对象的属性

当然也可以叫全局变量

权限修饰符  [static |& final]  数据类型  变量名 =  [变量值 | 方法] ;

成员方法

对应的就是对象的行为

需要注意的是:

如果不需要返回值则类型为void关键字

return返回的值需要与方法返回类型一致

参数列表的表现形式为: 数据类型 参数名

权限修饰符  [static |& final]  方法返回类型  方法名(参数列表){

        //doAnything

        return 返回值;

 

 在上述语法中[static |& final]表示为可以不选,或任选其一,或两个都写

 局部变量

当成员变量和局部变量同名时优先使用局部变量

数据类型 变量名 = [变量值 | 方法];

 作用域

class Test{
    int a = 0;
    int b = 10;

    public void test1(){
        int a = 1;
        
        if(a == 1){
            int c = 100;
            {
                println(c);    //100
            }
        }
        //这里为了省事所以没有写完输出
        println(a):    //1
        println(c);    //error:变量未定义    
        println(b);    //10 
    }

    public void test2(){
        int b = 20;
        println(a);    //0
        println(c);    //error:变量未定义 
        println(b);    //20   
    }
}

 通俗的来讲一个花括号就是一个作用域,变量从开始定义到代码块结束就是它的生命周期

只能访问到范围大的和自己本域的,不能访问同级

在Test类中定义了两个成员变量,这两个变量由最外部的花括号包围,所以作用域是最大的,即本类中的任何非静态方法块都可以访问到。

在方法中又重新定义了一个新的 c 变量 并赋值为100 这个变量只能 只能由本域及本域中代码块来访问

权限修饰符

访问包的位置 权限修饰符
private default protected public
本类可见
同包及其子类可见 同包可见
其他包及其子类可见

这里要注意是在普通类中没有显式的写权限修饰符 默认就是default

就像下面这样

void method(){}

因为在后面接口中有一个完全不同的概念

构造方法

构造方法是一个特殊的方法,这个是类必须得有的,它是在对象初始化的时候调用

与成员方法不一样的是构造方法没有返回值

并且方法名要与类名相同

权限修饰符 类名(参数列表){

        //doAnything

}

但没写也没关系,JVM会自动创建一个默认的无参构造来供程序运行

需要注意的是:

如果你写了构造方法的话,那么JVM就不会再为你提供无参构造,而是使用你写的来运行

//没有写出构造方法
public class Test{
	public static void main(String[] args) {
		new Test();    
	}
}
//写出构造方法
public class Test{
    String name;
    public Test(String name){
        this.name = name;
        println(name + "初始化了Test");
    }
	public static void main(String[] args) {
        new Test("Person");    //Person初始化了Test
		new Test();            //error Test()未定义
	}
}

不定参数

如果不确定传入参数的个数可以使用Java不定参数的格式并且支持重载(构造方法和成员方法都可以使用)

其实本质上还是一个数组

数据类型  ...参数名        //...挨着数据类型也可以 空一格也可以

数据类型...  参数名 

数据类型...参数名 

 需要注意的是

  1. 不定参数必须得放在参数列表的最后一个参数
  2. 在一个方法中不定参数只能存在一个
class Test(){
public static void main(String[] args) {
		print("fasf","fasfsd","fasdf");        //error
	}
	public static void print(String... vars) {
		for (String string : vars) {
			System.out.println(string);
		}
	}
	public static void print(String var1,String...vars) {
		System.out.println(var1);
		for (String string : vars) {
			System.out.println(vars);
		}
	}
}

 如上述代码,编译器就不知道要调用哪一个方法了

很明显,第一个print()方法满足参数列表,而第二个也显然满足,所以在重载方法时需要注意一下参数列表

对象

对象的创建

java中创建对象的关键字是new

类名 对象名 = new 构造方法;

/**
 *    这里就是前面讲的一个对象在初始化的时候
 *    会调用对应的构造方法,所以对象的初始化和创建都是绑定在一起的
 *    这是的person只是一个名字,可以随便取
 */

public class Person{
	private String name;

	public Person() {
		
	}
	
	public Person(String name) {
		this.name = name;
	}

    public static void main(String[] args) {
		                  new Person();            
		 Person person1 = new Person();            //无参构造
		 Person person2 = new Person("person");    //有参构造

	}
}

在上述代码中,当使用new关键字创建出对象后会有一个地址,然后将引用地址拷贝给对象person进行关联

而在主方法第一句的虽然它整体是一个对象,但没有变量存取它的引用,后面就无法对它进行操作

 变量存在于栈中,而对象存在于堆中,所以内部是这样的,这些对象现在都是独立的

对象超出了作用域也就没用了,这个时候由于Java垃圾处理机制,就会销毁这些对象

还有一种情况就是将对象值引用赋值为null也会被销毁

如果想在后面初始化的话,就这样直接放着也没事

Person person;

 对象创建好后,就是使用了,操作符"."

对象名.成员        这便是访问对象属性和方法的形式

 将上面的代码稍稍改动一下

public class Person{
	private String name = "Person";    //将Person类的默认名字赋值Person
	public final int AGE = 18;        //Person类的年龄永远18

	public Person() {                //无参构造
		
	}
	
	public Person(String name) {    //有参构造,传入参数,改变默认的名字
		this.name = name;
	}

    public String getName(){        //获取私有属性name;
        return this.name;
    }

    public void setName(String name){
        this.name = name;
    }

    public void work(){                //工作行为
        printf(this.name + "在码字");
    }
    
    public static void main(String[] args) {    
        //再出现一下,这里person只是一个名字,随便取
		Person person = new Person();                      //创建一个名叫person的对象
        println(person.getName + ":" + person.AGE + "岁"); //Person:18岁
        person.work;                                       //Person在码字
    
        person.setName("小丽");                            //设置对象的name属性
        println(person.getName + ":" + person.AGE + "岁"); //小丽:18岁
        person.work;                                       //小丽在码字
	}
}

对象的比较

用==或是equlas()方法

==

如果是基本类型的话就是比对它们的值是否相同

但如果是引用类型的话就是比较它们的引用地址是否相同

public static void main(String[] args) {
		int a = 1;
        int b = 2;
		int c = 1;
		String str1 = "equals";
		String str2 = "equals";
		String s1 = new String("equlas");
		String s2 = new String("equlas");
		Person person1 = new Person();
		Person person2 = person1;
		Person person3 = new Person();
		System.out.println(a == c);                //true
		System.out.println(str1 == str2);          //true
		System.out.println(s1 == s2);              //false
		System.out.println(person1 == person2);    //true
		System.out.println(person1 == person3);    //false
		System.out.println(person2 == person3);    //false
		
	}

第一句输出应该不会有什么疑问

但是两种String为什么会结果不一样呢,

引用类型比对的是地址所以s1和s2自然是不同,而传入的参数也仅仅是属于这个对象的成员而已。

但没有用new关键字的str1和str2的这个值"equals"和int的值 1 一样是存放在常量区(这里就不会讲的太深),而对于s1和s2来说它们是对象,所以是存放在堆区中的

 对一个变量赋的值会去常量区里面找,找到了就引用值对象

如果没有找到就会在常量区再创建一个值对象,然后引用

equlas()

equlas是超类Object的一个方法,代码是这样的

public boolean equals(Object obj) {
        return (this == obj);
    }

因为Object是所有类的超类,也可以称之为父类,所以如果没有重写父类的equals方法的话默认也是在比较两个对象的引用地址;

在些某些必要的时候,比如在一些Hash集合中,如果重写了equals方法的话是需要重写hashcode方法的,会降低hash冲突的几率

Person类

public class Person{
	private String name;
	private int age;
	private String gender;
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	
	
//	@Override
//	public int hashCode() {
//		return Objects.hash(age, gender, name);
//	}

	@Override
	public boolean equals(Object obj) {
        //引用相等直接返回true
		if (this == obj) {
		return true;
		}
        //如果参数不是属于Person及子类的话就返回false
		if (!(obj instanceof Person)) {
			return false;
		}
        //强制向下转型
		Person other = (Person) obj;
        //比较对象的属性
		return age == other.age 
                   && Objects.equals(gender, other.gender) 
                   && Objects.equals(name, other.name);
	}

	public Person(String name, int age, String gender) {
		super();
		this.name = name;
		this.age = age;
		this.gender = gender;
	}

	public Person() {
		
	}

}

Test类

public class Test {
	public static void main(String[] args) {
		Person var1 = new Person("小明",18,"男");
		Person var2 = new Person("小明",18,"男");
		System.out.println(var1.equals(var2));    //true
        System.out.println(var1);
		System.out.println(var2);
	}
}

在上述代码中只是以对象的属性来判断,但是hashcode却不一样

但是如果将重写的hashcode注释去掉就会是这样

 这里就不再深入

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到