1.如果.java文件包含一个public 类.它必需按该类命名。java语言中单词拼写严格区分大小写;
2.一个源文件中最多只有一个public类。其它类的个数不限。
3.System.out.println(Integer.MAX_VALUE) 看看整型的最大值
System.out.println(Integer.MIN_VALUE) 最小值
System.out.println(Float.MAX_VALUE)
9.int i[]; //int[] s; 栈内存
i=new int[10]; 堆内存
for(int i=0;i<a.length;i++)
{
for(int j=0;j<a[i].length;j++)
public static void main(String args[])
public class Demo
{}
15.System.arrayCopy(source,0,dest,0,source.length); //数组的拷贝
17.不分配堆内存会发生NullPointerException //new person();
18.new person(\"ding\",32).shout(); //匿名对象
匿名对象则在一个对象被创建之后,调用对象的方法时可以不定义对象的引用变量,而直接调用这个对象的方法,
(1)、如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象
(2)、将匿名对象作为实参传递给一个方法调用。
19.String name=new String(\"jj\");开辟两个空间,有一个垃圾空间 === String name=\"jj\";开辟一个空间,用这个
20.name1==name2 是false name1.equles(name2) 是true \"jj\".equels(name1)是true
21.
String name1=\"jj\"; //jj就是匿名的
String name2=\"jj\";
System.out.println(name1==name2);
答案是TRUE因为JAVA采用的是共享模式!!!!!!!!!!!!!!!
23.
String 类型一旦建立就不能改变
String str1=\"sa\";
fun(str1); //要是传递的是person的 name是可以改变的因为这样操作的是对象
System.out.println(str1);
public void fun(String str2)
{ str2=\"sadf\": 或 str2+=\"dfa\";} //结果都是sa没有任何改变
24.
要回避一种写法,不要在循环中做 str +=\"i\";这样会有超多的内存垃圾、性能降低,因为String类型一旦建立就不会改变
应该用StringBuffer, 它与String的本质区别在于StringBuffer可以改变
25.this.print(); //调用本类中的方法
this(); this(name); //调用构造方法,必须放在“构造方法“的首行!!
26.System.out.println(p); //打印的是对象P的地址
和在对象方法中的this一样 System.out.println(this);打印的都是地址
30.栈内存:保存的是对象的名字
堆内存:对象的具体内容(属性)
全局代码区:所有方法
全局数据区:存放static类型的数据
34.代码块:四种代码块
1. 普通代码块:是写在一个方法之中的语句块
{
{
int i=0; //只在大括号内有效
}
int i=10;
System.out.println(i);
}
2. 构造块:是直接写在类中的一个语句块,构造块优先于构造方法执行,执行多次
class person
{
{
System.out.println(\"Kkjfh\");
}
person()
{
System.out.println(\"safjk\");
}
3.静态块:是直接写在类中的,通过static声明的语句块,优先于构造块与构造方法执行,作用是为静态属性初始化,只执行一次
class person
{
static
{
System.out.println(\"rgKsf\");
}
{
System.out.println(\"Kkjfh\");
}
4.同步代码块(多线程)
int temp=Integer.parseInt(num); //包装类,转换类型,必须保证字符串是数字
37.System.exit(1); //程序退出,不再向下继续执行
38.
java 只允许单继承,可以多层继承。
42.
三种权限:
public 任何都可以访问
默认default:仅次于public
private:只能在一个类中访问
public >default>private
43.方法覆写时,名称完全一样,参数一样,权限更松!!!(最好一致,如果是public ,覆写也只能用public)
super(name,age); //可以通过super(),里面根据里面的内容调用指定的构造方法
{ return super.say()+\"world\";} //通过super.方法,可以由子类调用父类中指定的方法(方法被覆写了)
47.
this 与super 在使用上很相似,都可以调用其它方法、属性、构造方法[都必须放在首行]
this 与super 调用构造的操作不能同时在一个构造方法中!!
调用构造:this放在本类构造方法的首行,构造方法需要有一个出口(至少有一个构造方法没有用this 调用 )
super放在子类构造方法之中,默认情况下子类隐藏一个super(),去调用父类中默认的构造方法
49.
(1)final类不能被继承
final class A
{
}
(2)final定义的方法不能被覆写
public final void fun() //此方法不能被覆写
{}
(3)被final定义的变量称为常量
final String NAME=\"mldn\"; //name最好大写
50.public static final 叫全局常量
public static final String NAME=\"mldn\";
51.抽象类:就是包含一个抽象方法的类
抽象方法就是一个只有声明而没有实现的方法
52.抽象类比普通类多出一个抽象方法,普通类的所有定义 在抽象中都可以使用!
abstract声明为抽象类,抽象方法也必须用abstract声明。
53.
abstract class A //抽象类不能实例化对象
{
public void fun2() //普通的也行
{
System.out.println(\"hello world\");
}
public abstract void fun();
}
抽象方法只需声明,而不需实现
抽象类的子类必须复写所有(所有的)的抽象方法。。
56.
抽象类必须有子类,子类如果不是抽象类的话,则必须覆写抽象类中的全部方法。 (抽象类可继承抽象类,不用覆写抽象方法,但没什么意义)
抽象类也依然属于JAVA的单继承模式。
抽象类不能用final声明,因为final声明的类不能有子类,而抽象类本身又必须有子类。//用final没意义
58.抽象类中包含抽象方法,如果在类中全部都是抽象方法时,用接口表示。
接口中还包括全局常量: public static final //static 全局,final 常量
59.接口中的访问权限永远是:public
interface A
{
public static final String INFO=\"dmy\"; //--》可写在String INFO=\"dmy\"; 默认就是全局常量,代码自动加
public abstract void say(); //-->可写成public void say(); 它默认就是前面的
}
60.一个类可实现多个接口
class X extends C implements A,B //先继承再实现
61.一个接口是允许同时继承多个接口的,
65.
两个常见的错误:ClassCastException(两个对象之间毫无关系而进行转换) .
public static void main(String args[])
{
A a=new A();
B b=(B)a; //会出现ClassCastException异常
}
if(a instanceof B) //instanceof是关键字,不是一个方法
72.
抽象类和接口都不能直接实例化,通过多态性,可由其子类实例化。
抽象类可包括一般方法、变量、常量!接口:只包含常量、抽象方法
抽象类可有构造方法! 接口:不能有构造方法
抽象类可实现多个接口,接口不能继承类
抽象类只能单继承,接口可以解决单继承的局限性!
所有类都必须继承自 类(有很多方法,如equals(),toString())
一切对象都可以向 类进行转换
class Person //extends
{}
Person p=new Person();
System.out.println(p); //实际就是调用对象中的toString()方法,-->p.toString()
78.如果一个类希望按自己的方式打印对象,可以通过覆写的方式,将toString()方法覆写掉。
79.Equals方法是一个对象比较,在String类中调用的equals 方法肯定是已经被String类所覆写了。
public static void main(String args[])
{
Person p1=new Person(\"dingmingyu\",21);
Person p2=new Person(\"dingmingyu\",21);
System.out.println(p1.equals(p2)); //不能直接这样用,这样是false,需要覆写equals
}
80.
class Person //extends
{
private String name;
private int age;
public Person(String name,int age)
{ this.setName(); this.setAge();} //略
public String toString()
{
return \"姓名\"+this.name+\",年龄\"+this.age;
}
public boolean equals( obj)
{
if(!(obj instanceof Person))
{ return false; } //如果不是person的子类就没意义了,直接返回假就可以
person per1=this;
person per2=(Person)obj;
boolean flag=false;
if(per1==per2)
{ flag=true;}
else
{
if (per1.name.equals(per2.name)&&per1.age==per2.age)
{
flag=true;
}
}
return flag;
}
}
public class ooDemo01
{
public static void main(String args[])
{
Person p1=new Person(\"dingmingyu\",21);
Person p2=new Person(\"dingmingyu\",21);
System.out.println(p1.equals(p2));
//person p3=p1;
Sytem.out.prinln(p1.equals(p3));
Sytem.out.prinln(p1.equals(\"abc\")); //String类也是 的子类,上面接收是没问题的,但会出现类的转换异常
}
}
81.在一个类中定义一个类则称此类为内部类
class Outer
{
private String info=\"DMY-->DDOffice\";
class Inner //这就是内部类,好处就是可以访问外部类的私有属性!!
{
public void print()
{
System.out.println(\"INFO =\"+info);
}
public void fun()
{
new Inner().print();
}
}
public class ooDemo02
{
public static void main(String args[])
{
Outer o=new Outer();
o.fun();
Outer.Inner in=o.new Inner(); //实例化内部类
in.print();
}
}
82.内部类可以在任何位置定义,如方法中
class Outer
{
private String info=\"DDOFFICE\";
public void fun(final int len) //要在方法内部类中访问必须加final,但是此final并不表示说是一个常量,只是一个简单的标记。
{
class Inner
{
public void print()
{
System.out.println(\"len=\"+len);
System.out.println(\"info=\"+info);
}
}
new Inner().print();
}
}
public class ooDemo07
{
public static void main(String args[])
{
new Outer().fun(10);
}
}
83.匿名内部类:这个内部类只使用一次,一次之后就不用了,匿名内部类是在抽象类和接口的基础上发展起来的.
interface A
{
public void fun();
}
class B implements A
{
public void fun()
{
System.out.println(\"ddoffice\");
}
}
class C
{
public void fun2()
{
this.print(new B());
}
public void print(A a)
{
a.fun();
}
}
public class ooDemo09
{
public static void main(String args[])
{
new C().fun2();
}
}
84.
public void fun2()
{
this.print(new B()); //如上面,所B传到A中
}
public void fun2()
{
this.print(new A() //这就是匿名内部类,接口不能直接实例化!
{
System.out.println(\"ddoffice\");
});
}
javac *.java 表示当前文件夹下的一切java文件都进行编译
javac -d . ooDemo01.java //-d表示生成包的文件夹,. 表示在当前文件夹下保存生成的文件
java lxh.ooDemo02
90.java.lang 是系统自动导入的包
91.
访问权限
private :同一类中
default:同一包中的类
protected:不同包中的子类
public:都可以
93.异常在java中称为Throwable
Error 表示错误:JVM出错,程序无法运行。
Exception表示异常,表示程序运行时出现的错误,可以由人为处理。
94.
public class ooDemo03
{
public static void main(String args[])
{
System.out.println(\"----异常发生之前------\");
try
{
System.out.println(1/0);
System.out.println(\"*****\"); //这行和下面的不会被处理,直接到捕获里面去了。
}
catch (ArithmeticException ae)
{
System.out.println(\"发生异常了\");
System.out.println(ae);
}
System.out.println(\"-----异常发生之后------); //抛出异常后还能处理下面的。如果说不捕获就不会向下了
}
}
catch (ArithmeticException ae)
catch (ArrayIndexOutOfBoundsException abe)
97.
因为抛出的是一个异常对象,而所有的异常类都是Exception的子类,可以简单的用Exception进行接收
98.但是在使用try...catch中有一个注意点:
虽然一个try后面可以跟多个catch,但是捕获更细的异常要写在捕获更粗的异常之前。
99.
finally 表示一个异常的统一出口,不管程序是否出现了异常,都必须执行finally这个代码块。
100.throws用于在方法的声明处使用,表示在此方法中不处理异常,而交给调用此方法处进行处理。
public int div(int i,int j) throws Exception //谁调用谁捕获可能的错误
{
return i/j;
}
101.
如果在main方法处编写了throws语句,则表示此异常交给JVM去处理,默认情况下所有的异常就是通过JVM处理的,
102.throw 人为的抛出异常。
public class ooDemo08
{
public static void main(String args[])
{
try //自己抛的本身抛出的就是一个异常类的对象,所以要捕获。
{
throw new Exception(\"自己造的异常,牛吧!\");
}
catch (Exception e)
{ System.out.println(e);}
}
}
107.一个类只要继承了Thread类,则表示此类就实现了多线程。thread类是在java.lang包中的类。所以不用别导入包
class Demo extends Thread
{
//子类要覆写Thread类中的run方法
public void run()
{
for(int i=0;i<=10;i++)
{
System.out.println(\"i=\"+i);
}
}
}
108.上个程序中直接去调用run方法,实际上是类方法的调用,而没有启动操作系统的支持。
109.如果要执行一个线程,则必须调用public void start()方法,它是专门用于启动线程的操作。
通过start()调用的是类中的run()方法。此时的程序是交替运行的,不是像那样调用run方法进行的顺序执行。
在JDK中为用户提供了一个Runnable接口,
在Runnable接口中只有一个run方法,在实现接口实需要覆写run 方法。
class Demo implements Runnable
{
}
Demo d1=new Demo(\"线程1\");
Thread t1=new Thread(d1); //因为Runnable接口中没有start方法,所以要把接口的对象向上转型,通过thread类的构造方法进行start
t1.start();
public class Thread extends implements Runnable //Thread 类继承了 类,实现了Runnable接口。
接口的好处:
继承Thread 类多个线程之间不能实现资源的共享,而实现了Runnable接口之后可以实现多个线程之间资源的共享。
112.这个程序每个窗口各卖了10张票,一共有10张票的话是不可能的。所以必须用Runnable接口
class Demo extends Thread
{
private int ticket=10;
public void run()
{
while(this.ticket>0) //必须用循环,因为每个窗口都是排队买票的。
{
System.out.println(this.info+\"卖票:\"+this.ticket--);
}
}
}
public class ThreadDemo03
{
publci static void main(String args[])
{
//准备4个售票点
Demo d1=new Demo();
Demo d2=new Demo();
Demo d3=new Demo();
Demo d4=new Demo();
d1.start();
d2.start();
d3.start();
d4.start();
}
}
113.这个程序是用Runnable接口实现的,它们的线程是共享了10张票。
class Demo implements Runnable
{
private int ticket=10;
public void run()
{
while(this.ticket>0) //必须用循环,因为每个窗口都是排队买票的。
{
System.out.println(\"卖票:\"+this.ticket--);
}
}
}
public class ThreadDemo04
{
public static void main(String args[])
{
//四个售票点应该控制同一个资源:10
Demo d=new Demo();
Thread t1=new Thread(d);
Thread t2=new Thread(d);
Thread t3=new Thread(d);
Thread t4=new Thread(d);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
114.
用Thread继承而来的线程,一个线程对象只能启动一次,无论调用多少遍start()方法,结果都只有一个线程。
比如:t1.start(); //在继承thread 类中,会抛出异常,中止程序,但在Runnable中虽然抛出异常,但能执行完毕。
t1.start();
t1.start();
start-->run.线程启动之后要等待CPU进行调度,并不是立刻启动的。
取得当前运行的线程:public static Thread currentThread()
取得当前线程的名称:用getName()方法
设置线程式的名称:用setName()方法
System.out.println(Thread.currentThread().getname()+\"在运行\"); //取得当前线程的名称;
Thread t1=new Thread(d,\"线程1\"); //Thread类有这样的构造方法,传一个名字。
t1.setName(\"第一个线程\"); //给线程命名
118.线程控制基本方法:
isAlive():判断线程是否还活着,即线程是否还未终止。
getPriority():获得线程的优先级数值。
setPriority():设置线程的优先数值。
Thread.sleep():将当前线程眨眠指定秒数。
join():调用某线程的该方法,将当前线程与该线程合并,即等待该线程结束,再恢复当前线程的运行。
wait():当前线程进入对象的wait pool
notify():唤醒对象的wait pool中的一个等待线程。
notifyAll():唤醒对象的wait pool中的所有等待线程。
try
{
Thread.sleep(1000);
}
catch(Exception e)
{ e.printstacktrace;}
122.线程的强制运行。
join()方法指一个线程必须:运行完成之后其他的线程才可以继续运行,表示强制运行。
try
{
t.join();
}
catch(Exception e)
{e.printStackTrace();}
123.当一个线程运行时,另一个线程可以调用对应的Thread对象的interrupt()方法来中断它.
124.线程如果中断之后再休眠,则会清除中断标志。
Thread t=Thread.currentThread();
System.out.println(\"t.isInterrupted()=\"+t.isInterrupted());
t.interrupt();
125.同步操作就是在方法之中加入一个synchronized关键字,表示此方法为同步方法
class Demo implements Runnable
{
private int ticket =10;
public synchronized void sold()
{
if(ticket>0) //这个地方必须判断,要不然会出现负数的票数
{
//把需要同步的地方放在同步方法之中
try
{
Thread.sleep(100);
}
catch(Exception e)
{}
System.out.println(Thread.currentThread().getName()+\"卖票了i=\"+ticket--);
}
}
public void run()
{
while(ticket>0) //这个地方必须加循环,要不然票只能让一个窗口卖掉。
{
this.sold();
}
}
}
128.同步代码块:使用synchronized关键字括起来 的代码表示同步代码块。
同步代码块需要一个同步对象。
卖票的例子:应该是对当前操作的线程进行同步,所以此操作应该使用this,为this进行同步。
class Demo implements Runnable
{
private int ticket =10;
public void run()
{
while(ticket>0)
{
synchronized(this) //必须带上this这个对象。
{
if(ticket>0)
{
try
{
Thread.sleep(100);
}
catch(Exception e)
{}
System.out.println(Thread.currentThread().getName()+\"卖票了,剩余票数为\"+--ticket);
}
}
}
}
}
resume:要求被暂停的线程继续执行
suspend:暂停线程的执行
yield:将执行的权力交给其他线程,自己到队列的最后等待
注意:不推荐使用suspend和resume方法,因为
1.它们会导致死锁的发生
2.它允许甲线程通过直接控制线程乙的代码来直接控制线程乙。
虽然stop能够避免死死锁的发生,但如果一个线程正在操作共享数据段,操作过程没有完成就stop的话,将会导致数据的不完整性,所以stop不提倡使用。
134.分为三大类:
1.File类,文件夹操作类
2.字节操作类
3.字符操作类
135.File类:
File类是IO包中唯一代表磁盘文件本身的对象,
136.在F盘中建立一个文件。注意:文件操作时会进行判断,如果文件已经存在,则不会重新创建。
import java.io.*;
File f=new File(\"f:\\\\dingmingyu.txt\");
if(f.exists())
{
f.delete();
}
else
{
f.createNewFile();
}
138.
File f=new File(\"f:\\\\100\");
if(f.isDirectory())
{
String str[]=f.list();
for(int i=0;i<str.length;i++)
{
System.out.println(str[i]);
}
139.打印D盘中的内容:递归-->一个方法自己调用自己的情况
import java.io.*;
public class IoDemo04
{
public static void loop(String dir)
{
File f=new File(dir);
String str[];
if(f.isDirectory())
{
str=f.list();
for(int i=0;i<str.length;i++)
{
loop(dir+\"\\\\\"+str[i]);
}
}
else
{
System.out.println(dir);
}
}
}
140.输入输出方法
注意:出于安全的考虑,小应用不能实现文件I/O流!
File与文件有关
RandomAccessFile类与文件内容有关,但是此类有一个缺点,就是说如果要跳转,则需要数据的保存长度一致。
public static void main(String args[]) throws Exception
{
RandomAccessFile raf= new RandomAccessFile(\"f:\\\\dingmingyu.txt\",\"rw\");
String name=\"dingmin\";
int age=22;
raf.write(name.getBytes());
raf.writeInt(age);
name=\"god\";
age=22;
raf.write(name.getBytes());
raf.writeInt(age);
name=\"zhangsan\";
age=22;
raf.write(name.getBytes());
raf.writeInt(age);
raf.close();
RandomAccessFile raf1=new RandomAccessFile(\"f:\\\\dingmingyu.txt\",\"r\");
raf1.skipBytes(11); //跳转的字节数
byte b[]=new byte[8];
raf1.read(b);
int a=raf1.readInt();
System.out.println(new String(b)+\"-->\"+a);
}
141.outputStream、inputStream字节流 writer、reader字符流
注意:上面四个现代化都是抽象类,都要用子类实例化它们。
用fileOutputStream子类实例化outputStream
import java.io.*;
File f=new File(\"f:\\\\试验.txt\");
f.createNewFile();
OutputStream ou=new FileOutputStream(f);
String str=\"Hello king!丁明玉,你太牛逼了,我太崇拜你了。。。\";
byte b[]=str.getBytes();
ou.write(b);
ou.close();
}
}
142.用FileInputStream实例化InputStream
int len=0;
File f=new File(\"f:\\\\IOread.txt\");
f.createNewFile();
InputStream i=new FileInputStream(f);
byte b[]=new byte[100];
len=i.read(b);
System.out.println(new String(b,0,len));
143.InputStream与OutputStream所操作的都是字节操作
用于操作字符:Reader.Writer.它们也是抽象类
File f=new File(\"f:\\\\writer.txt\");
Writer w=new FileWriter(f);
String str=\"Hello ,world,i love you!!\";
w.write(str);
w.close();
字符流用到了缓存,字节流没有用到缓存(字节流不关闭也会写到文件中的)
字符流输出如果不关闭(w.close() ),则无法将内容写入到文件
也可以使用flush()
方法手工清空缓存。 w.write(str); w.flush();
146.管道流就是处理两个线程之间通讯的。
private PipedOutputStream pipout;
public SendDemo()
{
pipout=new PipedOutputStream();
}
public void run()
{
String str=\"helllllllll worlllllld\";
try
{
pipout.write(str.getBytes());
pipout.close();
}
catch(Exception e)
{}
System.out.println(\"数据已经写入文件中了\");
}
}
private PipedInputStream pipin;
public ReceDemo()
{
pipin=new PipedInputStream();
}
public void run()
{
int len=0;
byte b[]=new byte[1024];
try
{
len=pipin.read(b);
pipin.close();
}
catch(Exception e)
{}
System.out.println(\"数据已读出:\"+new String(b,0,len));
}
}
public class IoDemo12
{
public static void main(String args[]) throws Exception
{
SendDemo sd=new SendDemo();
ReceDemo rd=new ReceDemo();
Thread send=new Thread(sd);
Thread rece=new Thread(rd);
PipedOutputStream out=sd.getpipout();
PipedInputStream in=rd.getpipin();
out.connect(in);
send.start();
rece.start();
}
}
147.比特数组输入输出流:ByteArrayInputStream,ByteArrayOutputStream全部都是在内存中完成的。
String str=\"DINGMINGYU,HOHO!\";
byte b[]=str.getBytes();
ByteArrayInputStream in=new ByteArrayInputStream(b);
ByteArrayOutputStream out=new ByteArrayOutputStream();
int c=0;
while((c=in.read())!=-1)
{
int ch=(int)Character.toLowerCase((char)c);
out.write(ch);
}
b=out.toByteArray();
System.out.println(\"内容为:\"+new String(b));
148.System.out:把输出送到缺省的显示器
System.in:从标准输入获取输入
System.err:把错误信息送到缺省的显示
每当main方法被执行时,就自动生成上述三个对象
import java.io.*;
public class IoDemo14
{
public static void main(String args[]) throws Exception
{
OutputStream ou=System.out; //通过子类完成不同的功能,上面还有用FileOutputStream实例化的
String str=\"hello,dingmingyu!,现在是在屏幕上打印..\";
ou.write(str.getBytes());
ou.close();
}
}
149.PrintStream/PrintWriter实际上是一个打印流,打印流比普通的OutputStream/Writer提供了更多打印数据的方法。(PrintWriter用的较多,它什么都能打印)
import java.io.*;
public class IoDemo15
{
public static void main(String args[]) throws Exception
{
File f=new File(\"f:\\\\123.txt\");
//PrintWriter pw=new PrintWriter(new FileWriter(f));//这是向文件中打印
PrintWriter pw=new PrintWriter(System.out); //这是向屏幕上打印
pw.println(true);
pw.println(234.3);
pw.println(\"hello, Mldn\");
pw.close();
}
}
public class IoDemo18
{
public static void main(String args[]) throws Exception
{
InputStream in=System.in;
String str=\"\";
int c=0;
while((c=in.read())!=-1)
{
str+=(char)c;
}
in.close();
System.out.println(\"输入的内容是:\"+str);
}
}
151.实际上在输入数据的时候更希望将全部输入的数据一次性读取进来,如果一次性读取,则肯定不会出现乱码问题。
要想实现上述功能,则需要将输入的数据放入到一个缓存之中。
BufferedReader:此类在实例化时需要接收一个Reader的子类对象
System.in-->InputStream类型的-->字符类型
InputStreamReader:是将输入的内容由字节变为字符。
OutputStreamWriter:是将输出的内容由字符转化为字节。
BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));
String str=null;
for(int i=0;i<2;i++)
{
str=buf.readLine();
i1=Integer.parseInt(str);
153.
GBK:包含了繁体和简体的字符集
GB2312:主要是指简体中文
ISO8859-1:是国际通用编码
下面可以得到JVM的属性
public class IoDemo23
{
public static void main(String args[])
{
System.getProperties().list(System.out);
}
}
154.file.encoding=GBK 因为默认的是GBK编码所以下面的程序会正常输出
OutputStream ou=new FileOutputStream(new File(\"f:\\\\输出.txt\"));
String str=\"欢迎来到JAVA世界\";
ou.write(str.getBytes());
ou.close();
155.假设在程序中将编码变为ISO8859-1;上面的输出会乱码!
ou.write(str.getBytes(\"ISO8859-1\"));
ou.write(str.getBytes(\"GB2312\")); //这个会正常输出
156. 用于合并两个文件的内容:
public SequenceInputStream(InputStream s1,InputStream s2)
接收两个InputStream对象。这就意味着程序需要先使用InputStream找到两个文件。
InputStream in1=new FileInputStream(new File(\"f:\\\\1.txt\"));
InputStream in2=new FileInputStream(new File(\"f:\\\\2.txt\"));
OutputStream ou=new FileOutputStream(new File(\"f:\\\\合并.txt\"));
SequenceInputStream se=new SequenceInputStream(in1,in2);
int i=0;
while((i=se.read())!=-1)
{
ou.write(i);
}
in1.close();
in2.close();
ou.close();
se.close();
}
}
157.
对象序列化是指把对象写入到流中,对象的反序列化是指从流中恢复对象
对象所在的类必须实现java.io.Serializable接口,才能被序列化。
158.如果需要将对象变为byte流,则需要将对象进行转化, OutputStream实现
构造方法 OutputStream(OutputStream ous)
Person per=new Person(\"丁明玉\",22);
//建立一个方法用于完成对象的序列化
public static void ser(Person per) throws Exception
{
OutputStream oos=new OutputStream(new FileOutputStream(new File(\"f:\\\\12334.txt\")));
oos.write (per);
oos.close();
}
159.必须明确告诉 InputStream从哪里读内容
构造方法: InputStream(InputStream in)
//反序列化
InputStream ois=new InputStream(new FileInputStream(new File(\"f:\\\\12334.txt\")));
obj=ois.read ();
ois.close();
return (Person)obj;
160.一个序列化的核心部分:Serializable接口
在Person类中没有覆写接口中的任何一个方法
此接口只是一个声明性接口,表示实现此接口的类可以被序列化。
注意:当不希望类中的某个字段被序列化的时候,应用transient表示这个字段
class Person implements Serializable
{
private String name;
private transient int age=22; //这个被反序列化的时候不会被打印;
161.
变量声明的完整定义
[public |protected|private] [final] [static] [transient] 数据类型 变量名称 [=初始化内容]
完整的方法定义:
[public |protected|private] [final] [static] [synchronized] 方法的返回类型|void 方法名称(参数列表)
StringBuffer也是一个字符对象,但是此对象中的内容可以改变,
StringBuffer sb=new StringBuffer();
sb.append(\"A\").append(\"dkdf\"); //StringBuffer是append()
sb.append(\"iooiio\");
基本类型 包装类
int Integer //特殊
float Float
double Double
char Character //特殊
byte Byte//B要大写,定义比特时,要用byte,这点要注意!
short Short
long Long
boolean Boolean
包装类都在java.lang包中。
String str=\"123\";
int i=Integer.parseInt(str); //parseInt 是static所以可以直接用类使用
float f=Float.parseFloat(str);
167.Runtime类:
运行时类-->使用此类可以调用本机上的程序
Runtime类中没有任何一个构造方法,则外部无法实例化。
因为在类中将构造方法私有化了。但提供了getRuntime方法
Runtime rt=Runtime.getRuntime();
Process p=rt.exec(\"notepad.exe\");
Thread.sleep(3000); //让记事本运行3秒自动关闭
p.destroy(); //通过Process类中的destroy方法杀掉此进程
169.Random类
表示一个随机数类,例如:要产生一个不大于100的10个随机整数。
注意:它在java.util包下
Random rd=new Random();
for(int i=0;i<10;i++)
{
System.out.println(rd.nextInt(100));
}
170.取得时间的类:java.util包下
Date、
Calendar(此类可以将时间精确到毫秒)注意:它是一个抽象类,要想实例化此类需要子类。在API文档中可知:它有一个已知子类:GregorianCalendar()
System.out.println(new Date());
Calendar calendar =new GregorianCalendar(); //用子类实例化
System.out.println(\"YEAR: \" + calendar.get(Calendar.YEAR));
System.out.println(\"MONTH: \" + (calendar.get(Calendar.MONTH)+1)); //它是从0月开始的。所以要加1
System.out.println(\"DATE: \" + calendar.get(Calendar.DATE));
System.out.println(\"DAY_OF_MONTH: \" + calendar.get(Calendar.DAY_OF_MONTH));
System.out.println(\"DAY_OF_YEAR: \" + calendar.get(Calendar.DAY_OF_YEAR));
System.out.println(\"DAY_OF_WEEK: \" + calendar.get(Calendar.DAY_OF_WEEK));
System.out.println(\"AM_PM: \" + calendar.get(Calendar.AM_PM));
System.out.println(\"HOUR: \" + calendar.get(Calendar.HOUR));
System.out.println(\"HOUR_OF_DAY: \" + calendar.get(Calendar.HOUR_OF_DAY));
System.out.println(\"MINUTE: \" + calendar.get(Calendar.MINUTE));
System.out.println(\"SECOND: \" + calendar.get(Calendar.SECOND));
System.out.println(\"MILLISECOND: \" + calendar.get(Calendar.MILLISECOND));
171.自己定义时间的格式:
用SimpleDateFormat类,在java.text包下
import java.util.*;
import java.text.*;
String str=\"2010-03-08 20:55:55\";
SimpleDateFormat sdf1=new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");
SimpleDateFormat sdf2=new SimpleDateFormat(\"yyyy年MM月dd日 HH时mm分ss秒\");
Date d=sdf1.parse(str);
String str1=sdf2.format(d);
System.out.println(str1);
172.类集就是一个动态数组
回顾:对象数组:
173.JAVA类集接口框架
Collection 元素的类集
List 元素的序列
Set 没有重复元素的类集
SortedSet 没有重复元素且排序的类集
Map 元素为二元偶对的汇集,不能重复
SortedMap 在Map基础上,加上排序的要求
Iterator 一个可遍历问总个类集的对象
ListIterator 可遍历一个序列List 的对象
对于以上接口大家只需要掌握最核心的三个即可:
Collection:存放的就是一个个对象,每次存放单个对象。
Map: 每次存放一对值:key-->value
Iterator: 输出接口,只要是集合都要去使用iterator输出
175.Collection接口:
子接口:List
子接口:Set
List既然是一个接口,则要使用必须依靠子类-->ArrayList
用List的方法:add( obj)
import java.util.*;
List li=new ArrayList();
li.add(\"dmy\");
li.add(new Person(\"king\"));
加入数据后,加入数据的顺序就是输出的顺序,按顺序操作的。
176.
向第二个元素中加入数据:add(1,\"eiraiejr\")方法,因为下标是从0开始的
177.要删除刚才加入的数据:li.remove(1);
for(int i=0;i<li.size();i++)
{
System.out.println(li.get(i));
}
注意:在开发中基本上不使用以上做法,原则:只要是集合就使用Iterator输出
2、使用Iterator输出
因为集合的长度不固定,所以Iterator采用的方法是一个一个判断输出,
如果有下一个元素,则执行,如果没有下一个元素就不执行。
判断是否有下一个元素:hasNext()
返回下一个元素:next()
Iterator iter=li.iterator();
while(iter.hasNext())
{
obj=iter.next();
}
180.(Collection)集合操作的主要方法:
向集合中加入数据:public boolean add( obj)
从集合中删除数据:public boolean remove( obj)、public boolean remove(int id)
为Iterator初例化:public Iterator iterator()
取出元素个数:public int size()
181.Set与List的区别:
1、Set的基本使用与List一致,但是HashSet子类存放时是无序的(散列存放)
2、List中的数据允许重复,重复元素保留下来。
182. 在Set中如果使用HashSet则属于散列的无序的存放,如果希望有序存放使用TreeSet子类
靠的是Comparable接口排序
183.Iterator:可获得或删除元素(hasNext()、next()、remove())
ListIterator:允许双向遍历列表,并可修改单元
184. HashMap类使用散列表实现Map接口
key-->value
Map的主要功能是作为查找使用,而不是作为输出使用。
存数据的方法:
put( key, value)
取内容:根据key取
get( key)
185.Map接口的对象不能直接使用Iterator输出
如果非要使用Iterator输出Map接口对象的内容,必须使用以下的步骤:
Map-->Set-->Iterator-->Map.Entry-->key、values
Set s=m.entrySet();
Iterator i=s.iterator();
while(i.hasNext())
{
Map.Entry me=(Map.Entry)i.next();
System.out.println(me.getKey()+\"-->\"+me.getValue()); //这个和上面的输出相同;
}
187.Enumeration:枚举,与Iterator的功能一致,都是用于输出集合中的内容。
Enumeration Iterator
判断是否有下一个内容 hasMoreElements() hasNext()
取值 nextElement() next()
List和Set都不能使用Enumeration输出
而List的另外一个子类:Vector可以使用Enumeration输出,但它不常用,一般用ArrayList
Vector v=new Vector();//如果是List v=new Vector(); Enumeration则不能使了,不能发现这个方法,只能是Vector,也能用Iterator现在主要用Iterator
v.add(\"alsd\");
v.add(\"iofjg\");
v.add(\"jai\");
Enumeration e=v.elements();
while(e.hasMoreElements())
{
System.out.println(e.nextElement());
}
188.栈
Stack<java.lang.String> s=new Stack<java.lang.String>();
s.push(\"a\");
while(!s.empty())
{
System.out.println(s.pop());
}
}
190.Properties类,是属性类。它是Hashtable类的子类。
与hashtable不同的是:Properties类主要是保存字符串的,而Hashtable是保存对象的。
setProperties(String key,String value)
getProperties(String key)
191.ArrayList 和Vector比较
ArrayList Vector
异步 同步
只支持Iterator输出 支持Iterator和Enumeration输出
出现较晚 出现较早
192.HashMap和Hashtable比较
HashMap Hashtable
异步 同步
不直接支持Iterator输出 不直接支持Iterator输出
出现较晚 出现较早
TreeMap:按KEY进行排序的集合
输出:
Iterator:新的输出类,方法名称较短
Enumeration:旧的类输出,方法名称较长
194.实际上每一个对象都有一个hashCode,包括匿名对象
Map m=new HashMap();
m.put(new Person(\"zhangsan\"), \"张三\");
System.out.println(m.get(new Person(\"zhangsan\"))); //这样找到的是null,因为它是匿名对象,两个都是新产生的对象,hashcode不同
如果只覆写hashCode方法根本不起作用,还需要同时覆写equals方法。
195.如果像上面return 1的话,每个对象的hashCode都会相同,所以给它一个公式。
public int hashCode()
{
return this.name.hashCode()+1000;
}
196.对象克隆:
对象的复制
IO 序列化:Serializable-->可以序列化
要完成克隆的类必须具备以下两种条件:
1、类必须实现Cloneable接口,表示类可以被克隆
2、类必须覆写 类中的clone方法
class Person implements Cloneable
{
String name;
public Person(String name)
{
this.name=name;
}
public clone() throws CloneNotSupportedException
{
return super.clone();
}
}
public static void main(String[] args) throws Exception
{
Person p1=new Person(\"李兴华\");
Person p2=(Person)p1.clone();
p2.name=\"丁明玉\";
System.out.println(p1);
System.out.println(p2);
}
197.比较器:Comparable
Arrays类-->专门用于数组排序的。
可以对任意数据类型排序
按成绩由高到低排序,如果成绩一样,按年龄由高到低排序。
package com.king;
import java.util.*;
class Person1 implements Comparable
{
private String name;
private int age;
private int scoree;
public Person1(String name,int age,int scoree)
{
this.name=name;
this.age =age;
this.scoree=scoree;
}
public String toString()
{
return \"姓名:\"+this.name+\"年龄\"+this.age+\"成绩\"+this.scoree;
}
public int compareTo( obj)
{
Person1 p=(Person1)obj;
if(p.scoree>this.scoree)
{
return 1;
}
else if(p.scoree <this.scoree )
{
return -1;
}
else
{
if(p.age >this.age )
{
return 1;
}
else if (p.age<this.age )
{
return -1;
}
else return 0;
}
}
}
public class AdvDemo05
{
public static void main(String[] args)
{
Person1 p[]=new Person1[5];
p[0]=new Person1(\"张三\",20,68);
p[1]=new Person1(\"李四\",20,99);
p[2]=new Person1(\"王五\",18,90);
p[3]=new Person1(\"赵六\",23,62);
p[4]=new Person1(\"孙七\",30,68);
Arrays.sort(p);
for(int i=0;i<p.length ;i++)
{
System.out.println(p[i]);
}
}
}
比较器除了在Arrays类的排序外还可以用在TreeSet上,实际上TreeSet也需要比较器支持(Comparable)。
public static void main(String args[]) throws Exception
{
Set s=new TreeSet();
s.add(new Person2(\"张三\",20,68));
s.add(new Person2(\"李四\",20,99));
s.add(new Person2(\"王五\",18,90));
s.add(new Person2(\"赵六\",23,62));
s.add(new Person2(\"孙七\",30,68));
Iterator i=s.iterator();
while(i.hasNext())
{
System.out.println(i.next());
}
}
198.Class 类
Person3 p=new Person3(\"张三\");
System.out.println(p.getClass().getName()); //根据对象找到所属类,这是映射机制
199.Class 类能够动态的为类实例化
Class类本身没有任何构造方法(Runtime一样)
public class AdvDemo08
{
public static void main(String[] args) throws Exception
{
List li=null;
Class c=Class.forName(\"java.util.ArrayList\");
li=(List)c.newInstance();
li.add(\"klsdafjla\");
li.add(\"asdfa\");
System.out.print(li);
}
}
200.总结出JAVA中对象实例化的途径
1、直接用new:代码比较直观,但是程序会出现耦合度
2、程序出现了接口,如果一个接口的子类直接通过new实例化会造成程序耦合,所以使用工厂进行解耦合操作
3、对象的克隆,将对象拷贝一份,但是此种方法需要在子类中复写clone()
4、Class类,通过Class类来实例化一个对象,通过字符串操作完成。
Class c=Class.forName(\"java.util.ArrayList\");
li=(List)c.newInstance();
关于Class类只需要重点掌握实例化对象的操作。
但是对于以下一种情况不适合
Person p=null;
P=(Person)Class.forName(“com.king.Person”).newInstance();//它是调用Person的无参构造方法
要这样:
import java.util.*;
import java.lang.reflect.*;
public class AdvDemo09
{
public static void main(String[] args) throws Exception
{
Class c=Class.forName(\"com.king.Person3\");
Constructor ct=c.getConstructors()[0];
obj[]={\"张三是个大傻瓜\"};
Person3 p=(Person3)ct.newInstance(obj);
System.out.println(p);
}
}
JAVA编的是C/S程序,程序分为两种:
基于TCP协议:Socket,可靠的服务: 如:打电话:A?B
基于UDP协议:不可靠,如:短信功能
如果要编写一个TCP程序需要JAVA的两个包支持:
● Java.net.*; 主要提供网络支持
Java.net.ServerSocket类:服务器端程序
Java.net.Socket类:客户端程序
● Java.io.*; 传递信息流
ServerSocket ss=new ServerSocket(8888);
Socket client=ss.accept();
PrintWriter pw=new PrintWriter(client.getOutputStream());
pw.write(\"你好,尊敬的客户!!\");
pw.print(\"good bye\");
pw.close();
client.close();
ss.close();
Socket client=new Socket(\"localhost\",8888);
BufferedReader bf=new BufferedReader(new InputStreamReader(client.getInputStream()));
System.out.print(bf.readLine());
bf.close();
client.close();
2、 网络上传输的程序靠的是字节流(因为长度不确定,所以最好使用BufferedReader
201.在JDK中也准备了两个专门用于实现UDP的类
■DatagramSocket
■DatagramPacket
DatagramSocket ds=new DatagramSocket(5000);
byte b[]=new byte[2048];
String str=\"你好,这里是青岛的服务器!!\";
DatagramPacket dp=new DatagramPacket(str.getBytes(),0,str.length(),InetAddress.getByName(\"localhost\"),8888);
ds.send(dp);
ds.close();
这是客户端:要先运行它,再运行服务器端!!
import java.io.*;
import java.net.*;
public class UDPClient
{
public static void main(String[] args) throws Exception
{
DatagramSocket ds=new DatagramSocket(8888);
byte b[]=new byte[1024];
DatagramPacket dp=new DatagramPacket(b,b.length);
ds.receive(dp);
String str=new String(dp.getData(),0,dp.getLength());
System.out.print(str);
ds.close();
}
}
把输入的信息发送给客户:
import java.io.*;
import java.net.*;
public class UDPServerInput
{
public static void main(String[] args) throws Exception
{
DatagramSocket ds=new DatagramSocket(5000);
byte b[]=new byte[2048];
String str=\"hello ,dimg ming yu ,you are greet!!\";
BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));
System.out.println(\"请输入要给客户的忠告:\");
str=buf.readLine();
DatagramPacket dp=new DatagramPacket(str.getBytes(),0,str.length(),InetAddress.getByName(\"localhost\"),8888);
ds.send(dp);
ds.close();
}
}
上面的程序,会出现很多空格:
import java.io.*;
import java.net.*;
public class UDPServerInput2
{
public static void main(String[] args) throws Exception
{
DatagramSocket ds=null;
DatagramPacket dp=null;
ds=new DatagramSocket(5000);
byte b[]=new byte[1024];
int len=0;
System.out.println(\"请输入要给客户的忠告:\");
len=System.in.read(b);
dp=new DatagramPacket(b,0,len,InetAddress.getByName(\"localhost\"),8888);
ds.send(dp);
ds.close();
}
}
if(b.getName().indexOf(name)!=-1)
算术移位,逻辑移位
211.在JAVA中也提供了左移<<和右移>>两种操作
左移操作是将运算数的二进制码整体左移指定位数,左移之后的空位使用0来填充
右移操作是将运算数的二进制码整体右移,右移之后空位使用符号位填充,如果是正数使用0填充,如果是负数使用1填充。
214.无符号右移>>> 它使用0来填充空位
注意:位操作实际上在基本的开发中使用较少,对于一些底层的加密,MD5
216.布尔类型不能转换成其它类型。
218.JAVA提供了数组排序功能。
java.util.Arrays.sort(age);
还提供了对数组的拷贝方法:
System.Arraycopy(s1,3,i2,1,3); //源数组,起始位置,目标数组,起始位置,拷贝长度
219.新特性
在jdk1.5之后,?可变数组
所有的可变数组接收之后都是以数组的形式保存下来的,所以直接按数组的方式接收即可。
public ststic void fun(int … arg)
{ }
public class NewDemo01
{
public static void main(String args[])
{
System.out.println(\"不传递参数:\");
fun();
System.out.println(\"传递一个参数:\");
fun(4);
System.out.println(\"传递五个参数:\");
fun(6,8,5,2,87);
}
public static void fun(int ... arg) //这就是可变参数
{
for (int i=0;i<arg.length ;i++ )
{
System.out.print(arg[i]);
}
}
}
在JDK1.5之后,提供了foreach语法。
public static void fun(int ... arg)
{
for (int i:arg) //这就是JAVA的新特性,foreach语法
{
System.out.println(i);
}
}
222.构造方法私有化
所谓的单态就是在入口处(构造方法)限制了对象的实例化操作。
int j =1234567;
String sNumber = String .valueOf(j);
System.out.println(“j是”+sNumber.length()+”位数”);//算j是几位数
String s = “Mary,F,1976”;
String sPlit[] = s.Split(“,”); //分割
for(int i=0; i<sPlit.length;i++)
{System.out.println(sPlit[i]);
226.
public class TestEnum
{
public enum MyColor { red, green,blue}; 枚举类型
public static void main(String args[])
{
MyColor m = MyColor.red; 使用枚举类型
switch(m)
{
case red:
System.out.println(“red”);
break;
case green:
System.out.println(“green”);
break;
default:
System.out.println(“default”);
}
System.out.prinln(m);
}
228.泛型
Map<String,Integer> m = new HashMap<String,Integer>(); //这是MAP的泛型,因为它是一对值
System.out.println(m.size()+m1.containsKey(“one”));
s = String.valueOf(Math.random());
230.转换流
import java.io.*;
public class TestTransForm
{
public static void main(String[] args)
{
try
{
OutputStreamWriter ose = new OutputStreamWriter(new FileOutputStream(\"d:/char.txt\"));
osw.write(\"microsoftibmsunapplehp\");
System.out.println(osw.getEncoding());
osw.close();
osw = new OutputStreamWriter(new FileOutputStream(\"d:/char.txt\",true),\"ISO8859_1\");
osw.write(\"aiorjiotairetiorewt\");
System.out.println(osw.getEncoding());
osw.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
if (s.equalsIgnoreCase(\"exit\"))
System.out.println(s.toUpperCase());
catch (IOException e)
{
e.printStackTrace();
}
232.数据流
import java.io.*;
public class TestDataStream
{
public static void main(String[] args)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
try
{
dos.writeDouble(Math.random());
dos.writeBoolean(true);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
System.out.println(bais.available()); //有多少可读的字节
DataInputStream dis = new DataInputStream(bais);
System.out.println(dis.readDouble());
System.out.println(dis.readBoolean());
dos.close();
dis.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
233.打印流
import java.io.*;
public class TestPrintStream1
{
public static void main(String[] args)
{
PrintStream ps = null;
try
{
FileOutputStream fos = new FileOutputStream(\"d:/bak/log.dat\");
ps = new PrintStream(fos);
}
catch (IOException e)
{e.printStackTrace();
}
if (ps != null)
{
System.setOut(ps); //设置往打印流中打印!
}
}
}
235.
import java.util.*;
import java.io.*;
public class TestPrintStream3
{
public static void main(String[] args)
{
String s = null;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try
{
FileWriter fw = new FileWriter(\"d:/log.log\",true); //true 是往文件是追加内容,不会覆盖以前的内容
PrintWriter pw = new PrintWriter(fw);
while ((s = br.readLine())!=null)
{
if (s.equalsIgnoreCase(\"exit\"))
{
break;
}
System.out.println(s.toUpperCase()); //这是往屏幕写
pw.println(\"-------\"); //这是往文件写
pw.println(s);
pw.flush();
}
pw.println(\"======\"+new Date()+\"=====\");
pw.flush(); //它会自动flush,但是还是写上好,习惯!
pw.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
237.要想自己控制序列化过程的话,要实现Externalizable接口,一般不用!
实现Serializable接口是JDK帮助实现序列化的!
245.wait与sleep的区别
wait是 类中的方法,sleep 是Thtread类中的方法
wait时别的线程可以访问锁定对象,sleep时别的线程也不可以访问锁定对象。
246.notify叫醒wait在某个对象上的线程
247.TCP端口 UDP端口是分开的,每一个有65536个端口
Socket s = new Socket(\"127.0.0.1\",8888);
InputStream is = s.getInputStream();
OutputStream os = s.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
DataInputStream dis = new DataInputStream(is);
System.out.println(\"client:\"+dis.readUTF());
dos.writeUTF(\"hello,server,I am client\");
Socket s = ss.accept();
dos.writeUTF(\"hello,rookey:\"+s.getInetAddress()+\"port:\"+s.getPort());
253.传一个Long类型的数
服务器端
import java.net.*;
import java.io.*;
public class UDPServer
{
public static void main(String[] args) throws Exception
{
byte b[] = new byte[1024];
DatagramSocket ds = new DatagramSocket(9999);
DatagramPacket dp = new DatagramPacket(b,b.length);
while (true)
{
ds.receive(dp);
ByteArrayInputStream bais = new ByteArrayInputStream(b,0,b.length);
DataInputStream dis = new DataInputStream(bais);
System.out.println(dis.readLong());
}
}
}
客户端
import java.net.*;
import java.io.*;
public class UDPClient
{
public
继续阅读与本文标签相同的文章
-
望闻问切,用好人工智能
2026-05-19栏目: 教程
-
数字时代如何保护个人信息
2026-05-19栏目: 教程
-
SPAR国际物流峰会在威海召开
2026-05-19栏目: 教程
-
NewBalance新款3D打印运动鞋 改变前掌中底
2026-05-19栏目: 教程
-
简易区分物联网和互联网
2026-05-19栏目: 教程
