目录
命名规范(这些不是必须的,但是为了代码的可阅读性,建议遵守)
包名一般是公司域名然后跟着功能层名以区分,以点划分。在以后的学习中会接触到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不定参数的格式并且支持重载(构造方法和成员方法都可以使用)
其实本质上还是一个数组
数据类型 ...参数名 //...挨着数据类型也可以 空一格也可以
数据类型... 参数名
数据类型...参数名
需要注意的是
- 不定参数必须得放在参数列表的最后一个参数
- 在一个方法中不定参数只能存在一个
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注释去掉就会是这样
这里就不再深入