首页
关于
友链
Search
1
wlop 4K 壁纸 4k8k 动态 壁纸
1,386 阅读
2
Nacos持久化MySQL问题-解决方案
895 阅读
3
Docker搭建Typecho博客
733 阅读
4
滑动时间窗口算法
706 阅读
5
Nginx反向代理微服务配置
676 阅读
生活
解决方案
JAVA基础
JVM
多线程
开源框架
数据库
前端
分布式
框架整合
中间件
容器部署
设计模式
数据结构与算法
安全
开发工具
百度网盘
天翼网盘
阿里网盘
登录
Search
标签搜索
java
javase
docker
java8
springboot
thread
spring
分布式
mysql
锁
linux
redis
源码
typecho
centos
git
map
RabbitMQ
lambda
stream
少年
累计撰写
189
篇文章
累计收到
20
条评论
首页
栏目
生活
解决方案
JAVA基础
JVM
多线程
开源框架
数据库
前端
分布式
框架整合
中间件
容器部署
设计模式
数据结构与算法
安全
开发工具
百度网盘
天翼网盘
阿里网盘
页面
关于
友链
搜索到
45
篇与
的结果
2022-02-28
DBCP连接池
使用dbcp连接池,进行数据库的CRUD,涉及jar包:commons-dbcp2-2.8.0.jar(连接池包)、commons-pool2-2.9.0.jar(dbcp依赖该包)、commons-logging-1.2.jar(接口日志包)、mysql-connector-java-5.1.37-bin.jar(数据库连接驱动)、commons-dbutils-1.7.jar(基本CRUD操作)DbcpUtils数据库连接池配置:package learn.javase.dbcppool; import org.apache.commons.dbcp2.BasicDataSource; /** * 利用DBCP链接数据库 * @author Jole * */ public class DbcpUtils { private static BasicDataSource dataSource = new BasicDataSource(); static { //必配参数 dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/test"); dataSource.setUsername("root"); dataSource.setPassword("11111"); //可配参数 dataSource.setInitialSize(10); dataSource.setMaxIdle(8); dataSource.setMinIdle(2); } public static BasicDataSource getConnecton() { return dataSource; } } 利用DbcpUtils进行数据库的CRUD操作:package learn.javase.dbcppool; import java.sql.SQLException; import java.util.List; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.ArrayListHandler; /** * 利用DBCP数据库连接池增加、查询 * @author Jole * */ public class DbcpUtilsDemo { private static QueryRunner qr = new QueryRunner(DbcpUtils.getConnecton()); public static void main(String[] args) { // TODO Auto-generated method stub // insertData(); findData(); } public static void insertData() { String sql = "insert into my_user(u_id,u_name,u_age) values(?,?,?)"; Object[] params = {"777777","dbcpUTils",30}; try { int num = qr.update(sql, params); System.out.println(num); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void findData() { String sql = "select * from my_user"; try { List<List<Object[]>> objs = qr.execute(sql, new ArrayListHandler()); for(List<Object[]> obj : objs ) { for(Object ob : obj) { System.out.println(ob); } } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 除了DBCP数据库连接池外,还有目前比较常用的c3p0、Druid等数据库链接池。
2022年02月28日
278 阅读
0 评论
1 点赞
2022-02-28
JAVA原生JDBC操作
利用JAVA原生JDBC进行数据库的CRUD操作。简单记录一下。package learn.javase.jdbc; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Scanner; import java.sql.PreparedStatement; import java.sql.Connection; /** * jdbc使用 * @author Jole * */ public class MyDriver { public static void main(String[] args) throws ClassNotFoundException, SQLException{ //1.注册驱动 Class.forName("com.mysql.jdbc.Driver"); //2.获取数据库连接对象 String url = "jdbc:mysql://localhost:3306/test"; String user = "root"; String password = "111111"; Connection conn = DriverManager.getConnection(url, user, password); // System.out.println(conn); //3.获取连接平台的执行对象 // Statement st = conn.createStatement(); //4.执行sql,返回行数 //executeUpdate():增删改 //String sql = "insert into user(user_id,user_name,user_password) values('1320442338427273213','zss','12')"; //int n = st.executeUpdate(sql); Scanner scan = new Scanner(System.in); String name = scan.nextLine(); int age = scan.nextInt(); //为了防止sql注入攻击和提高效率,使用Statement的子类,进行预编译 //executeQuery():查询 String sql = "select * from my_user where u_name=? and u_age=?"; PreparedStatement ps = conn.prepareStatement(sql); ps.setObject(1, name); ps.setObject(2, age); System.out.println(sql); ResultSet rs = ps.executeQuery(); //5.处理结果 while(rs.next()) { System.out.println(rs.getString("u_name")+ " " + rs.getString("u_age")); } //6.释放资源 rs.close(); ps.close(); conn.close(); } }
2022年02月28日
299 阅读
0 评论
2 点赞
2022-02-28
JAVA反射
获取反射对象的3种方法。通过反射创建对象、通过反射获取有参、无参、公有、私有构造方法。通过反射获取公有、私有成员变量并修改之。通过反射获取成员方法,并调用。通过反射泛型擦除,存值。通过读取配置文件运行反射方法。package learn.javase.mycalss; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; /** * 一、获取class的三种方式 * * 二、获取公有构造方法 * 注意: * 1、被反射的类必须是有空参数的构造器 * 2、构造方法必须是public的才能反射获取 * * 三、获取所有构造方法 * * @author Jole * */ public class ClassDemo { public static void main(String[] args) throws Exception{ // 方式1、.getClass() Person p = new Person(); Class c = p.getClass(); System.out.println(c); //方式2、类名.class Class c3 = Person.class; System.out.println(c3); //方式3、Class.forName(类全名); Class c2 = Class.forName("learn.javase.mycalss.Person"); System.out.println(c2); Class personClass = Class.forName("learn.javase.mycalss.Person"); //获取public所有构造方法 Constructor[] cons = personClass.getConstructors(); for(Constructor con : cons) { System.out.println(con); } //获取public无参构造方法 Constructor cc = personClass.getConstructor(); Person pp = (Person)cc.newInstance(); //获取public有参构造方法 Constructor ccc = personClass.getConstructor(String.class, int.class); Person ppp = (Person)ccc.newInstance("张三",122); System.out.println(ppp); //获取所有包括private的构造方法 Constructor[] conss = personClass.getDeclaredConstructors(); for(Constructor co: conss ) { System.out.println(co); } //获取私有构造方法 Constructor ct = personClass.getDeclaredConstructor(String.class); ct.setAccessible(true); Person ps = (Person)ct.newInstance("zhangsan"); System.out.println(ps.toString()); //获取所有公共成员变量 Field[] fis = personClass.getFields(); for(Field fi : fis) { System.out.println("成员变量:"+fi); } //获取私有成员变量 Field fd = personClass.getDeclaredField("name"); System.out.println(fd); //修改成员变量的值 Object obj = personClass.newInstance(); fd.set(obj, "哈哈"); fd.setAccessible(true); System.out.println(obj); //获取所有公共成员方法 Method[] md = personClass.getMethods(); for(Method m : md) { System.out.println("所有公共成员方法:"+m); } //获取单个无参成员方方法 Method mt = personClass.getMethod("say"); mt.invoke(personClass.newInstance()); //获取单个有参成员方法,并运行 Method me = personClass.getMethod("say", String.class); Object objd = personClass.newInstance(); Object ob = me.invoke(objd, "Hello World"); System.out.println(ob); //反射泛型的擦除 List<String> list = new ArrayList<String>(); //正常情况只能存String类型,但是通过反射可以存其他类型 Class li = list.getClass(); Method mmm = li.getMethod("add", Object.class); mmm.invoke(list, 1000); mmm.invoke(list, 444); mmm.invoke(list,999L); mmm.invoke(list, 'c'); System.out.println(list); } } 通过读取配置文件,用反射调用成员方法,更加灵活。不同的成员方法如下:人类对象package learn.javase.mycalss; public class People { public void say() { System.out.println("我是人类"); } } 学生对象package learn.javase.mycalss; public class Student { public void stay() { System.out.println("我要学习"); } } 打工人对象package learn.javase.mycalss; public class Worker { public void job() { System.out.println("我要工作"); } } iconfig.properties配置文件如下:#className=learn.javase.mycalss.People #classMethod=say className=learn.javase.mycalss.Student classMethod=stay #className=learn.javase.mycalss.Worker #classMethod=job通过反射,调用不同对象的成员方法,每次只需要修配置文件即可,不需要修改代码。代码如下:package learn.javase.mycalss; import java.io.FileReader; import java.lang.reflect.Method; import java.util.Properties; /** * 读取配置文件,通过反射调用不同对象的成员方法 * @author Jole * */ public class ConfigPropertiesRun { public static void main(String[] args) throws Exception{ //读取配置文件,注意配置文件路径为src下 FileReader fr = new FileReader("iconfig.properties"); Properties pr = new Properties(); pr.load(fr); fr.close(); //获取配置文件数据 String className = pr.getProperty("className"); String classMethod = pr.getProperty("classMethod"); //反射,并获取对象 Class c = Class.forName(className); Object obj = c.newInstance(); //反射获取成员方法 Method m = c.getMethod(classMethod); //反射调用成员方法 m.invoke(obj); } }
2022年02月28日
243 阅读
0 评论
0 点赞
2022-02-28
JAVA多线程
进程:CPU为每个应用程序分配的独立空间,一个进程可能有多个线程。进程为线程中的摸个执行任务程序,多个进程之间可以进行共享数据。而JAVA的线程则是由JVM进程分配的,main方法所在线程,则成为主线程。〇、线程状态正常情况线程执行步骤:新建-》运行-》死亡当CPU资源不够时,CUP分配给各个线程的资源可能不同(貌似有点像是线程在抢资源,实际是CPU分配资源给每个线程)。因此就会出现线程的阻塞、休眠、等待3个状态。其中阻塞状态,当cpu资源够时,阻塞状态的线程可能恢复到运行状态,而休眠、等待的线程也可能进入运行状态。休眠、等待状态可能转换成阻塞状态,但是阻塞状态不会变成休眠、等待状态。一、多线程的实现0、线程常用方法package learn.javase.threads; /** * 继承Thread创建线程,设置线程名称、获取线程名称 * @author Jole * */ public class ThreadDemo01 { public static void main(String[] args) { MyThreadsDemo mt = new MyThreadsDemo(); mt.setName("Hi"); mt.start(); //获取当前线程 Thread t = Thread.currentThread(); System.out.println(t.getName()); } }线程实现方式主测试类:package learn.javase.threads; public class MyThreadsDemo extends Thread{ public MyThreadsDemo() { super("Google"); } public void run() { for(int i=0;i<5;i++) { try { Thread.sleep(1000); System.out.println(i); }catch(Exception e) { System.out.println(e.getMessage()); } } } }线程测试主类:package learn.javase.threads; /** * 实现多线程的4中方式: * 1、继承Thread类 * 2、实现Runnable接口 * 3、匿名内部类 * 4、匿名接口 * 5、实现Callable接口,与Runnable的区别: * 可以有返回值 * 可以抛异常 * @author Jole * */ public class ThreadNumberDemo { public static void main(String[] args) { // TODO Auto-generated method stub //方式1,继承Thread new ThreadThread1().start(); //方式2,实现Runnable接口 new Thread(new ThreadRunnables2()).start(); //方式3,匿名内部类 new Thread() { public void run() { System.out.println("匿名内部类,实现多线程"); } }.start(); //方式4,匿名接口 Runnable r = new Runnable() { public void run() { System.out.println("匿名接口,实现多线程"); } }; new Thread(r).start(); //方式4的简洁版 new Thread(new Runnable() { public void run() { System.out.println("匿名接口简洁版,实现多线程"); } }).start(); } }1、继承Threadpackage learn.javase.threads; /** * 方式一继承Thread实现多线程 * @author Jole * */ public class ThreadThread1 extends Thread{ public void run() { System.out.println("extends ....thread"); } }2、实现Runnable接口package learn.javase.threads; /** * 实现Runnable接口 * @author Jole * */ public class ThreadRunnables2 implements Runnable{ public void run() { System.out.println("runnable .. threads"); } }3、实现Callable通过使用线程池,实现Callable,主要用于有返回值和抛出异常的。如下的线程池实现。4、区别继承Thread接口与实现Runnable接口,实现多线程区别:1、单继承、多实现2、实现Runnable可以将线程与任务(run())解耦package learn.javase.threads; /** * 实现Runnable接口,创建线程。 * 继承Thread接口与实现Runnable接口,实现多线程区别: * 1、单继承、多实现 * 2、将线程与任务(run())解耦 * @author Jole * */ public class RunnableDemo { public static void main(String[] args) { // TODO Auto-generated method stub new Thread(new RunnableThreadDemo()).start(); for(int i=0;i<5;i++) { System.out.println("main..."+i); } } }线程实现类:package learn.javase.threads; public class RunnableThreadDemo implements Runnable{ public void run() { for(int i=0;i<5;i++) { System.out.println("run..."+i); } } }二、线程池1、线程池使用package learn.javase.threads; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 线程池 * @author Jole * */ public class ThreadPoolDemo { public static void main(String[] args) { //使用线程池工场Executors,创建线程池 ExecutorService es = Executors.newFixedThreadPool(2); //使用线程池,构造器为实现Runnable的接口,使用完后自动放回线程池 es.submit(new ThreadPoolThreas()); es.submit(new ThreadPoolThreas()); //如果线程池里面线程不够了,只有等待其它线程执行完后,在使用 es.submit(new ThreadPoolThreas()); //一般不用关闭线程池,特殊情况关闭线程池,可以使用 // es.shutdown(); } }线程池线程实现Runnable接口:package learn.javase.threads; public class ThreadPoolThreas implements Runnable{ public void run() { System.out.println(Thread.currentThread().getName()+"线程池的使用"); } }2、线程池-实现多线程package learn.javase.threads; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; /** * 通过线程池,实现Callable接口,实现多线程,并获取任务(run)返回值,和异常 * @author Jole * */ public class ThreadPoolDemo2 { public static void main(String[] args) throws Exception{ //使用线程池工场Executors创建线程池工场 ExecutorService es = Executors.newFixedThreadPool(2); //通过实现Callable实现线程,提交并返回Future对象 Future t = es.submit(new ThreadCallableDemo()); //通过get获取返回值 System.out.println(t.get()); } }实现类Callable接口类:package learn.javase.threads; import java.util.concurrent.Callable; /** * * @author Jole * 使用继承Callable<T>泛型接口,实现多线程,并使用线程池 */ public class ThreadCallableDemo implements Callable<String>{ public String call() { return "实现Callable接口"; } }3、实例实例1package learn.javase.threads; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; /** * 使用线程池实现异步提交求和:1+...100= 1+... 200= * 注意: * 有返回值 * 计算不同的值 * @author Jole * */ public class ThreadMainDemo1 { public static void main(String[] args) throws Exception{ //使用线程池工场Executors创建线程池 ExecutorService es = Executors.newFixedThreadPool(3); //使用线程池中的线程,并使用构造方法传参,求和并返回 Future<Integer> f =es.submit(new CallableDemo(100)); Future<Integer> f2 =es.submit(new CallableDemo(2100)); System.out.println("1+...100="+f.get()); System.out.println("1+...200="+f2.get()); //关闭线程池 es.shutdown(); } }实现类:package learn.javase.threads; import java.util.concurrent.Callable; /** * 通过实现Callable接口,及构造方法传参,并通过call返回值 * @author Jole * */ public class CallableDemo implements Callable<Integer>{ private int number; //创建构造方法,为了传参 public CallableDemo(int number) { this.number = number; } public Integer call() { int sum = 0; //使用构造方法传的参数求和并返回 for(int i=0;i<=number;i++) { sum=sum+i; } return sum; } }实例2:package learn.javase.threads; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; /** * 通过线程池,实现Callable接口,实现多线程,并获取任务(run)返回值,和异常 * @author Jole * */ public class ThreadPoolDemo2 { public static void main(String[] args) throws Exception{ //使用线程池工场Executors创建线程池工场 ExecutorService es = Executors.newFixedThreadPool(2); //通过实现Callable实现线程,提交并返回Future对象 Future t = es.submit(new ThreadCallableDemo()); //通过get获取返回值 System.out.println(t.get()); } }实现类:package learn.javase.threads; import java.util.concurrent.Callable; /** * * @author Jole * 使用继承Callable<T>泛型接口,实现多线程,并使用线程池 */ public class ThreadCallableDemo implements Callable<String>{ public String call() { return "实现Callable接口"; } }三、线程安全1、线程安全package learn.javase.threads; /** * 可能出现安全问题的情况:多线程,共享一个数据 * 线程安全问题,及解决办法加synchronized,实例:卖票 * @author Jole * synchronized解决线程安全问题,使用公式: * synchronized(锁(任意对象)){ * 代码块 * } * * 注意:因为加了锁,所以效率会降低,但是安全性得到了保证,效率低的原因如下: * 1、每次线程都会先判断是否有锁 * 2、获取锁 * 3、执行完代码块 * 4、执行完后,还会锁 * 5、在等下一个锁执行相同操作,相当于只能排队上一个厕所。 */ public class ThreadSeaerfDemo { public static void main(String[] args) { //多线程出现的安全问题,票有负数还在卖 // Tickets00 t = new Tickets00(); // Thread t0 = new Thread(t); // Thread t1 = new Thread(t); // Thread t2 = new Thread(t); // t0.start();t1.start();t2.start(); //原始代码 // Tickets01 t = new Tickets01(); // Thread t0 = new Thread(t); // Thread t1 = new Thread(t); // Thread t2 = new Thread(t); // t0.start();t1.start();t2.start(); //第一次优化代码:同步方法,同步锁对象为:this // Tickets02 t = new Tickets02(); // Thread t0 = new Thread(t); // Thread t1 = new Thread(t); // Thread t2 = new Thread(t); // t0.start();t1.start();t2.start(); //第一次优化代码:同步静态方法,同步锁对象为:类名.class Tickets03 t = new Tickets03(); Thread t0 = new Thread(t); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t0.start();t1.start();t2.start(); } }多线线程出现的问题package learn.javase.threads; /** 〇、原始多线程,会出现安全问题,会出现票卖完了还在卖,也就是会出现票为负数的情况 * @author Jole * */ public class Tickets00 implements Runnable{ //票的数量 private int ticket = 100; public void run() { while(true) { if(ticket>0) { //为了展示出现线程安全问题,此处让线程修改20毫秒 try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } //每次票减1 System.out.println(Thread.currentThread().getName()+ " " + ticket--); } } } }2、线程安全解决方案解决多线程问题方案使用同步锁,1、使用synchronized 2、使用Lock接口同步锁实现原理图:1、synchronized使用synchronized解决线程安全问题,使用公式: synchronized解决线程安全问题,使用公式: synchronized(锁(任意对象)){ 代码块 }1.1、synchronized加在外面:同步锁对象为objpackage learn.javase.threads; /** 一、原始线程同步解决,同步锁为obj * * synchronized解决线程安全问题,使用公式: * synchronized(锁(任意对象)){ * 代码块 * } * @author Jole * */ public class Tickets01 implements Runnable{ //票的数量 private int ticket = 100; Object obj = new Object(); public void run() { while(true) { //为了解决安全问题加入了synchronized关键字 synchronized (obj) { if(ticket>0) { //为了展示出现线程安全问题,此处让线程修改20毫秒 try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } //每次票减1 System.out.println(Thread.currentThread().getName()+ " " + ticket--); } } } } }1.2、synchronized加在非静态方法上:此时同步锁对象为thispackage learn.javase.threads; /** * 二、优化原始的线程安全解决办法,同步锁方法,同步锁对象为this * @author Jole * */ public class Tickets02 implements Runnable{ //总票数 private int tickets =100; //原始同步锁 // Object obj = new Object(); public void run() { bay(); } //第一次优化,将锁和代码块抽为一个方法,测试同步锁为obj // public void bay() { // while(true) { // synchronized (obj) { // if(tickets > 0) { // try { // Thread.sleep(20); // }catch(Exception e) { // e.printStackTrace(); // } // System.out.println(Thread.currentThread().getName()+" " +tickets-- ); // } // } // } // } //第二次进一步优化为,同步方法,此时同步锁为:this //测试就可以省去以前的obj对象的创建了,代码以前更占用少一点内存了 public synchronized void bay() { while(true) { if(tickets > 0) { try { Thread.sleep(20); }catch(Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" " + tickets--); } } } }1.3、synchronized加在静态方法上:此时同步锁对象为:类名.classpackage learn.javase.threads; /** * 静态同步方法,此时同步锁为:类名.class * 如此类中的同步锁对象是:Tickets03.class * @author Jole * */ public class Tickets03 implements Runnable{ //总票数 private static int tickets =100; public void run() { buy(); } //静态方法同步锁,此时代码的锁为:Tickets03.class public static synchronized void buy() { while(true) { if(tickets > 0) { try { Thread.sleep(20); }catch(Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" " + tickets--); } } } }2、Lock使用synchronized时,获取锁,释放锁都是JVM自动完成的,而通过Lock可以手动获取锁,释放锁。package learn.javase.threads; /** * 手动获取锁,释放锁 * @author Jole * */ public class ThreadShouDong { public static void main(String[] args) { ThreadRunnableDemo01 t = new ThreadRunnableDemo01(); Thread t0 = new Thread(t); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t0.start(); t1.start(); t2.start(); } }Lock接口实现类:package learn.javase.threads; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 手动获取锁,释放锁 * @author Jole * */ public class ThreadRunnableDemo01 implements Runnable{ //票总数 private int tickets = 100; //锁 Lock接口的实现类ReentrantLock private Lock lock = new ReentrantLock(); public void run() { while(true) { //获取锁 lock.lock(); try { if(tickets > 0) { Thread.sleep(20); System.out.println(Thread.currentThread().getName()+" "+tickets--); } }catch(Exception e) { e.printStackTrace(); }finally { //释放锁 lock.unlock(); } } } }3、注意点使用多线程为了保证数据的安全性,加了synchronized或Lock保持同步,因此效率上就降低了。可能出现安全问题的情况:多线程,共享一个数据。使用synchronized时,同步锁必须保证为同一个同步锁对象才行。四、死锁死锁:多个线程,对方互相等待获取对方的锁。双方一直处于等待获取对方锁对象状态,也就是死锁。package learn.javase.threads; /** * 死锁:多个线程,对方互相等待获取对方的锁。双方一直处于等待获取对方锁对象状态,也就是死锁。 * @author Jole * */ public class DealThreadMainDemo { public static void main(String[] args) { // TODO Auto-generated method stub DetalThread death = new DetalThread(); Thread t0 = new Thread(death); Thread t1 = new Thread(death); t0.start(); t1.start(); } }同步锁对象A:package learn.javase.threads; /** * 同步锁A,对象 * @author Jole * */ public class LockA { private LockA() { }; public static final LockA lockA = new LockA(); }同步锁对象B:package learn.javase.threads; /** * 同步锁B,对象 * @author Jole * */ public class LockB { public LockB() { } public static final LockB lockB = new LockB(); }模拟出现死锁情况,实现类:package learn.javase.threads; public class DetalThread implements Runnable{ private int number = 0; public void run() { while(true) { if(number % 2 ==0) { synchronized (LockA.lockA) { System.out.println(Thread.currentThread().getName()+"线程,"+"第"+number+"次,"+"if抢到资源--获取到--同步锁A对象"); synchronized (LockB.lockB) { System.out.println(Thread.currentThread().getName()+"线程,"+"第"+number+"次,"+"if抢到资源--获取到--同步锁B对象"); } } }else { synchronized (LockB.lockB) { System.out.println(Thread.currentThread().getName()+"线程,"+"第"+number+"次,"+"else抢到资源--获取到--同步锁B对象"); synchronized (LockA.lockA) { System.out.println(Thread.currentThread().getName()+"线程,"+"第"+number+"次,"+"else抢到资源--获取到--同步锁A对象"); } } } number++; } } }注意获取的锁是那个。五、线程等待、唤醒实例:input拷贝数据对象,output输入对象:如果不是用线程等待与唤醒,出现问题:拷贝的数据太快,还来不及输出,可能出现输出的数据错乱。使用线程等待和唤醒,可以控制拷贝一个后,拷贝线程等待,然后输出线程输出,输出后,输出线程等待,然后拷贝线程唤醒,进行拷贝数据,依次循环。从而保证拷贝一个数据,输出一个数据。package learn.javase.threads; /** * 线程等待、唤醒: * 涉及同步锁是否是同一个锁,只有锁调用wait和notify才有效,不然抛出异常。 * 正常情况是交替出现,不会出现数据错乱情况。 * @author Jole * 本类是主测试类 * 该实例:input拷贝数据对象,output输入对象: * input可能出现拷贝对象拷贝很快,output输出对象很慢,导致output输出数据错乱,因此只能单个拷贝输出,且每次拷贝完后需wait等待,然后等输出完成后在拷贝。 * 因此需要拷贝完成后,等待,并唤醒输出,等输出完成前唤醒拷贝,然后自己在等待,然后拷贝又拷贝,然后又唤醒输出,如此循环。 * 实现方法加一个flag标记,是该拷贝还是输出 */ public class WatiNotifyThreadMainDemo { public static void main(String[] args) { //操作的是同一个对象锁,不然拷贝和输出都是用自己的锁this,也会发生数据错乱 ResourceData resource = new ResourceData(); //保证是同一个锁对象,所以都写了构造方法传入同一个锁对象 InputDemo input = new InputDemo(resource); OutputDemo output = new OutputDemo(resource); Thread t0 = new Thread(input); Thread t1 = new Thread(output); t0.start(); t1.start(); } }要拷贝的数据类:package learn.javase.threads; /** * 操作数据 * @author Jole * */ public class ResourceData { public String name; public String sex; public boolean flag; }拷贝线程:package learn.javase.threads; /** * 拷贝线程: * 当标记flag=true时,拷贝完成,需等待 * @author Jole * */ public class InputDemo implements Runnable { private ResourceData resourceData; public InputDemo(ResourceData resourceData) { this.resourceData = resourceData; } @Override public void run() { int number=0; while(true) { synchronized (resourceData) { //如果为ture拷贝完成,需等待 if(resourceData.flag) { try { resourceData.wait(); }catch(Exception e) { e.printStackTrace(); } } //拷贝值,比如写死拷贝张三,30岁,lishi,20岁 if(number % 2==0) { resourceData.name = "张三"; resourceData.sex = "男"; }else { resourceData.name = "Lishi"; resourceData.sex = "nv"; } //设置true,以便下次进入等待wait resourceData.flag = true; //唤醒输出线程 resourceData.notify(); } number++; } } }输出线程:package learn.javase.threads; /** * 输出线程: * 当标记flag=false时,输出完成,需等待 * @author Jole * */ public class OutputDemo implements Runnable { private ResourceData resourceData; public OutputDemo(ResourceData resourceData) { this.resourceData = resourceData; } @Override public void run() { while(true) { synchronized (resourceData) { //如果为false,则输出完成,等待 if(!resourceData.flag) { try { resourceData.wait(); }catch(Exception e) { e.printStackTrace(); } } //否则输出,并唤醒拷贝 System.out.println(resourceData.name+" .. "+ resourceData.sex); resourceData.flag = false; resourceData.notify(); } } } }
2022年02月28日
226 阅读
0 评论
1 点赞
2022-02-28
JAVA IO
将自己看作为程序,将数据输出到文件中,称之为输出。从文件读取数据到程序,称为输出。JAVA流操作主要分为字节流、字符流。字节流鼻祖:InputStream\OutpuStream 字符流鼻祖:Reader\WriterFile1、File常用方法package learn.javase; import java.io.File; /** * File常用操作 * @author Jole * */ public class FileDemo01 { public static void main(String[] args) { File file = new File("H://"); //此抽象路径名表示的文件或目录的名称;如果路径名的名称序列为空,则返回空字符串 System.out.println(file.getName()); //返回文件大小 System.out.println(file.length()); //返回绝对路径 System.out.println(file.getAbsolutePath()); //绝对路径名 System.out.println(file.getAbsoluteFile()); //父目录 System.out.println(file.getParentFile()); //是否存在 System.out.println(file.exists()); //是否是目录 System.out.println(file.isDirectory()); //返回路径下的文件或文件夹 System.out.println(file.list()); for(String path : file.list()) { //获取路径 System.out.println(path); } //可用的文件系统根 System.out.println("listRoots:"+file.listRoots()); for(File f : file.listFiles()) { System.out.println("111"+f); System.out.println(f.list()); System.out.println(f.length()); System.out.println("111"+f.listRoots()); } } }2、实例遍历所有文件package learn.javase; import java.io.File; /** * 遍历文件 * @author Jole * */ public class SearchFIles { public static void main(String[] args) { // TODO Auto-generated method stub File file = new File("H:\\"); findFile(file); } public static void findFile(File file) { System.out.println("--"+file); File[] array = file.listFiles(); for(File f : array) { if(f.isDirectory()) { findFile(f); }else { System.out.println(f); } } } }3、文件过滤器通过文件过滤器,查询所有.java文件package learn.javase; import java.io.File; /** * FileFilter文件过滤器 * @author Jole * */ public class FileFilterDemo01 { public static void main(String[] args) { File f = new File("H:\\"); File [] filsArray =f.listFiles(new MyFilter()); for(File file : filsArray) { System.out.println("路径: "+file+"大小: "+file.length()); } } }文件过滤器实现:package learn.javase; import java.io.File; import java.io.FileFilter; /** * 利用文件过滤器筛选文件FileFilter * @author Jole * */ public class MyFilter implements FileFilter{ @Override public boolean accept(File pathname) { return pathname.getName().endsWith(".java"); } }字节流字节输出流package learn.javase; import java.io.FileOutputStream; import java.io.IOException; /** * 字节输出流,写入文件 * @author Jole * */ public class FileOutpuStream { public static void main(String[] args) throws IOException{ FileOutputStream fos = new FileOutputStream("H://fileoutputstream.txt"); fos.write(2014); byte[] b = {66,67,68,69}; fos.write(b); fos.write(b,1,2); fos.write("Hello World".getBytes()); fos.close(); } }File对象:package learn.javase; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; /** * 字节输出流 * @author Jole * */ public class FileOutPutStream2 { public static void main(String[] args) throws IOException{ File f = new File("H://111.txt"); FileOutputStream fos = new FileOutputStream(f, true); fos.write("Hello\r\n".getBytes()); fos.write("World".getBytes()); fos.close(); } }字节输入流实例:利用字节输入输出流拷贝文件package learn.javase; import java.io.File; import java.io.FileInputStream; import java.io.IOException; /** * 利用字节输入输出流拷贝文件 * @author Jole * */ public class FileInPutStream02 { public static void main(String[] args) { // try { // getLdfdas(); // } catch (IOException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } getAll(); } private static void getLdfdas() throws IOException{ FileInputStream fis = new FileInputStream("H:\\222.txt"); //创建字节数组 byte[] b = new byte[1024]; int len = 0 ; while( (len = fis.read(b)) !=-1){ System.out.print(new String(b,0,len)); } fis.close(); } public static void getAll() { FileInputStream fis = null; try { fis = new FileInputStream("H:\\222.txt"); byte[] b = new byte[1024]; int len = 0; while( (len = fis.read(b)) !=-1) { System.out.println(new String(b,0,len)); } }catch(IOException e) { throw new RuntimeException("读取失败,请重试"); }finally { try { fis.close(); }catch(IOException ex) { throw new RuntimeException("流关闭失败"); } } } }异常处理package learn.javase; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; /** * 输出流异常处理 * @author Jole * */ public class IoTryCatch { public static void main(String[] args) { FileOutputStream fos = null; try { File f = new File("H://222.txt"); fos = new FileOutputStream(f, true); fos.write("Hello\r\nWorld".getBytes()); }catch(IOException e) { System.out.println(e.getMessage()); throw new RuntimeException("写入失败,请重试"); }finally { if(null!=fos) { try { fos.close(); }catch(IOException ex) { System.out.println(ex.getMessage()); throw new RuntimeException("关闭失败"); } } } } }实例利用字节流拷贝文件:package learn.javase; import java.io.FileInputStream; import java.io.FileOutputStream; /** * 基于输入、输出流的文件拷贝 * @author Jole * */ public class CopyFIleDemo { public static void main(String[] args) { copyFiles(); } public static void copyFiles() { FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream("H:\\1.exe"); fos = new FileOutputStream("D:\\new1.exe"); byte[] b = new byte[1024]; int len =0; while((len=fis.read(b))!=-1) { fos.write(b,0,len); } }catch(Exception e) { System.out.println(e.getMessage()); throw new RuntimeException("复制失败"); }finally { if(null!=fos) { try { fos.close(); }catch(Exception e) { throw new RuntimeException("输出流关闭失败"); }finally { try { if(null!=fis) { fis.close(); } }catch(Exception e) { System.out.println(e.getMessage()); throw new RuntimeException("输入流关闭失败"); } } } } } }字符流字节输出流package learn.javase; import java.io.FileWriter; import java.io.IOException; /** * 字符输出流,写文件 */ public class FileWriteDemo01 { public static void main(String[] args) throws IOException{ FileWriter fw = new FileWriter("H://write.txt"); char[] c = {'a','b','v','d'}; fw.write(c,1,2); fw.flush(); fw.close(); } }字符输入流package learn.javase; import java.io.FileReader; import java.io.IOException; /** * 字符输入流,读取文件 * @author Jole * */ public class FileReaderDemo { public static void main(String[] args) throws IOException{ FileReader fr = new FileReader("H:\\write.txt"); char[] c = new char[1024]; int len =0; while((len = fr.read(c)) != -1) { System.out.println(new String(c, 0, len)); } fr.close(); } }实例理由字符流拷贝文件:package learn.javase; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; /** * 利用字符输入流、字符输出流拷贝文本文件 * @author Jole * */ public class CopyTxtFile { public static void main(String[] args) { FileReader fr = null; FileWriter fw = null; try { fr = new FileReader("H:\\write.txt"); fw = new FileWriter("I:\\copytxt.txt"); char[] c = new char[1024]; int len =0; while((len = fr.read(c)) != -1) { fw.write(c, 0, len); fw.flush(); } System.out.println("文本文件复制成功"); }catch(Exception e) { throw new RuntimeException("复制失败,请重试!"); }finally { if(null != fw) { try { fw.close(); }catch(IOException e) { throw new RuntimeException("字符输入流关闭失败!"); }finally { if(null != fr) { try { fr.close(); }catch(IOException e) { throw new RuntimeException("字符输出流关闭失败!"); } } } } } } }转换流利用转换流InputStreamReader:将字节流转成字符流package learn.javase; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; /** * 利用转换流InputStreamReader:将字节流转成字符流 * @author Jole * 与字节流的区别在于可以设置写入、写出时文件的编码集 */ public class InputStreamReaderDemo01 { public static void main(String[] args) { try { myInputStreamReader(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void myInputStreamReader() throws IOException{ FileInputStream is = new FileInputStream("H:\\zz.txt"); InputStreamReader isr = new InputStreamReader(is, "GBK"); int len =0; char[] c = new char[1024]; while((len = isr.read(c)) != -1) { System.out.println(new String(c, 0 ,len)); } isr.close(); } }缓冲流缓冲流-字节输出流package learn.javase; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; /** * 字节缓冲输出流 * @author Jole * */ public class BufferedOutputStreamDemo01 { public static void main(String[] args) { try { bufferWriter(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void bufferWriter() throws IOException{ BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("H:\\c.txt")); bos.write("Hello world".getBytes()); bos.flush(); bos.close(); } }缓冲流-字节输入流package learn.javase; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; /** * 字节缓冲输入流,读取文件 * @author Jole * */ public class BufferInputStreamDemo { public static void main(String[] args) { // TODO Auto-generated method stub try { bufferInputTxt(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void bufferInputTxt() throws IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream("H:\\c.txt")); byte[] b = new byte[1024]; int len =0; while((len = bis.read(b)) != -1) { System.out.print(new String(b, 0 , len)); } } }缓冲流-字符输出流package learn.javase; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; /** * 字符缓冲输出流,独有writeLine()换行与平台无关 * @author Jole * */ public class BufferWriterDemo01 { public static void main(String[] args) { try { bufferWrited(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void bufferWrited() throws IOException{ BufferedWriter bw = new BufferedWriter(new FileWriter("H:\\zxw.txt")); bw.write("Hello World"); bw.newLine(); bw.flush(); bw.close(); } }缓冲输-字符输入流package learn.javase; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; /** * 字符缓冲输入流,独有readlin方法 * @author Jole * */ public class BufferedReaderDemo02 { public static void main(String[] args) { try { bufferReadered(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void bufferReadered() throws IOException{ int n=0; BufferedReader br = new BufferedReader(new FileReader("H:\\zxw.txt")); String len =null; while((len = br.readLine()) != null) { n++; System.out.println(n+"\t"+len); } br.close(); } }对象流序列化利用对戏那个输入输出流,进行序列化与反序列化package learn.javase; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /** * 利用对戏那个输入输出流,进行序列化与反序列化 * 实现Serializable接口的目的是为了可以被序列化, * transient关键字标记的标量 不会被序列化 * @author Jole * */ public class ObjectLiu { public static void main(String[] args) throws IOException,ClassNotFoundException{ //序列化 // objectOutputStreamInfo(); //反序列化 objectinputStreamInfo(); } public static void objectOutputStreamInfo() throws IOException{ ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("H:\\z2.txt")); Persion persion = new Persion("zhangsan",30); oos.writeObject(persion); oos.close(); } public static void objectinputStreamInfo() throws IOException,ClassNotFoundException{ ObjectInputStream ois = new ObjectInputStream(new FileInputStream("H:\\z2.txt")); Persion persion = (Persion)ois.readObject(); System.out.println(persion); ois.close(); } }实现Serializable接口的目的是为了可以被序列化:package learn.javase; import java.io.Serializable; /** * 实现Serializable接口的目的是为了可以被序列化, * transient关键字标记的标量不会被序列化 * @author Jole * */ public class Persion implements Serializable{ /** * */ private static final long serialVersionUID = 2056540569585913293L; private String name; private transient int age; public Persion(String name, int age) { super(); this.name = name; this.age = age; } public Persion() { super(); // TODO Auto-generated constructor stub } 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; } @Override public String toString() { return "Persion [name=" + name + ", age=" + age + "]"; } }打印流利用打印流复制文件:设计打印机流自动刷新(流对象才支持自动刷新,File、字符串不支持自动刷新)package learn.javase; import java.io.BufferedReader; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; /** * 利用打印流复制文件:设计打印机流自动刷新(流对象才支持自动刷新,File、字符串不支持自动刷新) * PrintStream\PrintWriter * @author Jole * */ public class PrintLiu { public static void main(String[] args) throws IOException{ copyFiles(); } public static void copyFiles() throws IOException{ BufferedReader br = new BufferedReader(new FileReader("H:\\zz.txt")); PrintWriter pw = new PrintWriter(new FileWriter("D:\\zz.txt")); String len = null; while((len = br.readLine()) != null) { pw.println(len); } pw.close(); br.close(); } }Properties读取Properties文件的值和写入值package learn.javase; import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.util.Properties; /** * Properties的load(),store方法 * 读取Properties文件的值和写入值 * @author Jole * */ public class PropertiesDemo { public static void main(String[] args) throws IOException{ function(); } public static void function() throws IOException{ Properties pro = new Properties(); FileInputStream fs = new FileInputStream("H:\\pro.properties"); pro.load(fs); fs.close(); FileWriter fw = new FileWriter("H:\\1.properties"); pro.store(fw, "add"); fw.close(); System.out.println(pro); } }开源工具Commons-IOFilenameUtilspackage learn.javase.utils; import org.apache.commons.io.FilenameUtils; /** * Commons-io工具类 FilenameUtis常用方法 * @author Jole * */ public class CommonsIODemo { public static void main(String[] args) { //打印后缀,没有则为空 String name = FilenameUtils.getExtension("demo.java"); System.out.println(name); //获取文件名 String fileName = FilenameUtils.getName("H:\\z.txt"); System.out.println(fileName); //判断后缀名 boolean Extension = FilenameUtils.isExtension("World.java", "java"); System.out.println(Extension); } }FileUtilspackage learn.javase.utils; import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; /** * 利用开源工具Commons-IO中的FileUtils工具类进行文件的常规操作 * @author Jole * */ public class CommonsIOFileUtils { public static void main(String[] args) throws IOException{ //读文件 String string = FileUtils.readFileToString(new File("H:\\zz.txt")); System.out.println(string); //写文件 FileUtils.writeStringToFile(new File("H:\\cc.txt"), "Look ME"); //复制文件 FileUtils.copyFile(new File("H:\\z.txt"), new File("D:\\xx.txt")); //复制文件夹 FileUtils.copyDirectoryToDirectory(new File("H:\\a"), new File("D:\\a")); } }注意点1、每种流的特有方法2、异常的处理3、一定要关闭流4、哪种情况选择哪种流
2022年02月28日
539 阅读
0 评论
7 点赞
2022-02-28
JAVA异常
异常ThrowableThrowable类是所有错误跟异常类的超类.ExceptionException异常类及其子类都是继承自Throwable类,用来表示java中可能出现的异常,并且合理的处理这些异常。RuntimeExceptionRuntimeException类是运行异常类,继承自Exception类,它以及它的子类只能在运行过程中存在,当出现时,只能修改源代码,此异常无法处理。特点: 方法中抛出运行时期异常,方法定义中无需throws声明,调用者也无需处理此异常 运行时期异常一旦发生,需要程序人员修改源代码ErrorError类是与Exception的平级的类,用来表示Java中存在的严重错误,只能通过修改代码来解决问题。区别Exception与Error区别:Exception是指程序在编译或者运行时出现的某种异常问题,我们可以对异常进行某种处理,如果不处理异常的话,程序将会停止运行。 Error是指程序在运行时出现的严重问题,无法处理,程序将会停止运行,Error通常都是系统级别的问题,都是虚拟机jvm所在系统发生的,只能通过修改源代码解决问题。异常的产生运行或编译时产生异常。创建异常类的对象。声明异常类。将异常类对象传给调用者(main()方法)处理。调用者无法处理,再将异常类对象传给jvm虚拟机。jvm虚拟机将异常类的信息(名称、详细信息、异常所处的位置)打印在屏幕上,并且停止程序的运行。抛出异常throw在java中,提供了一个throw关键字,用来抛出一个指定的异常。使用方法:1.创建一个异常对象。封装一些提示信息2.将这个异常告知调用者使用格式:throw new 异常类名(参数);声明异常throws声明异常格式:修饰符 返回值类型 方法名称 (参数)throws 异常1名称,异常2名称{}捕获异常try...catch...finally捕获异常:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理语句格式:ry { //需要被检测的语句。 }catch(异常类 变量) { //参数。 //异常的处理语句。 }finally { //一定会被执行的语句。 }try:该代码块中编写可能产生异常的代码。catch:用来进行某种异常的捕获,实现对捕获到的异常进行处理。finally:有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。捕获异常的组合方式try catch finally组合:检测异常,并传递给catch处理,并在finally中进行资源释放。try catch组合: 对代码进行异常检测,并对检测的异常传递给catch处理。对异常进行捕获处理。一个try 多个catch组合: 对代码进行异常检测,并对检测的异常传递给catch处理。对每种异常信息进行不同的捕获处理。注意:这种异常处理方式,要求多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。try finally 组合: 对代码进行异常检测,检测到异常后因为没有catch,所以一样会被默认jvm抛出。异常是没有捕获处理的。但是功能所开启资源需要进行关闭,所有finally。只为关闭资源。package learn.javase; /** * 异常的抛出(throw)与声明(throws) * @author Jole * */ public class ThrowsDemo { public static void main(String[] args){ String[] str = {}; // System.out.println(throwT(null)); System.out.println(throwT2(null)); } public static int throwT(String[] arr) throws NullPointerException{ if(arr==null) { throw new NullPointerException("数组不能为空!"); } int num = arr.length; return num; } public static int throwT2(String[] arr){ int num =0; try { num = arr.length; }catch(Exception e) { System.out.println(e.toString()); }finally { System.out.println("hhhhh"); } return num; } }自定义异常package learn.javase; /** * 自定义异常,需集成RuntimeException运行时异常 * @author Jole * */ public class TrcyTest { public static void main(String[] args) { getEx(1); } public static void getEx(int ... num){ for(int i : num) { if(i==1) { throw new TryDemoException("不能等于1"); } } } }自定义异常需要继承RuntimeExceptionpackage learn.javase; /** * 抛出异常 new 异常名称,继承RuntimeException运行时异常 * @author Jole * */ public class TryDemoException extends RuntimeException{ public TryDemoException(String s) { super(s); } }子父类异常子类覆盖父类方法时,如果父类的方法声明异常,子类只能声明父类异常或者该异常的子类,或者不声明。package learn.javase; /** * 子夫类异常 * 1. 子类覆盖父类方法时,如果父类的方法声明异常,子类只能声明父类异常或者该异常的子类,或者不声明。 * 2. 当父类方法声明多个异常时,子类覆盖时只能声明多个异常的子集。 * 3. 当被覆盖的方法没有异常声明时,子类覆盖时无法声明异常的。 * @author Jole * */ public class ZifuException extends FuException{ //抛出父类一样的异常 public void method() throws RuntimeException { } //抛出父类子异常 public void method2() throws NullPointerException{ } }父类:package learn.javase; public class FuException { public void method () throws RuntimeException { } }当父类方法声明多个异常时,子类覆盖时只能声明多个异常的子集。package learn.javase; /** * 子类异常 * @author Jole * */ public class Zexception extends Fexception{ //抛出父类全部异常 public void method() throws NullPointerException, ClassCastException { } //抛出父类异常中的一部分 // public void method() throws NullPointerException{ // } //抛出父类异常中的一部分 // public void method() throws ClassCastException { // } }父类异常:package learn.javase; /** * 父类抛出多个异常 * @author Jole * */ public class Fexception { public void method () throws NullPointerException, ClassCastException{ } }当被覆盖的方法没有异常声明时,子类覆盖时无法声明异常的。package learn.javase; public class Zi extends Fu{ //错误的方式,会报错。 public void method() throws Exception { } }父类:package learn.javase; public class Fu { public void method (){ } }
2022年02月28日
217 阅读
0 评论
1 点赞
2022-02-28
JAVA数组
JAVA数组重点掌握知识,以后肯定会用到的,可以了解一下底层原理。数组是指一组数据的集合,数组中的每个数据被称作元素。在数组中可以存放任意类型的元素,但同一个数组里存放的元素类型必须一致。数组数组定义格式:数据类型[] 数组名(变量名) = new 数据类型[元素个数或数组长度];实例:public class ArrayDemo01 { public static void main(String[] args) { int[] x = new int[100]; } }注意:数组定长,一但定义长度为100,在使用时大小就是100了。不变量。数组特点:定长、引用类型。JVMjava程序运行时,操作系统会给jvm虚拟机分配一块内存。JVM又会将这块内存,进行划分管理。JVM内存划分:JVM对自己的内存进行了划分,分成5个区域。1、寄存器:内存和CPU之间。 2、本地方法栈:JVM调用操作系统中的功能。 3、方法和数据共享:运行时其class文件,进入的地方。 4、方法栈:所有的方法运行的时候,进入的内存。 5、堆:存储的是容器和对象。开发人员主要关心:方法和数据共享、方法栈、堆。数组内存划分首先,运行class文件,所以先进入方法区。运行main方法,在方法栈中运行,但是main用不了那么多,所以方法栈中会分配一块给main方法是用。执行数组,一个容器,所以JVM在堆内存,开空间,存储数组容器。JVM会将该地址,给定义的数组变量arr(相当于arr引用了这个地址),所以数组是引用类型。每次运行,JVM分配的地址是不同的。当main方法运行完了,arr变量就没了,然后new int[3]也就没了 ,JVM垃圾回收机制,会自动帮我们回收,不用我们去处理了。堆空间太大,怎么找到这个容器呢,所以每个数组,在内存中,都有自己的内存地址,也就是数组元素的首地址,第一个数据的地址。注意:arr引用类型,保存的数据,实际上是内存中的地址。数组元素的访问数组是一个容器,存储到数组中的每个元素,都有自己的自动编号/下标(专业名词:索引)。访问数组存储的元素,必须依赖索引。访问公式:数组名[索引]public class ArrayDemo02 { public static void main(String[] args) { int[] arr = new int[3]; System.out.println(arr[0]); System.out.println(arr[1]); System.out.println(arr[2]); } }一初始化时,数组里面就有了默认值。注意:数组索引是从0开始的。当数组被成功创建后,数组中元素会被自动赋予一个默认值,根据元素类型的不同,默认初始化的值也是不一样的。byte、short、int、long:默认值0 float、double:默认值0.0 char:默认值一个空字符(空格),即’\u0000’ boolean:默认值false 引用数据类型:null,表示变量不引用任何对象数组的属性数组的长度length:使用方法:数组名.lengthpublic class ArrayDemo02 { public static void main(String[] args) { int[] arr = new int[3]; System.out.println(arr[0]); System.out.println(arr[1]); System.out.println(arr[2]); System.out.println(arr.length); } }注意:length是int类型,因此数组最大索引为:数组名.length-1数组中最小的索引是0,最大的索引是“数组的长度-1”。在Java中,为了方便我们获得数组的长度,提供了一个length属性,在程序中可以通过“数组名.length”的方式来获得数组的长度,即元素的个数。数组初始化在定义数组时只指定数组的长度,由系统自动为元素赋初值的方式称作动态初始化。数组的静态初始化方式一:数据类型[] 变量名 = new 数据类型[]{元素1,元素2,元素3...};方式二:数据类型[] 变量名 = {元素1,元素2,元素3,...};public class ArrayDemo03 { public static void main(String[] args) { //定义方式一 int[] arr = new int[] {1,3,4,5}; System.out.println(arr.length); //注意:new 后面的中括号中,不允许写任何内容,写了就编译失败。 //错误实例: //int[] arr = new int[4]{1,2,3,4}; //定义方式二(这种比较简单,常用) int[] arr2 = {1,2,3,4,}; //注意:最后一个逗号,会自动去掉 System.out.println(arr2.length); } }注意:第3行代码千万不可写成int[] arr = new int[4]{1,2,3,4};,这样写编译器会报错。原因在于编译器会认为数组限定的元素个数[4]与实际存储的元素{1,2,3,4}个数有可能不一致,存在一定的安全隐患。数组元素赋值public class ArrayDemo04 { public static void main(String[] args) { //没有赋值的元素,都是默认值 int[] arr = new int[3]; arr[2] =5; System.out.println(arr[0]); System.out.println(arr[1]); System.out.println(arr[2]); } }注意:如果在使用数组时,不想使用这些默认初始值,也可以显式地为这些元素赋值,如上代码。数组的遍历遍历:通过索引的方式,将数组中的每个元素,分别获取出来。public class ArrayDemo05 { public static void main(String[] args) { int[] arr = {1,2,4,52,4,3,6,}; System.out.println(arr[0]); System.out.println(arr[1]); System.out.println(arr[2]); System.out.println(arr[3]); //...... //如果有几千个,这样肯定不行,索引是依次加1的,因此可以用到循环来变量。 //for:知道循环次数,计数器思想 //while:不确定循环次数。 for(int i=0;i<arr.length;i++) { System.out.println(arr[i]); } } }输出结果:1 2 4 52 1 2 4 52 4 3 6注意://for:知道循环次数,计数器思想//while:不确定循环次数。会自动去掉最后一个逗号。数组中常见异常数组索引越界异常public class ArrayError { public static void main(String[] args) { int[] arr = {1,2,4,}; //1、数组索引越界异常 System.out.println(arr[3]); System.out.println(arr[-2]); } }输出结果,编译时不出错,运行时,错误提示信息:Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:错误原因:索引越界、索引为负数。空指针异常public class ArrayError { public static void main(String[] args) { //2、空指针异常 int[] arr2 = {2,345,4}; System.out.println(arr2[2]);; arr2 = null;//arr2不在保持数组的地址了 System.out.println(arr2[2]); } }空指针内存运行说明:步骤1:int[] arr2 = {1,5,8},存在于栈中 步骤2:同时在堆中开辟一块内存空间存储数据,并分配一个地址,如图右边。 步骤3:arr2变量,引用执行该存储空间地址。 上面3步是正常情况。 步骤4:当执行arr2=null时,arr2引用就没有了指向的空间地址。 步骤5:打印的数组的时候就会出现空指针异常了。输出结果:错误提示信息Exception in thread "main" java.lang.NullPointerException错误原因:数组变量为null注意:内存地址只能给一次,不能给第2次地址。因为为null空指向断了,JVM可能已经将堆地址内存释放掉了,不能再给回来。数组获取最值获取最值的原理思想:找到数组中的最大值或最小值,然后做比较。最大值或最小值比较思想:将最大值放到一个变量中,赋值为第一个元素,每次将这个值与其他元素比较,将大的给这个值,最后这个就是最大值。最小值同理。public class ArrayDemo05 { public static void main(String[] args) { int[] arr = { 4, 1, 6, 3, 9, 8 }; // 定义一个数组 int max = arr[0]; // 定义变量max用于记住最大数,首先假设第一个元素为最大值 // 下面通过一个for循环遍历数组中的元素 for (int x = 1; x < arr.length; x++) { if (arr[x] > max) { // 比较 arr[x]的值是否大于max max = arr[x]; // 条件成立,将arr[x]的值赋给max } } System.out.println("max=" + max); // 打印最大值 } }说明:1、定义了一个临时变量max,用于记住数组的最大值。通过for 循环获取数组中的最大值,赋值给max变量。 2、首先假设数组中第一个元素arr[0]为最大值。 3、使用for循环对数组进行遍历,在遍历的过程中只要遇到比max值还大的元素,就将该元素赋值给max。 4、这样一来,变量max就能够在循环结束时记住数组中的最大值。需要注意的是,在for循环中的变量i是从1开始的,这样写的原因是程序已经假设第一个元素为最大值,for循环中只需要从第二个元素开始比较,从而提高程序的运行效率。二维数组二维数组的定义有很多方式,几种常见的方式。第一种方式:int[][] arr = new int[3][4];上面的代码相当于定义了一个3*4的二维数组,即二维数组的长度为3,二维数组中的每个元素又是一个长度为4的数组,接下来通过一个图来表示这种情况,如下图所示。第二种方式:int[][] arr = new int[3][];第二种方式和第一种类似,只是数组中每个元素的长度不确定.第三种方式:int[][] arr = {{1,2},{3,4,5,6},{7,8,9}};上面的二维数组中定义了三个元素,这三个元素都是数组,分别为{1,2}、{3,4,5,6}、{7,8,9}。对二维数组中元素的访问也是通过角标的方式,如需访问二维数组中第一个元素数组的第二个元素,具体代码如下:arr[0][1];操作二维数组时,经常需要获取数组中元素的值。public class TwoArrayDemo { public static void main(String[] args) { //二维数组创建方式 //方式一 int[][] arr = new int[2][3]; //方式二 int[][] arr2 = new int[2][]; arr2[0] = new int[5]; arr2[1] = new int[1]; //方式三 int[][] arr3 = {{2,4,5},{1,2},{6,3,5,5}}; //这种方式最简单,最常用。 } }二维数组内存分配:public class TwoArrayDemo { public static void main(String[] args) { int[][] arr3 = {{2,4,5},{1,2},{6,3,5,5}}; //二维数组的访问 System.out.println(arr3[2][2]); //二维数组的遍历 for(int i=0;i<arr3.length;i++) { for(int j=0;j<arr3[i].length;j++) { System.out.print(arr3[i][j]); } System.out.println(); } } }
2022年02月28日
292 阅读
0 评论
1 点赞
2022-02-28
JAVA基础(第二篇)
JAVA流程控制语句JAVA中非常重要的基础知识点务必完全理解掌握,总结记录一下之前学习笔记。JAVA流程控制语句是编程的基础知识,主要是为了更好的组织代码的执行流程,下面将详细介绍java流程控制语句。一、选择结构ifif条件语句分为三种格式。if语句如果满足某种条件就执行。if语句格式:if(条件){ 语句的执行体 }条件:结果必须是布尔类型 1==1 true || false执行体:当id条件为true的时候,执行大括号中的语句,否则什么都不做。例如:/** * if语句例子 */ public class IfDemo { public static void main(String[] args) { // TODO Auto-generated method stub int i = 5; if(i==5) { System.out.println("if中的条件是true"); i++; } System.out.println("i="+i); } }注意:if()括号后面没有分号";"if...else语句如果满足某种条件,就执行某种处理,否则就执行另一种处理。if ... else语法格式:if(条件){ if的执行体 }else{ else的执行体 }当if中的条件为true时,执行if的执行体,为false时,执行else的执行体。例如:** * if ... else 语句 * */ public class IfElseDemo { public static void main(String[] args) { int i = 13; if(i%2==0) { System.out.println(i+"是偶数"); }else { System.out.println(i+"是奇数"); } } }if...else if...else语句用于多条件进行判断,进行多种不同的处理。语句格式:if(条件1){ 执行语句1 }else if(条件2){ 执行语句2 } ... else if(条件n){ 执行语句n }else{ 执行语句n+1 }当判断条件1为true时,if后面{}中的执行语句1会执行。当判断条件1为false时,会继续执行判断条件2,如果为true则执行语句2,以此类推,如果所有的判断条件都为false,则意味着所有条件均未满足,else后面{}中的执行语句n+1会执行。注意:条件最后都是boolean值,要么true要么false。例如: package java_learn_code; import java.util.Scanner; /** * if...else if...else * 多条件判断 */ public class IfElseIfElseDemo { public static void main(String[] args) { while(true) { System.out.print("请输入分数:"); Scanner scan = new Scanner(System.in); double sum = scan.nextDouble(); if(sum<90) { System.out.print("可以哦"); }else if(sum <=80) { System.out.println("合格"); }else if(sum <=60){ System.out.println("不及格"); }else { System.out.println("分数有问题"); } System.out.println(""); } } }注意:if...else只能进行单条件判断,而if...else if...else可以进行多条件进行判断了。if..else也可以实现,但是效率没有if..else .. if ... else效率高。二、三元运算符三元运算符得到一个结果,通常用于对某个变量进行赋值,当判断条件成立时,运算结果为表达式1的值,否则结果为表达式2的值。三元运算符和if...else类似,语法如下:判断条件 ? 表达式1 : 表达式2例如:package java_learn_code; /** * if..else 与三元运算符的转换 */ public class IfAllDemo { public static void main(String[] args) { int m = 10; int n = 8; //if...else运算 if(m>n) { System.out.println(m); }else { System.out.println(n); } //三元运算符运算 System.out.println(m>n ? m : n); } }注意:如果判断条件比较多,使用三元运算符,是必须有结果的,而if语句可以没有结果的。三、循环语句whilewhile语句会反复地进行条件判断,只要条件成立,{}内的执行语句就会执行,直到条件不成立,while循环结束。while循环语句的语法结构:while(循环条件){ 执行语句 ……… }说明:{}中的执行语句被称作循环体,循环体是否执行取决于循环条件。当循环条件为true时,循环体就会执行。循环体执行完毕时会继续判断循环条件,如条件仍为true则会继续执行,直到循环条件为false时,整个循环过程才会结束。例如:/** * while循环语句 */ public class WhileDemo { public static void main(String[] args) { int i = 0; while(i<5) { System.out.println("i="+i); i++; } } }注意:i++用于在每次循环时改变变量i的值,从而达到最终改变循环条件的目的。如果没有这行代码,整个循环会进入无限循环的状态,永远不会结束。四、循环语句for语法格式:for(初始化表达式; 循环条件; 操作表达式){ 执行语句 ……… }说明:初始化变量:定义变量,用于控制循环的次数。条件:当条件是true的时候,执行循环体,为false时,结束循环。增量:变量自增情况/** * for循环 * @author Jole * */ public class ForDemoOne { public static void main(String[] args) { //1、变量 2、条件 3、增量 for(int i=0;i<5;i++) { System.out.println("i="+i); //两大括号之间:4、循环体 } } }执行过程:第一步:变量定义i,在整个循环中,只会执行一次(int i=0,在整个过程中至执行一次)。 第二步:如果条件为false,整个循环就结束了。 第三步:如果为true时,执行循环体。 第四步:增量,i++ 第五步:重复走条件(第二步或第三步) 后面继续循环 注意:int i=0;终其一生只运行一次。条件为false时,不会在走增量,而是直接结束了注意:int i=0;终其一生只运行一次。条件为false时,不会在走增量,而是直接结束了。分析for循环的执行流程:for(1 ; 2 ; 3){ 4 } 第一步,执行1 第二步,执行2,如果判断结果为true,执行第三步,如果判断结果为false,执行第五步 第三步,执行4 第四步,执行3,然后重复执行第二步 第五步,退出循环注意事项:1、初始化表达式、循环条件和操作表达式,它们之间用“;”分隔,{}中的执行语句为循环体。 2、int i=0;终其一生只运行一次。 3、条件为false时,不会在走增量i++,而是直接结束了。实例:用for循环进行累加求和。1+2+3+4...+100=?/** * 用for循环进行累加求和,1+2+3+4...+100=? */ public class ForSum { public static void main(String[] args) { int sum = 0; for(int i=1;i<=100;i++) { sum += i; } System.out.println("sum="+sum); } }五、do...while()循环do…while循环语句和while循环语句功能类似。语法格式:do { 执行语句 ……… } while(循环条件);说明:关键字do后面{}中的执行语句是循环体。do…while循环语句将循环条件放在了循环体的后面。意味着,循环体会无条件执行一次,然后再根据循环条件来决定是否继续执行。public class DowhileDemo { public static void main(String[] args) { int i = 1; do { i++; }while(i<0); System.out.println("i="+i); } }注意:无论条件是否成立,都会执行一次循环体。do …while循环和while循环能实现同样的功能,区别在于,如果循环条件在循环语句开始时就不成立,那么while循环的循环体一次都不会执行,而do…while循环的循环体还是会执行一次。(无论条件是否成立,do...while都会执行一次循环体)六、死循环(无限循环)最简单无限循环格式:while(true){} 或 for(;;){}注意:无限循环存在的原因是并不知道循环多少次,而是根据某些条件,来控制循环。/** * while、for死循环 */ public class DeadDemo { public static void main(String[] args) { //while死循环 while(true) { } //for死循环(注意:上面的while死循环,这个for死循环不会执行) for( ;true ; ) { } } }注意:上面的while死循环,这个for死循环不会执行。七、循环嵌套嵌套循环是指在一个循环语句的循环体中再定义一个循环语句的语法结构。while、do…while、for循环语句都可以进行嵌套,并且它们之间也可以互相嵌套。在for循环中嵌套for循环,格式如下:for(初始化表达式; 循环条件; 操作表达式) { ……… for(初始化表达式; 循环条件; 操作表达式) { 执行语句 ……… } ……… }嵌套循环的执行顺序:public class ForForDemoTwo { public static void main(String[] args) { for(int i = 0;i < 2;i++) { for(int j = 0; j<2 ;j++) { } } } }执行顺序说明:1.i=0 2.i<2 3.执行循环体j=0 4.j<2 5.执行内循环的循环体 6.j++ 1 7.j<2 8.执行内循环的循环体 9.j++ 10.j<2 内循环结束 11.外循环的增量i++ 1 12.i<2 执行3到10步骤 13.外循环的增量i++ 2 14.i<2注意:循环次数=外循环次数*内循环次数。内循环是外循环的一个循环体。嵌套循环:主要是理解执行顺序实例:打印三角形public class ForForDemo { public static void main(String[] args) { for(int i=1;i<=5;i++) { for(int j=1;j<i;j++) { System.out.print("* "); } System.out.println("*"); } } }输出结果:``` * * * * * * * * * * * * * * *八、跳转语句(break、continue)跳转语句用于实现循环执行过程中程序流程的跳转,在Java中的跳转语句有break语句和continue语句。break语句1、在switch条件语句和循环语句中都可以使用break语句。当它出现在switch条件语句中时,作用是终止某个case并跳出switch结构。 2、当它出现在循环语句中,作用是跳出循环语句,执行后面的代码。 public class BreakDemo { public static void main(String[] args) { int i=1; while(true) { if(i==3) { break; }else { System.out.println("i="+i); } i++; } } }输出结果:i=1 i=2多循环,break是结束的哪个循环? public class MostForBreakDemo { public static void main(String[] args) { for(int i=1;i<5;i++) { for(int j=1;j<7;j++) { if(j==4) { break; }else { System.out.print(" j="+j); } } System.out.println(" i="+i); } } }**注意:当break语句出现在嵌套循环中的内层循环时,它只能跳出内层循环,如果想使用break语句跳出外层循环则需要对外层循环添加标记。标记:当多层循环时,想在内循环结束外循环通过加标记结束。** package java_learn_code; public class MostForBreakDemo { public static void main(String[] args) { a:for(int i=1;i<4;i++) { for(int j=1;j<7;j++) { if(j==4) { break a; }else { System.out.print(" j="+j); } } System.out.println(" i="+i); } } }输出结果: j=1 j=2 j=3switch或循环遇到break就全结束。continue语句continue语句用在循环语句中,它的作用是终止本次循环,执行下一次循环。 public class ContinueDemo { public static void main(String[] args) { for (int j = 1; j < 7; j++) { if (j == 4) { continue; } else { System.out.print(" j=" + j); } } } }输出结果: j=1 j=2 j=3 j=5 j=6多层循环,通过标记,跳过外层其中一次循环。 public class ContinueDemoTwo { public static void main(String[] args) { a:for(int i=1;i<7;i++) { for(int j=1;j<4;j++) { if(i==3) { continue a; }else { System.out.print(" j="+j); } } System.out.println(" i="+i); } } }输出结果: j=1 j=2 j=3 i=1 j=1 j=2 j=3 i=2 j=1 j=2 j=3 i=4 j=1 j=2 j=3 i=5 j=1 j=2 j=3 i=6注意:同样支持标记,跳过某一次循环。九、综合实例:随机猜数字 import java.util.Random; import java.util.Scanner; public class DemoOne { public static void main(String[] args) { while(true) { System.out.print("请输入猜的数字:"); Scanner scan = new Scanner(System.in); int number = scan.nextInt(); Random ran = new Random(); int yourNum = ran.nextInt(10)+1; if(number==yourNum) { System.out.println("恭喜你猜对了,么么哒!"); break; }else if(number>yourNum) { System.out.println("输入的值:"+number); System.out.println("随机值:"+yourNum); System.out.println("sorry....猜大了哦"); }else { System.out.println("输入值:"+number); System.out.println("随机值:"+yourNum); System.out.println("sorry....猜小洛"); } System.out.println(""); } } }十、选择结构switch选择结构switch,switch 条件语句也是一种很常用的选择语句,它和if条件语句不同,它只能针对某个表达式的值作出判断,从而决定程序执行哪一段代码。Switch语法格式:switch (表达式){ case 目标值1: 执行语句1 break; case 目标值2: 执行语句2 break; ...... case 目标值n: 执行语句n break; default: 执行语句n+1 break; }说明:switch语句将表达式的值与每个case中的目标值进行匹配,如果找到了匹配的值,会执行对应case后的语句,如果没找到任何匹配的值,就会执行default后的语句。break的作用是跳出switch语句。在switch语句中的表达式只能是byte、short、char、int类型的值,如果传入其它类型的值,程序会报错。但上述说法并不严谨,实际上在JDK5.0中引入的新特性enum枚举也可以作为switch语句表达式的值,在JDK7.0中也引入了新特性,switch语句可以接收一个String类型的值。实例:数字转星期public class SwitchDemo { public static void main(String[] args) { boolean flag=true; while(flag) { System.out.print("星期转换:"); Scanner scan = new Scanner(System.in); int num = scan.nextInt(); switch(num) { case 1: System.out.println("星期一"); break; case 2: System.out.println("星期二"); break; case 3: System.out.println("星期三"); break; case 4: System.out.println("星期四"); break; case 5: System.out.println("星期五"); break; case 6: System.out.println("星期六"); break; case 7: System.out.println("星期日"); break; default: flag = false; System.out.println("退出成功!"); } System.out.println(""); } } }Case的穿透性:在使用switch语句的过程中,如果多个case条件后面的执行语句是一样的,则该执行语句只需书写一次即可,这是一种简写的方式。实例:判断一周中的某一天是否为工作日import java.util.Scanner; public class SwitchCaseDemo { public static void main(String[] args) { boolean flag=true; while(flag) { System.out.print("星期转换:"); Scanner scan = new Scanner(System.in); int num = scan.nextInt(); switch(num) { case 1: case 2: case 3: case 4: case 5: System.out.println("工作日"); break; case 6: case 7: System.out.println("休息日"); break; default: flag = false; System.out.println("推出成功!"); } System.out.println(""); } } }没有break就会一直往下穿透。
2022年02月28日
264 阅读
0 评论
2 点赞
2022-02-27
JAVA基础(第一篇)
总结一下JAVA基础知识如:注释、关键字、标识符、数据类型、变量、数据类型转换等基础语法。初学者可参考看看。1、程序注释单行注释://xxxxxx多行注释:/* xxxxxx */文档注释:/** xxxxxx */2、关键字关键字:是被Java语言赋予特殊含义,具有专门用途的单词。所有的Java关键词,都是小写。关键词比较多,不用刻意去背,以后用多了自己就记住了。3、标识符Java中除了关键字以外基本上都是标识符。我们自己定义的词,比如自己定义的HelloWorld。标志符命名规则:标志符组成:字母、数字、下划线、美元符号 字母:a~z、A~Z 数字:0-9 下划线:_ 美元符号:$注意:不能数字开头,不能是关键字,严格区分大小写,不限制长度起名时,尽量达到见名知意。4、数据类型数据类型分为基本数据类型和引用数据类型。A、基本数据类型:4类8种(4类展开后共8种基本类型),基本数据类型是JAVA中内置的类型。第一类:整型字节byte 1个字节 二进制位数:8 -128~127短整型short 2个字节 二进制位数:16 包装类:java.lang.Short 最小值:Short.MIN_VALUE=-32768 (-2的15此方) 最大值:Short.MAX_VALUE=32767 (2的15次方-1)整型int 4个字节 二进制位数:32 包装类:java.lang.Integer 最小值:Integer.MIN_VALUE= -2147483648 (-2的31次方) 最大值:Integer.MAX_VALUE= 2147483647 (2的31次方-1)长整型long 8个字节 二进制位数:64 包装类:java.lang.Long 最小值:Long.MIN_VALUE=-9223372036854775808 (-2的63次方) 最大值:Long.MAX_VALUE=9223372036854775807 (2的63次方-1)第二类:浮点型单精度 float 4个字节 二进制位数:32 包装类:java.lang.Float 最小值:Float.MIN_VALUE=1.4E-45 (2的-149次方) 最大值:Float.MAX_VALUE=3.4028235E38 (2的128次方-1)注意:必须已“F”结尾,java才认为是float类型,否则默认认为是double类型。双精度 double 8个字节 二进制位数:64 包装类:java.lang.Double 最小值:Double.MIN_VALUE=4.9E-324 (2的-1074次方) 最大值:Double.MAX_VALUE=1.7976931348623157E308 (2的1024次方-1)注意:必须以“D”结尾,java中默认的浮点类型是double类型。第三类:字符型char 2个字节 二进制位数:16 表示一个字符,如('a','2','家')注意:用单引号包裹起来,并且其中只能包含一个字符,必须填写。一个汉字=2个字节=16位,所以一个中文字符刚好可以装下。第四类:布尔型boolean 1个字节 只有2个值true与false只记基本数据类型的字节数,以及byte取值范围127~-128即可,其它不用记,一般开发中使用int、double、char、boolean。B、引用数据类型:分别是数组、类、接口引用数据是强大的数据类型,它是基于基本数据类型创建的。JavaSE中提供了一个超级类库,类库中包含了近万种引用数据类型。5、常量JAVA中数据量分为常量和变量。常量就是不变的数据量,任何数据量都是有其类型的,常量就是整数类型。整数表示方式有十进制、二进制、十六进制、八进制,它们之间的转换(自行谷歌/百度)。整数常量是byte、short、int、long中的哪种类型呢?整数常量可以根据所在范围来确定类型,java中默认的整数类型是int类型。long类型必须添加“L”后缀,java才知道其类型,不加"L",java会将其当作int类型。默认浮点类型为doule类型。float需要加“F”后缀,double需加“D”后缀。1267:没有L后缀,为int类型,但是超出int范围,会报错。 12L:为long类型. 3.1:没有后缀,所以为double类型。 2.34D:为double类型。 1.45F:为float类型。6、变量Java变量应用最多的。内存数据运行时,临时存储数据的地方。变量就是内存中装载数据的小盒子,只能用来存数据和取数据,数据类型定义了就不能改变了,里面的数据可以变化的。定义变量格式:数据类型 变量名 数据值 int num = 100;注意:变量必须要有明确的类型,什么类型的变量装载什么类型的数据,同时也要指定变量能装载多大的数据。数据值不指定,不能使用,编译时不会报错,但是运行时会报错。变量名必须满足标识符规则,才能作为变量来使用。7、字符串字符串类型,值用""双引号包裹起来,属于引用数据类型。String str = "Hello World";注意:字符串Sring不属于基本数据类型,属于JAVA中的引用类型,但是定义、使用和基本数据类型定义类似。标记一下,后面详细记录String类型8、变量使用注意事项变量定义后可以不赋值,使用时再赋值。不赋值不能使用。错误演示:/** * 变量使用注意事项演示 * 错误演示:变量没有赋值 */ public class ErrorVariable{ public static void main(String[] args){ int i; System.out.println(i); } }输出结果:ErrorVariable.java:9: 错误: 可能尚未初始化变量i System.out.println(i);正确演示:/** * 变量使用注意事项演示 * 正确演示 */ public class CorrectVariable{ public static void main(String[] args){ int i; i = 100; int j = 200; System.out.println(i); System.out.println(j); } }输出结果:100变量是有自己的作用范围,变量的有效范围为:定义的一对大括号内.错误演示:/** * 变量使用注意事项演示 * 错误演示:变量有效范围 */ public class ErrorVariable2{ public static void main(String[] args){ { int i = 100; } System.out.println(i); } }输出结果:ErrorVariable2.java:11: 错误: 找不到符号 System.out.println(i); ^ 符号: 变量 i 位置: 类 ErrorVariable2 1 个错误变量不能重复定义错误演示:/** * 变量使用注意事项演示 * 错误演示:变量不能变量重复定义 */ public class ErrorVariable2{ public static void main(String[] args){ int a = 50; int a = 30; } }输出结果:ErrorVariable3.java:9: 错误: 已在方法 main(String[])中定义了变量 a int a = 30; ^ 1 个错误变量使用总结:1、变量没有赋值不能使用 2、变量有效范围 3、变量不能重复定义9、数据类型代码演示定义Java八种基本数据类型变量/** * 定义Java八种基本数据类型变量。 * 变量只能存一个值,以最后一个值为准。 */ public class DataType{ public static void main(String[] args){ //字节类型(127~-128) 1个字节 byte b = 127; //短整型 2个字节 short s = 128; //整型 4个字节 int i =111111; //长整型 8个字节 long l = 22222222222222L; System.out.println(b); System.out.println(s); System.out.println(i); System.out.println(l); //单精度 4个字节 float f =1.176F; //双精度 8个字节 double d =1.100D; System.out.println(f); System.out.println(d); //字符类型 2个字节 //注意:必须有值,空字符也可以,必须单引号包裹起来。 char c ='6'; //char c2 =''; 这个没有值,会报错。 char c3 =' '; System.out.println(c); System.out.println(c3); //布尔类型 1个字节 只有2个值,true和false boolean boo = true; boolean boo2 = false; System.out.println(boo); System.out.println(boo2); } }输出结果:127 128 111111 22222222222222 1.176 1.1 6 true false数据类型/** * 数据类型演示 */ public class DemoOne{ public static void main(String[] args){ //输出整数 十进制 System.out.println(50); //输出整数 二进制,数字开头oB System.out.println(0B11); //输出整数 八进制,数字开头0 System.out.println(0537); //输出整数 十六进制,数组开头0X 0-9 A-F System.out.println(0XE); //输出浮点数 System.out.println(3.2); //输出布尔数据,只有2个值,true/false System.out.println(true); System.out.println(false); //输出字符常量,单引号包裹,只能写1个字符(无论是汉字、数组、字母),都是一个字符。 //注意:不写也不行,不写会报错,但可以写一个空字符。 System.out.println('6'); System.out.println(' '); //输出字符串。 //注意:可以什么都不写,就为一个空字符。 System.out.println(""); } }输出结果:50 3 351 14 3.2 true false 6 注意:最后输出的2个为空。字符串类型演示/** * 字符串,引用类型 * 常量:字符串,""双引号包裹起来 * 注意:字符串Sring不属于基本数据类型,属于JAVA中的引用类型,但是定义、使用和基本数据类型定义类似。 */ public class StrVariable{ public static void main(String[] args){ String str = "Hello World"; System.out.println(str); } }输出结果:Hello World强烈推荐阿里巴巴JAVA开发手册,程序员必备手册。10、数据类型转换数据类型转换分为自动转换和强制转换。不同类型的变量是否可以一起运算?答案是可以的,但是需要先进行数据类型转换,再运算。数据转换遵循原则:范围小的数据类型值,可以直接转换为范围大的数据类型值。 范围大的数据类型值,不可以直接转换为范围小的数据类型值。各种数据类型按照数据范围从小到大依次列出:byte -> short -> int -> long -> float -> doubleA:自动类型转换:表示范围小的数据类型转换成范围大的数据类型,这种方式称为自动类型转换。自动转换格式:范围大的数据类型 变量 = 范围小的数据类型值;/** * 数据类型转换 * 自动转换:取值范围小的数据值,会自动转换成取值范围大的值。 * 注意:bolean类型不能参与转换 */ public class DataTypeConversion{ public static void main(String[] args){ //double类型变量 double d = 10000; //出现类型自动转换,int自动转换成double System.out.println(d); int i =100; double d2 = i; //出现类型自动转换,int自动转换成double System.out.println(d2); byte b =10; int j = b; //自动类型转换,byte类型自动转换成int类型 System.out.println(j); } }注意:bolean类型不能参与转换B:强制转换:把数据类型取值范围大的,转换成数据类型取值范围小的。数据类型强制转换公式:被转后的数据类型 变量名 = (被转换后数据类型)要被转的数据;/** * 强制数据类型转换 */ public class DataTypeConversion2{ public static void main(String[] args){ //double浮点,转成int double d = 3.14; //被转后的数据类型 变量名 = (被转换后数据类型)要被转的数据 int i = (int)d; System.out.println(i); //类似大桶中的水倒入小桶,水肯定会丢失(精度丢失) byte b = (byte)200; System.out.println(b); } }输出结果:3 -56注意:强制类型转换,实际开发中没有要求强制转换时,不转换,不然会丢失精度 ,除非要求转换才做强制转换。### 11、运算符运算符分为:算术运算符、赋值运算符、比较运算符、三元运算符。算术运算符运算符是用来计算数据的符号。数据可以是常量,也可以是变量。被运算符操作的数我们称为操作数。算术运算符最常见的操作是将操作数参与数学计算,如下:运算符 运算规则 范列 结果 + 正号 +3 3 + 加 2+3 5 + 字符串连接 "你"+"好" 你好 - 负号 int a=3;-a -3 - 减号 3-1 2 * 乘 2*3 6 / 除 5/2 2 % 取模 5/2 1 ++ 自增 int a=1;a++/++a 2 -- 自减 int b=3;b--/--b 2算术运算符演示:/** * + 加法,连 * - 减法 * * 乘法 * / 除法 * % 取模(求余数) * ++ 自增 * -- 自减 */ public class Operator{ public static void main(String[] args){ // + 连接作用,将一个字符串和其他数据连接起来 // 遇到字符串,变成连"5+4=54" // + 任何类型只要和字符串+,所有的数据都变成了字符串。 System.out.println("5+4="+5+4); //除法运算 //java中,整数除法运算最后只会得到整数 int i = 100; int j = 9; System.out.println(i/j); //取模运算,两数相除,获取的余数 int k =6; int m =4; System.out.println(k%m); //++/-- 自增/自减运算 int a = 3; int b = 3; a++; //变量a自己增加1 System.out.println(a); ++b; System.out.println(b); //====================================================== //++:写在变量前面,和写在后面的,区别 int c = 3; int d = 3; ++c; d++; //结论:符号写在前面,还是后面,在变量自己独立计算的时候,没有区别。 //但是变量,要是参与了其它运算,就有区别了。 //f = e++,++后算,先将e的值赋予f,然后e再自增1. //q = ++h,++先算,先将h自增1,后再赋值给q。 //======================测试============================ int e = 5; int f = e++; System.out.println(e); System.out.println(f); int h = 5; int q = ++h; System.out.println(h); System.out.println(q); } }输出结果:5+4=54 11 2 4 4 6 5 6 6++:写在变量前面,和写在后面的,区别:符号写在前面,还是后面,在变量自己独立计算的时候,没有区别。但是变量,要是参与了其它运算,就有区别了。f = e++,++后算,先将e的值赋予f,然后e再自增1. q = ++h,++先算,先将h自增1,后再赋值给q。-- 与++类似,不再做说明。赋值运算符赋值运算符就是为变量赋值的符号。赋值运算符的使用如下:运算符 运算规则 范例 结果 = 赋值 int a=2 2 += 加后赋值 int a=2,a+=2 4 -= 减后赋值 int a=2,a-=2 0 *= 乘后赋值 int a=2,a*=2 4 /= 整除后赋值 int a=2,a/=2 1 %= 取模后赋值 int a=2,a%=2 0注意:诸如+=这样形式的赋值运算符,会将结果自动强制转成等号左边的数据类型。public class Operator2{ public static void main(String[] args){ int a = 1; a+=4.8; System.out.println(a); int b = 10; b%=3.3; //会先把10转成double 10.0 然后相除余数0.1,去整数0. System.out.println(b); int h = 10; //h=h%3.3; 会报 不兼容的类型: 从double转换到int可能会有损失 System.out.println(h); int c = 10; double d=3.3; System.out.println(c/d); System.out.println(c%d); byte m =1; //m = m + 1; //出错,会丢失精度,类似把小桶加大桶的水,放到小桶。 m=(byte)(m+1);//通过强转就可以。 m+=1;//这种加就包含了上面的强转,因此推荐使用+=这种 System.out.println(m); } }输出结果:5 0 10 3.0303030303030303 0.10000000000000053 3注意:在运算时,都会往类型占有字节大的转换后再运算,除/余数运算,结果去整数。比较运算符比较运算符,又叫关系运算符,它是用来判断两个操作数的大小关系及是否相等关系的,结果是布尔值true/false。运算符 运算规则 范例 结果 == 相等于 4==3 false != 不等于 4!=3 true < 小于 4<3 false > 大于 4>3 true <= 小于等于 4<=3 false >= 大于等于 4>=3 true注意:赋值运算符的=符号与比较运算符的==符号是有区别的:赋值运算符的=符号,是用来将=符号右边的值,赋值给=符号左边的变量。比较运算符的==符号,是用来判断==符号左右变量的值是否相等的。/** * 赋值运算符 */ public class Operator3{ public static void main(String[] args){ int a = 3; int b = 4; System.out.println(a=b); System.out.println(a==b); System.out.println(a==3); System.out.println(a!=3); } }输出结果:4 true false true逻辑运算符逻辑运算符,是用于布尔值进行运算的,结果为布尔值true或false运算符 运算规则 范例 结果 & 与 false&true false | 或 false|true true ^ 异或 true^false true ! 非 !true false && 短路与 false&&true false || 段落或 false||false true逻辑运算符通常是对两个类型数据之间进行计算,结果也是boolean类型。/** * 逻辑运算符 */ public class Operator4{ public static void main(String[] args){ //一边是false,运算结果就是false System.out.println(false & false); System.out.println(false & true); System.out.println(true & true); //一边是true,结果就是true System.out.println(false | false); System.out.println(false | true); System.out.println(true | true); ////两相同就是false,不同为true System.out.println(false ^ false); System.out.println(false ^ true); System.out.println(true ^ true); //取反 System.out.println(!false); System.out.println(!true); //前边是false,后边不运行,结果为false。比&效率高 System.out.println(false && false); System.out.println(false && true); System.out.println(true && true); //前边是true,后边不运行,结果为true。比|效率高 System.out.println(false || false); System.out.println(false || true); System.out.println(true || true); } }输出结果:false false true false true true false true false true false false false true false true true重点:&与&&区别: 短路与&&,前面不成立(false),后面就不运算了,结果为不成立(false)。 |与||区别: 短路或||,前面成立,后面就不运算了,结果为成立(true)。三目运算符之前的均为一元或二元运算符,元就是参与运算的数据。例如:3+5,使用算术运算符将操作数联系起来,这种情况,称为:算符表达式。3>2,使用比较运算符(条件运算符)将操作数联系起来,称为:条件表达式其它表达式类似。三目运算符格式:(条件表达式)? 表达式1 : 表达式2 表达式:几通过使用运算符将操作数联系起来的式子。三目运算符运算规则:先判断条件表达式的值,为true,结果则为表达式1,为false,结果为表达式2./** * 三目运算符 */ public class Operator5{ public static void main(String[] args){ int a =2; int b=6; System.out.println(a>b ? a+b : b-a); System.out.println(a<b ? a+b : b-a); String c = 9>4 ? "Hello" : "呵呵"; System.out.println(c); } }输出结果:4 8 Hello
2022年02月27日
236 阅读
0 评论
1 点赞
1
...
4
5