当前位置: 首页 > news >正文

广东网站建站公司莫停之科技windows优化大师

广东网站建站公司,莫停之科技windows优化大师,dw设计个人网页,怎么给网站添加统计代码Java的反射机制、Lambda表达式和枚举 文章目录 Java的反射机制、Lambda表达式和枚举1.反射机制反射的概念、用途、优缺点反射相关的类及使用(重要!!)相关类Class类:代表类实体,表示类和接口Field类&#xf…

Java的反射机制、Lambda表达式和枚举

文章目录

  • Java的反射机制、Lambda表达式和枚举
    • 1.反射机制
      • 反射的概念、用途、优缺点
      • 反射相关的类及使用(重要!!)
        • 相关类
          • Class类:代表类实体,表示类和接口
          • Field类:代表类的成员变量/类的属性
          • Method类:代表类的方法
          • Constructor类:代表类的构造方法
          • 获取类中注解相关的方法(了解)
        • 使用
          • 获取Class对象的三种方式
          • 例子
            • 通过反射创建对象
            • 反射私有构造方法创建对象
            • 反射私有属性
            • 反射私有方法
    • 2.Lambda表达式
      • Lambda是什么、语法
      • 基本使用
      • 用途1:变量捕获
        • 匿名内部类变量捕获
        • Lambda表达式变量捕获
      • 用途2:在集合中的使用
        • Collection接口
        • List接口
        • Map接口
    • 3.枚举
      • 枚举简介、优缺点
      • 枚举的构造方法
      • 创建与使用
      • 枚举与反射

1.反射机制

反射的概念、用途、优缺点

Java的反射机制就是在运行状态中,对于任意一个类都能知道它所有属性和方法,对于任意一个对象都能调用它的任意方法和属性,并进行部分类型信息的修改,这种动态获取信息以及动态调用对象方法的功能叫做Java的反射机制

Java程序中很多对象在运行时会出现两种基本类型:运行时类型(RTTI)和编译时类型。

例如Person p=new Student(),这句代码中p在编译时就是Person,运行时就是Student,程序需要再运行时发现对象和类的真实信息,通过反射就可以判断出这个对象和类属于哪些类。

  1. 在日常的第三方应用开发过程中,可以利用Java的反射机制通过反射来获取所需要的私有成员或者方法(比较常见)

  2. 最重要的用途就是开发各种框架。

    例如,在spring中,我们把所有的类Bean交给spring容器管理,不管是xml配置还是注解配置Bean,当我们从容器中获取Bean来依赖注入时,容器就读取配置,而配置中给的就是类的信息,spring根据这些信息,动态的创建Bean

优点:

  1. 对于任意类都能知道它的属性和方法,对于任意对象都能调用它的任意方法
  2. 可以增加程序的灵活性和扩展性
  3. 已经运用在很多流行的框架如spring中

缺点:

  1. 会有效率问题,导致程序效率降低
  2. 代码可能比较复杂

反射相关的类及使用(重要!!)

在Java中,实现反射都要依赖于Class类。

这是因为,Java文件被编译后,生成.class文件,JVM需要去解读.class文件,被编译后的Java文件.class也被JVM解析成一个对象,这个对象就是java.lang.Class。

这样当程序运行时,每个Java文件最终都变成了Class类对象的一个实例。

因此,将反射机制应用到这个实例上时,就可以获取或添加改变这个类的属性和方法时,这个类就会成为一个动态的类。

注意:所有和反射相关的包都在 import java.lang.reflect 包下面

相关类

所有的这些类都是加了declared能够访问的范围是更大的。

Class类:代表类实体,表示类和接口
方法用途
getClassLoader()获取类的加载器
getDeclaredClasser()返回一个数组,数组中包含这个类中所有的类和接口类的对象
forName(String className)根据类名返回类的对象
newInstance创建类的实例
getName()获取类的完整路径名字
Field类:代表类的成员变量/类的属性
方法用途
getField(String name)获取某个公有的属性对象
getFields()获取所有公有的属性对象
getDeclaredField(String name)获取某个属性对象
getDeclaredFields()获取所有属性对象
Method类:代表类的方法
方法用途
getMethod(String name,Class…<?> parameterTypes)获取该类某个公有的方法
getMethods()获取该类所有公有的方法
getDeclaredMethod(String name,Class…<?> parameterTypes)获取该类某个方法
getDeclaredMethods()获取该类所有方法
Constructor类:代表类的构造方法
方法用途
getConstructor(Class…<?> parameterTypes)获取该类中与参数类型匹配的公有构造方法
getConstructors()获取该类中所有公有构造方法
getDeclaredConstructor(Class…<?> parameterTypes)获取该类中与参数类型匹配的构造方法
getDeclaredConstructors()获取该类所有构造方法
获取类中注解相关的方法(了解)
方法用途
getAnnotation(Class annotationClass)返回该类中与参数类型匹配的公有注解对象
getAnnotations()返回该类中所有公有注解对象
getDeclaredAnnotation(Class annotationClass)返回该类中与参数类型匹配的所有注解对象
getDeclaredAnnotations()返回该类中所有的注解对象

使用

在进行反射之前,需要做的第一步就是拿到当前需要反射的类的Class对象,然后根据Class对象的核心方法,达到反射的目的(获取或修改相关信息)。

获取Class对象的三种方式

第一种:使用Class.forName(“类的全路径名”);【使用的比较多的】

第二种:使用.class方法(适合在编译时就已经明确要操作的Class)

第三种:使用类对象的getClass()方法

class Student{//私有属性nameprivate String name = "school";//公有属性agepublic int age = 18;//不带参数的构造public Student(){System.out.println("Student()");}//私有带参构造private Student(String name,int age) {this.name = name;this.age = age;System.out.println("Student(String,name)");}//私有不带参private void eat(){System.out.println("i am eating");}//公开不带参public void sleep(){System.out.println("i am sleeping");}//私有带参private void function(String str) {System.out.println(str);}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
public class Reflect {public static void main(String[] args) throws ClassNotFoundException {Student student=new Student();//获取Class对象的三种方法//1.通过getClass方法Class<?> c1=student.getClass();//2.通过类名.class获取Class<?> c2=Student.class;//3.通过Class.forName(全路径)[需要处理异常——自己处理or交给JVM处理]Class<?> c3=Class.forName("Student");//在当前类System.out.println(c1.equals(c2));System.out.println(c1.equals(c3));System.out.println(c3.equals(c2));}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L1k8pGSJ-1692022990152)(F:\typora插图\image-20230814163231771.png)]

例子
通过反射创建对象
    public static void reflectNewInstance() throws ClassNotFoundException, InstantiationException, IllegalAccessException {Class<?> c3 = Class.forName("Student");Student student = (Student) c3.newInstance();System.out.println(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {//通过反射创建对象reflectNewInstance();}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5bQEkcyf-1692022990153)(F:\typora插图\image-20230814185543613.png)]

反射私有构造方法创建对象
    //反射私有的构造方法public static void reflectPrivateConstructor() {try {Class<?> c3=Class.forName("Student");Constructor<?> constructor=c3.getDeclaredConstructor(String.class,int.class);//设置为true之后可以修改访问权限constructor.setAccessible(true);Student student=(Student) constructor.newInstance("zhangsan",17);System.out.println(student);} catch (ClassNotFoundException e) {throw new RuntimeException(e);} catch (NoSuchMethodException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (InvocationTargetException e) {throw new RuntimeException(e);}}//反射私有属性public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {//通过反射创建对象
//        reflectNewInstance();//通过反射得到私有构造方法创建对象reflectPrivateConstructor();}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VPH9W8nv-1692022990153)(F:\typora插图\image-20230814185524760.png)]

反射私有属性
    //反射私有属性public static void reflectPrivateField(){try {Class<?> c3=Class.forName("Student");Field field=c3.getDeclaredField("name");field.setAccessible(true);//修改属性的访问权限Object objectStudent=c3.newInstance();Student student=(Student)objectStudent;field.set(student,"张三");String name=(String)field.get(student);System.out.println("反射私有属性修改名字为:"+name);} catch (ClassNotFoundException e) {throw new RuntimeException(e);} catch (NoSuchFieldException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);}}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {//通过反射创建对象
//        reflectNewInstance();//通过反射得到私有构造方法创建对象
//        reflectPrivateConstructor();//反射私有属性reflectPrivateField();}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y0bNue4Y-1692022990154)(F:\typora插图\image-20230814185447879.png)]

反射私有方法
    //反射私有方法public static void reflectPrivateMethod(){try {Class<?> c3=Class.forName("Student");Method method= c3.getDeclaredMethod("function",String.class);method.setAccessible(true);Object object=c3.newInstance();Student student=(Student) object;method.invoke(student,"给私有function函数传的参数");} catch (ClassNotFoundException e) {throw new RuntimeException(e);} catch (NoSuchMethodException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (InvocationTargetException e) {throw new RuntimeException(e);}}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {//通过反射创建对象
//        reflectNewInstance();//通过反射得到私有构造方法创建对象
//        reflectPrivateConstructor();//反射私有属性
//        reflectPrivateField();//反射私有方法reflectPrivateMethod();}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bEQRVbm2-1692022990155)(F:\typora插图\image-20230814185425769.png)]

2.Lambda表达式

相当于只有一个抽象方法的接口的简化。

Lambda是什么、语法

它是JavaSE8中的一个新的特性,Lambda表达式允许我们通过表达式代替功能接口。Lambda 表达式(Lambda expression),基于数学中的λ演算得名,也可称为闭包(Closure)。

基本语法: **(parameters) -> expression****(parameters) ->{ statements; }**

parameters:就是函数式接口里的形参列表。这里的参数类型可以明确的生命也可以由JVM隐含判断。当只有一个推断类型时可以省略圆括号。

->:被用于的意思

方法体:可以是表达式也可以是代码块,是函数式接口方法的实现,可返回可不返回

// 1. 不需要参数,返回值为 2
() -> 2
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的和
(x, y) -> x + y
// 4. 接收2个int型整数,返回他们的乘积
(int x, int y) -> x * y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)

函数式接口:一个接口有且只有一个抽象方法

如果我们在某个接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接口,这样如果有两个抽象方法,程序编译就会报错的。

定义方法:

@FunctionalInterface
interface NoParameterNoReturn {//注意:只能有一个方法void test();
}
@FunctionalInterface
interface NoParameterNoReturn {void test();default void test2() {System.out.println("JDK1.8新特性,default默认方法可以有具体的实现");}
}

基本使用

@FunctionalInterface
interface NoParameterNoReturn{void test();
}
@FunctionalInterface
interface OneParameterNoReturn{void test(int a);
}
@FunctionalInterface
interface MoreParameterNoReturn{void test(int a,int b);
}
@FunctionalInterface
interface NoParameterReturn{int test();
}
@FunctionalInterface
interface OneParameterReturn{int test(int a);
}
@FunctionalInterface
interface MoreParameterReturn{int test(int a,int b);
}
public class LambdaDemo {public static void main(String[] args) {//匿名内部类,重写了实现接口的方法NoParameterNoReturn noParameterNoReturn=new NoParameterNoReturn(){@Overridepublic void test() {System.out.println("无参无返回值");}};noParameterNoReturn.test();NoParameterNoReturn noParameterNoReturn1=()->{System.out.println("L:无参无返回值");};noParameterNoReturn1.test();OneParameterNoReturn oneParameterNoReturn=new OneParameterNoReturn() {@Overridepublic void test(int a) {System.out.println("一参无返回值");}};oneParameterNoReturn.test(1);OneParameterNoReturn oneParameterNoReturn1= (x)->{System.out.println("L:一参无返回值");};oneParameterNoReturn1.test(1);MoreParameterNoReturn moreParameterNoReturn=new MoreParameterNoReturn() {@Overridepublic void test(int a,int b) {System.out.println("多参无返回值");}};moreParameterNoReturn.test(1,2);MoreParameterNoReturn moreParameterNoReturn1=(x,y)->{System.out.println("L:多参无返回值");};moreParameterNoReturn1.test(1,2);//匿名内部类,重写了实现接口的方法NoParameterReturn noParameterReturn=new NoParameterReturn(){@Overridepublic int test() {System.out.println("无参有返回值");return 0;}};noParameterReturn.test();NoParameterReturn noParameterReturn1=()->{System.out.println("L:无参有返回值");return 0;};noParameterNoReturn1.test();OneParameterReturn oneParameterReturn=new OneParameterReturn() {@Overridepublic int test(int a) {System.out.println("一参有返回值");return 0;}};oneParameterNoReturn.test(1);OneParameterReturn oneParameterReturn1= (x)->{System.out.println("L:一参有返回值");return x;};oneParameterNoReturn1.test(1);MoreParameterReturn moreParameterReturn=new MoreParameterReturn() {@Overridepublic int test(int a,int b) {System.out.println("多参有返回值");return a+b;}};moreParameterReturn.test(1,2);MoreParameterReturn moreParameterReturn1=(x,y)->{System.out.println("L:多参有返回值");return x+y;};moreParameterNoReturn1.test(1,2);}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MamGMkbA-1692022990156)(F:\typora插图\image-20230814211545477.png)]

用途1:变量捕获

变量捕获可以使我们更好的理解Lambda表达式的作用域,Java中的匿名内部类和Lambda表达式会存在变量捕获。

匿名内部类变量捕获

@FunctionalInterface
interface Test{void test();
}
public class LambdaDemo2 {//匿名内部类变量捕获public static void test01() {int a=100;final int b=10;
//        int c=100;
//        c=20;Test t=new Test(){@Overridepublic void test() {System.out.println("匿名内部类的变量捕获:(常量或者没有被改变过值的变量)"+a);System.out.println("匿名内部类的变量捕获:(常量或者没有被改变过值的变量)"+b);
//                System.out.println("匿名内部类的变量捕获:(常量或者没有被改变过值的变量)"+c);}};t.test();}public static void main(String[] args) {test01();}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qf6me7pW-1692022990156)(F:\typora插图\image-20230814212621312.png)]

可以被捕获的只能是常量或者没有被修改过的常量,否则就会直接报错:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YbB6npMV-1692022990157)(F:\typora插图\image-20230814212507835.png)]

Lambda表达式变量捕获

@FunctionalInterface
interface Test{void test();
}
public class LambdaDemo2 {//匿名内部类变量捕获public static void test01() {int a=100;final int b=10;
//        int c=100;
//        c=20;Test t=new Test(){@Overridepublic void test() {System.out.println("匿名内部类的变量捕获:(常量或者没有被改变过值的变量)"+a);System.out.println("匿名内部类的变量捕获:(常量或者没有被改变过值的变量)"+b);
//                System.out.println("匿名内部类的变量捕获:(常量或者没有被改变过值的变量)"+c);}};t.test();}//Lambda表达式的变量捕获public static void test02() {int a=100;final int b=10;Test t=()->{System.out.println("L的变量捕获:(常量或者没有被改变过值的变量)"+a);System.out.println("L的变量捕获:(常量或者没有被改变过值的变量)"+b);};t.test();}public static void main(String[] args) {
//        test01();test02();}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A25c1hwX-1692022990158)(F:\typora插图\image-20230814213242215.png)]

用途2:在集合中的使用

Collection接口

以实现Collection接口方法(实现了Iterable接口)的forEach方法为例

import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Consumer;public class LambdaDemo3 {public static void main(String[] args) {ArrayList<Integer> list=new ArrayList<>();list.add(1);list.add(19);list.add(17);list.add(16);list.add(12);list.add(12);//使用foreach迭代器System.out.println("迭代器:");for (int x:list) {System.out.print(x+" ");}System.out.println();//使用匿名内部类方式System.out.println("匿名内部类:");list.forEach(new Consumer<Integer>() {@Overridepublic void accept(Integer integer) {System.out.print(integer+" ");}});System.out.println();System.out.println("Lambda表达式:");//使用Lambda表达式方式list.forEach((i)->{System.out.print(i+" ");});}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BB0YzdBe-1692022990158)(F:\typora插图\image-20230814214622693.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3maQJlms-1692022990159)(F:\typora插图\image-20230814220253812.png)]

List接口

以sort方法为例:

//sort方法
list.sort((a,b)->{return b-a;});//修改排序规则为降序排序
System.out.println(list);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GdbrR2ok-1692022990159)(F:\typora插图\image-20230814222111073.png)]

Map接口

import java.util.HashMap;
import java.util.function.BiConsumer;public class LambdaDemo4 {public static void main(String[] args) {//Map接口的forEach方法HashMap<Integer,String> map=new HashMap<>();map.put(1,"张三");map.put(2,"李四");map.put(3,"王五");//匿名内部类map.forEach(new BiConsumer<Integer, String>() {@Overridepublic void accept(Integer integer, String s) {System.out.println(integer+":"+s);}});//Lambda表达式map.forEach((integer,s)->{System.out.println("L:"+integer+":"+s);});}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n4pi9BTf-1692022990160)(F:\typora插图\image-20230814221619947.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TOH0EkpR-1692022990160)(F:\typora插图\image-20230814222003571.png)]

3.枚举

枚举简介、优缺点

它是在JDK1.5之后引入的,主要用来将常量组织起来。通常应用在错误状态码,消息类型,颜色划分和状态机上等等。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5cmNChqD-1692022990160)(F:\typora插图\image-20230814190715860.png)]

定义好的是枚举对象。

枚举类型实际上是 java.lang.Enum 的子类,也就是说,自己写的枚举类,就算没有显示的继承 Enum ,但是其默认继承了这个类。

优点:

  1. 枚举常量更安全简单
  2. 枚举具有内置方法,更优雅

缺点:

  1. 没法继承,不能被实例化【原因就是它构造方法是私有的】,不可扩展

枚举的构造方法

默认是私有的,也只能是私有的,不能被继承,并且只能在定义枚举对象的时候被调用。

public enum TestEnum {RED,BLACK,WHITE,BLUE("BLUE",4),PINK;TestEnum(){}private String color;private int ri;TestEnum(String color,int ri){this.color=color;this.ri=ri;}
}

创建与使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VlSmSsUO-1692022990161)(F:\typora插图\image-20230814191135595.png)]

public enum TestEnum {RED,BLACK,WHITE;public static void main(String[] args) {test01();test02();test03();}//测试枚举的switch用法public static void test01() {TestEnum testEnum = TestEnum.BLACK;switch(testEnum){case RED:System.out.println("red");break;case BLACK:System.out.println("black");break;case WHITE:System.out.println("white");break;default:System.out.println("没有当前颜色");break;}}//以数组形式返回枚举类型的所有成员public static void test02() {TestEnum[] testEnum=TestEnum.values();for (int i = 0; i < testEnum.length; i++) {System.out.println("testEnum[i]:"+testEnum[i]);}}public static void test03(){//将普通字符串转换成枚举实例
//        TestEnum testEnum=TestEnum.valueOf("GREEN");//需要是已经定义的,否则报错 No enum constant TestEnum.GREENTestEnum testEnum=TestEnum.valueOf("RED");System.out.println(testEnum);//获取枚举成员的索引位置int index=TestEnum.BLACK.ordinal();System.out.println("BLACK:"+index);//比较两个枚举成员在定义时的顺序,默认拿序号比较System.out.println(BLACK.compareTo(RED));}}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O9jTvwqk-1692022990161)(F:\typora插图\image-20230814193300309.png)]

枚举与反射

能不能通过反射创建枚举实例?

不能!!看源码分析:

    //反射枚举 私有的构造方法public static void reflectEnumPrivateConstructor() throws Exception {Class<?> c3=Class.forName("TestEnum");Constructor<?> constructor=c3.getDeclaredConstructor(String.class,int.class);//设置为true之后可以修改访问权限constructor.setAccessible(true);TestEnum testEnum=(TestEnum) constructor.newInstance("GREY",10);System.out.println(testEnum);}public static void main(String[] args) throws Exception {//通过反射创建对象
//        reflectNewInstance();//通过反射得到私有构造方法创建对象
//        reflectPrivateConstructor();//反射私有属性
//        reflectPrivateField();//反射私有方法
//        reflectPrivateMethod();//反射枚举类型私有方法reflectEnumPrivateConstructor();}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sGdNuURh-1692022990162)(F:\typora插图\image-20230814195547404.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JeoUgxSk-1692022990162)(F:\typora插图\image-20230814203135715.png)]

通过查看源码我们发现,枚举在这里被过滤了。

总的来说,因为枚举的构造方法是私有的,所以不能实例化,另外反射拿到的类对象再去new实例的时候会因为枚举类型被过滤掉,所以枚举实现的单例模式是安全的。

所以枚举具有构造方法默认是私有的,并且都是默认继承java.lang.Enum这个类,可以避免反射和序列化问题,枚举常量更安全更简单,代码更加优雅。

http://www.dt0577.cn/news/13433.html

相关文章:

  • 美国搜索网站建设广州今日新闻最新消息
  • 网站需要几个人设计公司网站
  • 免费做团购网站的软件有哪些免费关键词搜索引擎工具
  • 同ip网站做友链厦门seo培训
  • 宁德住房和城乡建设部网站百度账号怎么改名字
  • 宁津华企动力做网站的电话多少网络营销与直播电商专业介绍
  • 韩都衣舍网站建设百度收录申请
  • 石家庄网站建设多少钱好口碑关键词优化
  • 网站开发行业工作交接交接哪些代做seo关键词排名
  • 宁夏建设工程质量网站网络推广软件有哪些
  • 网站建设应注重实用性辽宁seo推广
  • 建设一个网站需要哪些材料我国的网络营销公司
  • 营销型网站建设概述中国搜索引擎排名2021
  • 新闻大全抖音seo推广
  • wordpress更换主题影响北京关键词seo
  • 快速建网站模板营销案例
  • 外贸可以什么网站做宁波seo软件免费课程
  • 做网站社区赚钱吗互联网营销工具
  • 邯郸最新工程项目公示张家界百度seo
  • 网站源码程序下载seo网站优化价格
  • 哪个网站有利于做课件网站seo优化服务商
  • php动态网站开发 项目教程百度官网下载安装到桌面上
  • 柳城网站建设搜索关键词的方法
  • 自己的网站怎么做实时监控营销网课
  • 网站建立网络优化搜索引擎优化实训心得
  • 建设网站可选择的方案有友情链接在线观看
  • dw自己做网站需要什么区别seo优化是做什么的
  • 京东网站建设策略seo免费资源大全
  • 电商平台网站建设网站建设首页
  • 网络网站建设价格网络推广代理平台