对象被创建的步骤
1.分配对象空间,并将对象成员变量初始化为0或空
2.执行属性值的显式初始化
3.执行构造方法(此时的对象已经被创建,我们可以在这一步对对象进行进一步的初始化工作)
4.返回对象的地址给相关的变量
面对对象:
public class Demo { public static void main(String[] args){ Horse h = null; h = new Horse(); // h.name = "dd"; h.eat(); h = null; //释放对象 } } class Horse{ String name; public void eat(){ System.out.println(name); } }
封装性:
public class Demo { public static void main(String[] args){ Horse h1 = new Horse(); // h1.name = "小明";//由于 name设置了私有字段,此时在给对象赋值,会报错; h1.setName("小明"); System.out.println(h1.getName()); } } class Horse{ //属性的封装 private String name; private int age; //成员变量,在类中定义,在堆内存,对象清空,则成员变量清空,有默认初始值,像String引用变量初始值为null,int的初始值为0; public void setName(String name){ //参数也是局部变量 int a = 111; //局部变量;在方法中定义,在栈内存,方法调用完毕,就清空,没有初始值,必须定义,赋值后,才能调用。 this.name = name; } public String getName(){ // return name; return this.name; // 可以使用this调用其他方法和属性,this可以省略,this前面可以加上类名 Horse.this.name(); } }
构造方法和构造方法的重载:
类似python中的__init__(self){}
public class Demo { public static void main(String[] args){ Horse h = new Horse(); Horse h2 = new Horse(1); } } class Horse{ public Horse(){ //方法名称和类名相同,没有返回值 System.out.println("我是构造方法"); } public Horse(int a){ System.out.println("a="+a); } }
构造方法之间的调用,用this()
public class Demo { public static void main(String[] args){ Horse h2 = new Horse(1); } } class Horse{ public Horse(){ //默认构造方法,可以保留 } public Horse(String b){ //方法名称和类名相同,没有返回值 System.out.println(b); } public Horse(int a){ this("11"); //调用另一个构造方法,注意,这条语句,只能放在最前面,否则报错;,限制了,不能调用多个; this("22"); //报错,只能调用一个 System.out.println("a="+a); } }
对象之间的关联:
public class Demo { public static void main(String[] args){ Hero hero1 = new Hero("刘备"); Weapon weapon1 = new Weapon("双股剑"); hero1.setWeapon(weapon1);//将对象传递给一个对象,实现对象之间的关联 System.out.println(hero1.getWeapon().getName()); } } class Hero{ //属性的封装 private String name; private Weapon weapon; public Hero(String name){ this.name = name; } public void setWeapon(Weapon weapon){ this.weapon = weapon; } public Weapon getWeapon(){ return this.weapon; } } class Weapon{ private Hero hero; private String name; public Weapon(String name){ this.name = name; } public void setHero(Hero hero){ this.hero = hero; } public String getName(){ return this.name; } }
继承:
方法的重载:发生在同一个类中,函数名相同,参数列表不相同,与返回值返回值(类型)无关;
方法的重写:发生在继承的关系中,函数名相同,参数列表相同,返回值(类型)需要相同。子类的访问修饰符需要大于或者等于父类的访问修饰符,子类的异常声明要小于或等于父类的异常声明,如果方法被private 、static修饰,那么方法不能被继承/重写。 final修饰,只能继承,不能重写
public class Demo { public static void main(String[] args){ Dog dog = new Dog(); //子类创建对象时 ,也会 自动 调用父类的默认的构造方法 System.out.println(dog.name); dog.print(); } } class Animal{ protected String name = "动物"; public Animal(){ System.out.println("我是Animil 默认构造方法"); } public Animal(String name){ System.out.print("我是Animial 传参构造方法"); } public void print(){ System.out.println("Animal"); } } class Dog extends Animal{ //继承的写法 public Dog(){ super("传值"); //如果有super,就会继承super所指的构造方法,具体执行那一个,看传参的列表 // super(); //如果没有传值,就会执行父类的默认的构造方法,前提父类必须保留默认的构造方法; //注意1:默认情况下,会自动添加super(),如果自己写了super,就会覆盖默认的 //注意2:super(),只能方法最开始的位置 } public void print(){ super.print(); //继承父类的方法; System.out.println("Dog"); } }
抽象类:
1、抽象类可以没有抽象方法,有抽象方法的一定是抽象类
2、非抽象类继承抽象类必须实现所有的抽象方法
3、抽象类可以继承抽象类,可以不实现父类的抽象方法
4、抽象类可以有方法实现和属性
5、抽象类不能被实例化
6、抽象类不能声明final
7、抽象类可以有构造方法
public class Demo { public static void main(String[] args){ Dog dog = new Dog(); } } abstract class Animal{ //声明该类是一个抽象类,只能继承,不能实例化 { System.out.println("可以有构造方法"); } public abstract void eat(); //可以没有抽象方法 ,如果有了抽象方法,该类必须是抽象类,并且该抽象方法必须子类实现; public void run(){ //普通的方法可以不用被实现 System.out.print("我可以跑"); } } class Dog extends Animal{ public void eat(){ } }
接口:
1、抽象类实现接口,可以不实现接口的方法,非抽象类,必须实现接口的所有的方法;
2、接口的方法没有声明访问修饰符,默认为public
3、接口不能有构造方法,接口不能被实例化
4、接口之间的继承用extends ,定义接口用interface ,类实现接口用implements
5、接口只能定义常量,抽象方法,(jdk1.8之后有默认的实现方法,和静态方法)
6、final不可以修饰接口
public class Demo { public static void main(String[] args){ Person person = new Person(); person.print(); //默认的方法实现; } } interface IEat{ // public abstract void eat(); void eat(); //简写,定义抽象方法 // public final static int NUM = 10; int NUM = 10; //简写,定义常量 public default void print(){ System.out.println("默认方法实现"); //jdk1.8之后有 默认方法实现(加上default),不能有其他的方法实现 } } interface ISleep{ void sleep(); } interface IRun extends IEat,ISleep{ //接口可以有多继承 void run(); } class Person implements IRun,ISleep{ //接口的实现,类可以继承多个接口(不是接口的继承) public void sleep(){} //必须实现接口的所有的方法 public void run(){} public void eat(){} }
多态:
public class Demo { public static void main(String[] args){ Chick smailchick = new SmailChick(); //用父类的引用指向子类对象,(用大的类型接受小的类型,向上转型,自动转换) eat(smailchick); SmailChick smailchick2 = new SmailChick(); eat(smailchick2); Chick bigchick = new BigChick(); eat(bigchick); } public static void eat(Chick c){ //多态性,Chick可以接受比他小的或者等于他的类型,(例如int可以接受short类型) c.eat(); // c.song(); //直接写会报错,原因Chick中没有song方法,在运行的时候,c才是所new的对象,在编译的时候c还是chick if(c instanceof BigChick){ //在转换之前做类型的判断 // BigChick bigchick = (BigChick)(c); //若果父类中没有定义song()方法,就需要 强制转换 将Chick转变成BigChick // bigchick.song(); ((BigChick)c).song(); //简写 } } } abstract class Chick{ public abstract void eat(); } class SmailChick extends Chick{ public SmailChick(){ super(); }//默认自动添加 public void eat(){ System.out.println("我是小鸡,我爱吃米"); } } class BigChick extends Chick{ public void eat(){ System.out.println("我是大鸡,我爱吃虫"); } public void song(){ System.out.println("我是大鸡,我会唱歌"); } }
this的本质
指明当前的对象,不能放到static静态方法中
class Test{ int a; public Test(int a){ //给成员变量进行赋值 this.a = a; } public Test(){ //调用另一个构造方法,只能放在代码的第一行(所以只能有一个) this(1); } }
java中的new到底为我们做了什么?
参考https://www.cnblogs.com/KingIceMou/p/7245446.html
String 中的hashcode()和equals()?
hashcode和equals都是为了对比两个对象是否相等一致,那么为什么会有两个呢?
hashcode()的判断是比较高效的,如果hashcode不一样那么这两个对象一定不相等。但是hashcode相等不能代表这两个对象一定相等,需要equals进行复杂的逻辑判断最终确定是否相等。所有我们在equals判断之前先判断hashcode是否相等可以一定程度提高效率,之后hashcode为了false,就可以不需要在判断equals了。
hashcode目的只是让一个对象只存在唯一的hashcode值,但是一个hashcode值可能会被多个对象共享。所以只要两个对象的hashcode值不相等,那他们对象肯定是不相等的。
这种大量的并且快速的对象对比一般使用的hash容器中,比如hashset,hashmap,hashtable等等,比如hashset里要求对象不能重复,则他内部必然要对添加进去的每个对象进行对比,而他的对比规则就是像上面说的那样,先hashCode(),如果hashCode()相同,再用equal()验证,如果hashCode()都不同,则肯定不同,这样对比的效率就很高了。
我们再来看看String中的hashcode和equals?
String重写了objdect中的hashcode()和equals()方法,所以这两个方法都可以用来判断字符串是否相等。只需要使用任意一个就可以判断?
new Object().equals(objdect)所有的类中默认的equals方法都是和"=="一样的效果,判断内存地址是否一样,只是String重写了equals。
public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }
public static void main(String[] args) { StringBuilder stringBuilder = new StringBuilder("11"); System.out.println(stringBuilder.hashCode()); stringBuilder.append("1"); //比较的是内存地址 System.out.println(stringBuilder.hashCode()); String a = "a"; String b = "a"; System.out.println(a.hashCode()+"=="+b.hashCode() );
补充
访问修饰符