class 是类 new 出的是对象
栈内存:
1 2 3 4 在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配 栈内存主要存放的是基本类型类型的数据 如( int , short , long , byte , float , double , boolean , char ) 和对象句柄。 注意 :并没有String基本类型、在栈内存的数据的大小及生存周期是必须确定的、其优点是寄存速度快、栈数据可以共享、缺点是数据固定、不够灵活。
堆内存:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 String str1 = new String ("myString" ); String str2 = "myString" ; System.out.println(str1 ==str2 ); String str1 = new String ("myString" ); String str2 = new String ("myString" ); System.out.println(a==b); 创建了两个引用,创建了两个对象。两个引用分别指向不同的两个对象。以上两段代码说明, 只要是用new ()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同, 也不会与栈中的数据共享 ( 此句话说明了每当new 出一个新的对象 但是虽然与栈区的数据相同的,但不会被影响)
1 2 3 4 5 6 7 8 9 10 11 12 在java中必须先设计类 才能获得对象 类(设计图): 是对象共同特征的描述 对象: 是真实存在的具体实例 一个java文件中可以定义多个java类 且只能有一个类是pubic修饰 而且public 修饰的类名必须成为代码文件名 下图为设计类方式: 类名 对象名 = new 类名(); Student s = new Student (); 得到类对象的语句写在main方法
我们需要先在外部定义类,并且存在成员变量和成员方法。而后才可以在类中去使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 实例代码 直接复制学习 public class Student { String name; double pce; double age; public void run () { String one; System.out.println(name+"----" +age); } public void kali () { System.out.println(name+"----" +age); } }
** 两个变量指向同一个对象 **
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class a { public static void main (String[] args) { Student s1 = new Student (); s1.name = "你好" ; s1.pce = 1 ; s1.age = 2 ; s1.kali(); Student s2 = s1; s2.name = "世界" ; s2.pce = 3 ; s2.age = 4 ; System.out.println("-----------------" ); System.out.println(s1.name); System.out.println(s2.name); s2.kali(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 可以多个得到类的对象 , 且每一个都是独立的 最后一个写的我们要使用的类名称 Car() Student s1 = new Student ();Student s2 = new Student (); 如何使用对象 : 访问属性: 对象.成员变量 c.name = "奔驰" ; 访问行为: 对象名.方法名() c.start() 注意: Car c = new Car () c 变量名中存储的是对象在堆内存中的地址
1 2 3 4 5 6 7 8 9 10 11 12 注意点: 对象放在堆内存中 垃圾回收 : 当堆内存中的类对象或数组对象 ,没有被任何变量引用指向时() 就会被判定为内存中的 “垃圾” Java存在自动垃圾回收期 会定期清理
# 封装 使用 private 关键字修饰类的属性,被私有化的属性只能在类中访问,外界想要访问就需要通过
提供 pubilc 修饰的公开的 getter 和 setter 方法。暴露其取值和赋值;
1 2 3 封装的好处 : 加强了程序代码的安全性 适当的封装可以提升开发效率 同时可以让程序更容易理解与维护
我们在类中取出这个对象使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 实例代码 直接复制学习 class Studen { private String name ; private int age; public int getAge () { return age; } public String getName () { return name; } public void setName (String name) { System.out.println("值为" +name); } public void setAge (int age) { if (age > 18 ){ this .age = age; System.out.println("是一个未成年" +age); }else { System.out.println("不是未成年" +age); } } } public class a1 { public static void main (String[] args) { Studen sa = new Studen (); sa.setName("你好时间" ); sa.setAge(16 ); } } 输出为: 值为你好时间 不是未成年16
# 构造器
1 2 3 4 5 6 7 8 有参数的构造器:在初始化对象的时候 同时可以为对象进行赋值 构造器的作用 初始化类的对象 并返回对象的地址 注意事项: 一旦定义了有参数构造器 无参数构造器就没有了 此时需要自己写一个
** 无参构造器 **
构造方法的名称必须和类名一致
有参构造器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 实例代码 直接复制学习 注意事项: 一旦定义了有参数构造器 无参数构造器就没有了 此时需要自己写一个 不然会报错,但其实只要没有new 出无参的构造器就没有事情 会报错只是我们简单的new 出了它, saber s = new saber () 但我们没有在类中写无参的方法,所以才会导致报错 class sa { private String name ; private int age ; public sa () { System.out.println("定义了有参构造器无参构造器就会没有了 " + "此时需要自己写一个不然会报错" ); } public sa (String a,int b) { name = a; age = b; System.out.println("狗叫是" +a+"年龄是" +b); } public void saber () { System.out.println(name+"为name修改后的值" +age+"同样也被修改" ); } } public class one { public static void main (String[] args) { sa day = new sa (); sa day1 = new sa ("耀阳" ,29 ); day1.saber(); } }
# 构造方法重载 重载在相同作用域,只是说添加了形参个数达到复用的目的,也就是再构造方法的基础上去添加参数 , 它们具有相同的名称但参数列表不同 ,也就是说 Java 可以存在相同的方法只要参数列表不同就可以了
和普通方法一样,构造方法也可以重载,多次使用不影响,只要每一个得到的参数个数不同即可调用不同的构造方法为不同的属性赋值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 实例代码 直接复制学习 class sa { private String name ; private int age ; private int mo ; public sa () { System.out.println("定义了有参构造器无参构造器就会没有了 " + "此时需要自己写一个不然会报错" ); } public sa (String a,int b) { name = a; age = b; System.out.println("狗叫是" +a+"年龄是" +b); } public sa (String a,int b,int c) { name = a; age = b; mo = c; System.out.println("姓名是" +a+"年龄是" +b+"身高是" +c); } public void saber () { System.out.println(name+"为name修改后的值" +age+"同样也被修改" ); } } public class one { public static void main (String[] args) { sa day = new sa (); sa day1 = new sa ("耀阳" ,29 ); sa day2 = new sa ("邓小伟" ,19 ,180 ); } }
# this **this 在这里加就代表指向当前对象或者方法 谁调就是谁 String name **
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 this 的作用是为了区分开构造方法的变量和成员变量,普通的写法在下图中两个成员变量和构造方法的实参不一样 虽然说都会在方法中等于,但是如果命名不一一致的花可读性很差 但是如果让两个变量一致的话那么也就不好区分,this 的作用就是区分 通过它想调用谁就调用谁 String name ; int age ; public sa (String a,int b){ name = a; age = b; System.out.println("狗叫是" +a+"年龄是" +b); } ------------------------------------------------------ 三种用法 1. this 关键字调用本类成员变量属性2. this 关键字调用成员方法3. this 调用本类的构造方法
1.this 调用本类的 成员变量属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 实例代码 直接复制学习 class Car { String name; double price; public Car(){ System.out.println("定义了有参构造器无参构造器就会没有了 " + "此时需要自己写一个不然会报错" ); } public Car(String name,double price){ this .name = name; this .price = price; } public void goWith(String name){ System.out.println("this.name为" +this .name+"普通name为" +name); System.out.println(this ); } } public class one { public static void main(String[] args) { Car c = new Car(); Car c1 = new Car("奔驰" ,50 ); c.goWith("宝马" ); } 就是传入了不同的参数得到了代码的复用 t his.name 的值其实就是被 c1 这个有参构造方法赋值了,赋的值就是 奔驰 和 50 gowith只赋普通的name,this .name的值在构造方法中传入参数中就已经使用了 输入为: this .name为奔驰 普通name 为宝马
2.this 调用成员方法
让类中一个方法,访问该类里的另一个方法或实例变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Car { String name; double price; public Car(){ System.out.println("定义了有参构造器无参构造器就会没有了 " + "此时需要自己写一个不然会报错" ); } public Car(String name,double price){ this .name = name; this .price = price; } public void goWith(String name){ System.out.println("this.name为" +this .name+"普通name为" +name); System.out.println(this ); } public void demo(){ System.out.println("123" ); } public void test(){ this .demo(); } } ---------------------------------------- 输出: 123
3.this 调用本类的构造方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 实例代码 直接复制使用 class Car { private String name; private double price; public Car(){ System.out.println("定义了有参构造器无参构造器就会没有了 " + "此时需要自己写一个不然会报错" ); } public Car(String name,double price){ this (); this .name = name; this .price = price; } public void goWith(String name){ System.out.println("this.name为" +this .name+"普通name为" +name); System.out.println(this ); } public void demo(){ System.out.println("我是" +name+"年龄" +price); } public void test(){ } } public class one { public static void main(String[] args) { Car c = new Car("李白" ,50 ); c.goWith("宝马" ); c.demo(); } 注意点: 1. 只能在构造方法中使用this 调用其他的构造方法,不能再成员方法中通过this 调用2. 在构造方法中使用this 调用其他构造方法必须处于第一行且只能出现一次输出: 定义了有参构造器无参构造器就会没有了 此时需要自己写一个不然会报错 this .name为李白普通name为宝马Car@1 b6d3586 我是李白年龄50.0
# 代码块
1 简单来说 就是使用 {} 括起来的一段代码, 根据位置及声明关键字的不同 代码块可以分为普通代码块,静态代码块,构造块,静态代码块. 同步代码块 4 种
普通代码块
普通代码块就是直接在方法或语句中定义的代码块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class exp { public static void main(String[] args) { { int age = 100 ; System.out.println("普通代码块" ); } int age = 30 ; System.out.println("所处的代码块不同 定义同样的变量也不会影响s" ); } } 每一对被大括号{ } 括起的区域就被称为是代码块, exp同样也是一个大的代码块,在exp里面又包含了 main()方法代码块 在main里面又定义了局部代码块,它做了分割,所以在下方定义的 变量age不会影响 ,二者处于不同的代码块,作用域也不同
构造块
直接在类中定义的代码块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 实例代码 class saber { String age = "18" ; public saber(){ System.out.println("我是saber类的构造方法" ); } { System.out.println("我是构造代码块" ); } } public class exp { public static void main(String[] args) { saber a1 = new saber(); saber a2 = new saber(); } } 我们在saber中定义了 构造块,与构造方法,成员变量同级,但是实例化这个东西会先输出,哪怕构造代码块在它的下方也是先执行 "我是构造代码块" 说明了构造代码块的执行顺序是优于构造方法的,与放置前后的位置没有关系输出: 我是构造代码块 我是saber类的构造方法 我是构造代码块 我是saber类的构造方法
# Static (修饰静态)单独定义了一个类但是没有通过 new 实例化是并没有开辟栈内存和堆内存的, 只要 new 过后才会开启
我们 ** 希望一些属性和所有的对象共享,那么就可以将其声明为 static 属性,** 如果使用了这个修饰,那么这个属性可以直接使用 类名去进行调用
包括成员方法也是可以通过 static 修饰
# 静态属性 通过 static 修饰的属性该属性被称为静态属性,也叫 (全局属性) 静态属性使用类名直接访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 定义方式: 将属性用户 static 修饰现在可以被全局访问到,所谓全局属性 就是可以被不同的类修改使用 本来下方两个类都是独立开辟的内存空间,属性互不影响值,但如果类被 static 修改 那么就可以被一起修改值, Student a = new Student; Student a1 = new Student; static String scho = "清华" ; 使用: y.scho = "南昌大学" ; 实例对象修改也就是 yan y = new yan(); yan.scho = "南昌大学" ; 类名修改 class yan {}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 实例代码 class yan { String name ; int age; static String scho = "清华" ; public yan (String name,int age) { this .name = name; this .age = age; } public void info () { System.out.println("现在的姓名是" +name+"年龄是" +age+"学校是" +scho); } } public class idea1 { public static void main (String[] args) { yan y = new yan ("小白" ,18 ); yan y1 = new yan ("小白" ,18 ); yan y2 = new yan ("小白" ,18 ); y.info(); y1.info(); y2.info(); y.scho = "南昌大学" ; y.info(); y1.info(); y2.info(); } } 输出: 现在的姓名是小白年龄是18 学校是清华 现在的姓名是小白年龄是18 学校是清华 现在的姓名是小白年龄是18 学校是清华 现在的姓名是小白年龄是18 学校是南昌大学 现在的姓名是小白年龄是18 学校是南昌大学 现在的姓名是小白年龄是18 学校是南昌大学 注意: static 关键字只能修饰成员变量,不能修饰在方法内的局部变量 下面演示错误代码public void saber () {static int a = 10 ; }
# 静态方法 想要使用类中的成员方法,就需要将它实例化 但是在开发中我们希望不创建对象的情况下,通过类的名称就可以调用 想要实现这个效果,就可以在成员方法前面加上 static 修饰,被修饰后的方法称为静态方法
1 2 3 4 5 静态方法可以通过类名和对象访问: 类名.方法 saber.pen(); saber{} 实例对象名.方法 Student.pen(); saber Student = new Student();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 实例代码 class pen { String name; double age; private static String xiao = "B大学" ; public pen (String name,double age) { this .name = name; this .age=age; } public void tr () { System.out.println("姓名是" +name+"年龄" +age+"学校是" +xiao); } public static void sf (String xiao) { pen.xiao = xiao; } } public class kali { public static void main (String[] args) { pen p1 = new pen ("小李" , 18 ); pen p2 = new pen ("小李" , 18 ); pen p3 = new pen ("小白" , 18 ); p1.tr(); pen.sf("清华" ); p1.tr(); p2.tr(); p3.tr(); } } ---------------------------------- 上面代码可以成功将 "xiao" 的值 由 "B大学" 改变为 "清华" 且我们没有通过 sf()方法去做,而是直接通过pen.方法去完成, pen.xiao="清华" 类名修改 pi.xiao是="清华" 实例对象修改 以上两个方法都是可以统一修改的 二者都和静态属性一个道理也是全局都可以访问到,并且可以修改 pen p1 = new pen ("小李" ,18 ); 只是将值传入了this .name的构造方法,其实我更喜欢理解为new 出多个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class kami { static public void saber (String name,int age) { System.out.println("传入的name是" +name+"年龄是" +age); } } public class Quadratic { public static void main (String[] args) { kami a = new kami (); kami.saber("123" ,123 ); } }
# 静态代码块 使用 Static 修饰的代码块称为静态代码块,当类被加载时,静态代码块才会被执行,由于类被加载一次 因此静态代码块也只被加载一次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class pen { { System.out.println("我是构造代码块" ); } static { System.out.println("我是静态代码块" ); static 修饰的代码块会随class文件一起加载,并且优先级最高,并且只会输出一次 } 虽然我们在下方实例化了三次对象,但是静态代码块的内容只输出了一次 public pen () { 这就说明,静态代码块在类使用的第一次才会被加载,并且只会加载一次 System.out.println("我是pen类的构造方法" ); } } public class idea2 { public static void main (String[] args) { pen p = new pen (); pen p1 = new pen (); pen p2 = new pen (); } } 输出: 我是静态代码块 我是构造代码块 我是pen类的构造方法 我是构造代码块 我是pen类的构造方法 我是构造代码块 我是pen类的构造方法