文章目录
1.构造方法调用
调用本类构造,必须用this语句;
位置:必须写在 构造器中;
必须是构造的第一行代码处。
class WebUser{
private int userId;
private String userPwd = "999999";
private String userPwd;
private String userEmail;
// 构造块
{
this.userPwd = "999999";
}
public WebUser() {
this.userPwd = "999999";
}
public WebUser(int userId, String userEmail) {
//调用带参数的构造
this(userId,"999999",userEmail);
/*
* 调用本类构造,必须用this语句;
* 位置:必须写在 构造器中;
* 必须时构造的第一行代码处。
*/
this();//调用本类构造器
this.userId = userId;
this.userEmail = userEmail;
this.userPwd = "999999";
}
public WebUser(int userId, String userPwd, String userEmail) {
this.userId = userId;
this.userPwd = userPwd;
this.userEmail = userEmail;
}
public int getUserId() {
return userId;
}
public WebUser setUserId(int userId) {
this.userId = userId;
return this;
}
public String getUserPwd() {
return userPwd;
}
public WebUser setUserPwd(String userPwd) {
this.userPwd = userPwd;
return this;
}
public String getUserEmail() {
return userEmail;
}
public WebUser setUserEmail(String userEmail) {
this.userEmail = userEmail;
return this;
}
public String show() {
return userId + "\t" + userPwd + " \t" + userEmail;
}
}
public class TestWebUser {
public static void main(String[] args) {
// 链式调用setter访问器
WebUser user = new WebUser().setUserEmail("user@qq.com").setUserPwd("123456").setUserId(222);
user.setUserId(11);
user.setUserEmail("aa@qq.com");
System.out.println(user.show());
WebUser user1 = new WebUser().setUserId(111);
System.out.println(user1.show());
WebUser user1 = new WebUser();
System.out.println(user1.show());
WebUser user2 = new WebUser(11, "user2@163.com");
System.out.println(user2.show());//11 999999 user2@163.com
WebUser user3 = new WebUser(22, "123456", "user3@163.com");
System.out.println(user3.show());
}
}
2.包解决的问题
程序包:用来管理类和接口的工具,是类和接口的集合
2.1 创建
定义程序 包:
package 包名;
package 父包名.子包名[.……];
注意:
1.通常包名都用小写字母;
2.位置必须在java文件的第一行代码处;
3.只能有一行 package语句;
4.同一个项目下包名不能重复。
通常:域名反转.部门名.项目名;
2.2使用
同一个包下,直接使用;
不同的包下:
1)导入程序包下的类型;
import 包名.类型名;
2)完全限定名称
优点:
1.方便查找;
2.避免命名冲突;
3.更好的提供了封装
3.访问修饰符
4.static修饰符
静态:修饰 类,成员变量,成员方法,代码块
4.1 修饰变量
class Student{
int count = 0;
}
public class TestStudent {
public static void main(String[] args) {
Student guojing = new Student();
guojing.count ++;
Student huangrong = new Student();
huangrong.count ++;
System.out.println(guojing.count);//1
System.out.println(huangrong.count);//1
}
}
静态变量(类变量)
//类加载的时候 初始化
//静态变量 属于类,不属于对象
//被所有对象所共享
//优先于 对象而存在
class Student{
//静态变量(类变量)
//类加载的时候 初始化
//静态变量 属于类,不属于对象
//被所有对象所共享
//优先于 对象而存在
static int count = 0;
}
public class TestStudent {
public static void main(String[] args) {
//类名.静态变量名(可以不创建对象)
Student.count ++;
Student.count ++;
System.out.println(Student.count);
}
}
总结静态变量:
1.名称:静态变量(类变量);
2.属于类,不属于对象;
3.在类加载时,初始化;
4.优先于对象而存在的;
5.被所有对象所共享。
使用语法:
类名.静态变量名; //使用
对象名.静态变量名;
场合: 共享空间。
4.2 修饰方法
静态方法(类方法):
场合: 1.类不能创建对象 ,想实现功能,调用静态方法实现;
2.简单。
public class TestStaticMethod1 {
int n = 11;
static int sn = 22;
//实例成员方法
public void f() {
System.out.println("f");
System.out.println(n);
System.out.println(sn);//使用静态成员
}
//静态方法(类方法)
public static void sf() {
System.out.println("sf");
//静态方法中只能直接访问静态成员
System.out.println(sn);
//非静态的创建对象
System.out.println(new TestStaticMethod1().n);
//不能使用this,super
}
public static void main(String[] args) {
TestStaticMethod1.sf();//使用
new TestStaticMethod1().sf();//
new TestStaticMethod1().f();
}
}
4.3 修饰代码块
代码块:
1) 构造块
class 类{
{
//构造块:初始化对象的。
}
}
2)静态块
static {
//静态块:初始化类
}
class Demo{
static{
System.out.println("Demo的静态块");
}
{
System.out.println("构造块");
}
Demo(){
System.out.println("构造器");
}
}
public class TestStaticMethod2 {//启动类,主类
/* static {
System.out.println("静态块");
}*/
public static void main(String[] args) {
Demo demo = new Demo();//引起了类的加载
Demo demo1 = new Demo();//类不会重复加载
// ClassLoader.getSystemClassLoader().loadClass(name)//了解以下原码
//可以知道为什么请看最后一个
}
}
3)局部代码块
public void 方法名(){
{
//局部块:
//限制 局部变量的使用范围和生命周期。
}
}
public void f() {
int n = 11;
System.out.println(n);
//局部块
{
int m = 22;
System.out.println(m);
}
}
4.4 静态变量初始化
class Demo1{
static int sn = 11;
static {
sn = 22;
}
}
public class TestStaticMethod3 {
public static void main(String[] args) {
System.out.println(Demo1.sn);//22
}
}
4.5 静态导入
格式:
import static 包名.类名.静态变量名(方法);
4.6 单例模式
只能创建一个对象。
/饿汉式特点:
1.这个对象类加载时就加载了,就有了;
2.线程安全的。
class Window{
//静态变量只初始化一次
private static Window win = new Window();
static {
System.out.println("static");
}
private Window(){}
public static Window getWindow() {
return win;
}
}
//懒汉式 特点:
1 .在使用的时候 创建对象;
2.线程非安全的。
class Window{
//静态变量只初始化一次
private static Window win = null;
private Window(){}
public static Window getWindow() {
if(win == null) {
win = new Window();
}
return win;
}
}
5.编写:静态修饰符 3个人从篮子里拿苹果
class Child{
private String name;
// 共享的6个苹果
private static int appleCount = 6;
public Child(String name) {
this.name = name;
}
// getter
public int getAppleCount() {
return appleCount;
}
// 拿苹果
public void getApple() {
appleCount --;
System.out.println(name + "拿了一个苹果");
}
}
public class TestChild_exam {
public static void main(String[] args) {
Child guojing = new Child("郭靖");
Child yangkang = new Child("杨康");
Child huangrong = new Child("黄蓉");
guojing.getApple();
yangkang.getApple();
huangrong.getApple();
System.out.println("剩下" + guojing.getAppleCount());
}
}
6.项目案例:图书管理系统2.0
需求:使用类和方法对于图书管理系统进行升级
代码如下:
import java.util.Scanner;
class Book{
private int no;
private String name;
private double price;
public Book() {
}
public Book(int no, String name, double price) {
this.no = no;
this.name = name;
this.price = price;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String show() {
return no + "\t" + name + "\t" + price;
}
}
class ManagerBook{
private Book [] books = new Book[100];// null,null,null……………………
public void add(Book book) {
for(int i = 0; i < books.length; i++) {
if( books[i] == null) {
books[i] = book;
System.out.println("添加成功");
break;
}
}
}
public void update(int no , double price) {
for(int i = 0; i < books.length; i++) {
if(books[i].getNo() == no) {
books[i].setPrice(price);
System.out.println("修改成功");
break;
}
}
}
public void delete(int no) {
for(int i = 0; i < books.length; i++) {
if(books[i].getNo() == no) {
//覆盖
for(int j = i; j < books.length -1; j ++) {
books[j] = books[j + 1];
}
if(books[books.length -1] != null) {
books[books.length -1] = null;
}
System.out.println("删除成功");
break;
}
}
}
public void queryAll() {
System.out.println("图书编号\t图书名称\t图书价格");
for(Book book : books) {
if(book == null) {
break;
}
System.out.println(book.show());
}
}
}
public class TestBook {
public void startMenu() {
Scanner input = new Scanner(System.in);
ManagerBook mgr = new ManagerBook();
System.out.println("\t-菜单-");
System.out.println("\t 1.添加;2.修改;3.删除;4.查询;5.退出\n");
int menuNo;
int no;
String name;
double price;
while(true) {
System.out.println("-- 输入菜单项:");
menuNo = input.nextInt();
switch(menuNo) {
case 1:
//add
System.out.println("--输入编号:");
no = input.nextInt();
System.out.println("--输入名称:");
name = input.next();
System.out.println("--输入价格:");
price = input.nextDouble();
Book book = new Book(no, name, price);
// 或者:
// book.setName(name);
// book.setNo(no);
// book.setPrice(price);
mgr.add(book);
break;
case 2:
//update
System.out.println("--输入要修改的图书编号:");
no = input.nextInt();
System.out.println("--输入新的价格:");
price = input.nextDouble();
mgr.update(no, price);
break;
case 3:
//delete
System.out.println("--输入要删除的图书编号:");
no = input.nextInt();
mgr.delete(no);
break;
case 4:
//select
mgr.queryAll();
break;
case 5:
System.out.println("退出应用程序");
System.exit(0);
}
}
}
public static void main(String[] args) {
// TestBook test = new TestBook();
// test.startMenu();
//匿名对象 :只能使用一次
new TestBook().startMenu();
}
}
7.为什么static块只被执行一次?
那么static块到底在什么时候运行的呢?如果了解JVM原理,我们知道,一个类的运行分为以下步骤:
1.装载
2.连接
3.初始化
其中装载阶段又三个基本动作组成
1.通过类型的完全限定名,产生一个代表该类型的二进制数据流
2.解析这个二进制数据流为方法区内的内部数据结
3.构创建一个表示该类型的java.lang.Class类的实例
另外如果一个类装载器在预先装载的时遇到缺失或错误的class文件,它需要等到程序首次主动使用该类时才报告错误。
连接阶段又分为三部分:
1.验证,确认类型符合Java语言的语义,检查各个类之间的二进制兼容性(比如final的类不用拥有子类等),另外还需要进行符号引用的验证。
2.准备,Java虚拟机为类变量分配内存,设置默认初始值。
3.解析(可选的) ,在类型的常量池中寻找类,接口,字段和方法的符号引用,把这些符号引用替换成直接引用的过程。
当一个类被主动使用时,Java虚拟就会对其初始化,如下六种情况为主动使用:
1.当创建某个类的新实例时(如通过new或者反射,克隆,反序列化等)
2.当调用某个类的静态方法时
3.当使用某个类或接口的静态字段时
4。当调用Java API中的某些反射方法时,比如类Class中的方法,或者java.lang.reflect中的类的方法时
5.当初始化某个子类时
6.当虚拟机启动某个被标明为启动类的类(即包含main方法的那个类)
Java编译器会收集所有的类变量初始化语句和类型的静态初始化器,将这些放到一个特殊的方法中:clinit。
实际上,static块的执行发生在“初始化”的阶段。初始化阶段,jvm主要完成对静态变量的初始化,静态块执行等工作,正因为初始化只会进行一次,所以static只会执行一次。
下面我们看看执行static块的几种情况:
1、第一次new A()的过程会打印"";因为这个过程包括了初始化
2、第一次Class.forName(“A”)的过程会打印"";因为这个过程相当于Class.forName(“A”,true,this.getClass().getClassLoader());
3、第一次Class.forName(“A”,false,this.getClass().getClassLoader())的过程则不会打印""。因为false指明了装载类的过程中,不进行初始化。不初始化则不会执行static块。
8.注意
1.代码只能有一个public 名称与文件名一致;通常是主函数
2.即使不用也叫加一个无参的构造器,保证可以创建一个最基本的对象
3.编程思路:没有模板创建模板
4.匿名对象只能使用一次,再用再写
5.return this;this可以用来返回调用的数据结果
6.当以后对象比较多时,可以用这个方法直接在new里赋值,在get里return this即可。
7.import导入可以导入很多个
import a.A导入a包里的A
import a.是导入a包所有的类型
8.完全限定名称:
a.A a =new a.A()
这个方式用的不多
9.import b.c.C/import b.
调用小包需要写全,否则不调用
10.如果两个包下有同名的类,就要用完全限定名称的方式。
11.public的访问权限是最高的
12.访问修饰符一共就只有4个
13.static修饰符是静态的,可以用来修饰类,类中的成员变量,代码块,成员方法
14.变量加static就会变成公共的了
由此编程静态变量,
存储方式改变:
1.内存里开辟出一个方法区
2.其中有一个静态区,专门存储静态变量
3.对于静态变量的初始化,系统在类加载的时候完成
4.类加载的时候会初始化,而静态变量属于类,不属于对象,静态变量被所有对象所共享。
15.字节码文件(.class)被放在内存里释放,由JVM虚拟机进行解码加载,此过程如下解释:
1.虚拟机把class文件加载到方法区里,加载成功后会生成一个对应的对象在堆中,
这个对象还是.class,不过是在堆里,这样就可以被new了。
2.看看类中有没有静态变量,有则为其开辟空间在静态区里,默认初始化为0。
3.随后进行声明处初始化,至此这个类就可以被正常使用了。
16.类名.静态变量名 :可以不创建对象,直接使用,被所有对象所共享。
17.静态变量优先于对象而存在
18.静态块在第一次主动加载类时,也就是无需调用,写上就能用,例如写在主类之中。
包含主方法的类叫做启动类/主类
19.类是不会重复加载的
20.局部代码块的主要目的:
1.限制代码块里的代码适用范围和生命周期。
2.当代码块被执行完,代码块里的变量就会被释放掉。
21.饿汉式:
1无论是否想用,只要类一加载就会被执行,例如反射时触发它执行。
2.多线程安全的